Try your search with a different keyword or use * as a wildcard.
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping;
using Nop.Data;
using Nop.Services.Shipping.Pickup;
using Nop.Services.Shipping.Tracking;
namespace Nop.Services.Shipping;
///
/// Shipment service
///
public partial class ShipmentService : IShipmentService
{
#region Fields
protected readonly IPickupPluginManager _pickupPluginManager;
protected readonly IRepository _addressRepository;
protected readonly IRepository _orderRepository;
protected readonly IRepository _orderItemRepository;
protected readonly IRepository _productRepository;
protected readonly IRepository _shipmentRepository;
protected readonly IRepository _siRepository;
protected readonly IShippingPluginManager _shippingPluginManager;
#endregion
#region Ctor
public ShipmentService(IPickupPluginManager pickupPluginManager,
IRepository addressRepository,
IRepository orderRepository,
IRepository orderItemRepository,
IRepository productRepository,
IRepository shipmentRepository,
IRepository siRepository,
IShippingPluginManager shippingPluginManager)
{
_pickupPluginManager = pickupPluginManager;
_addressRepository = addressRepository;
_orderRepository = orderRepository;
_orderItemRepository = orderItemRepository;
_productRepository = productRepository;
_shipmentRepository = shipmentRepository;
_siRepository = siRepository;
_shippingPluginManager = shippingPluginManager;
}
#endregion
#region Methods
///
/// Deletes a shipment
///
/// Shipment
/// A task that represents the asynchronous operation
public virtual async Task DeleteShipmentAsync(Shipment shipment)
{
await _shipmentRepository.DeleteAsync(shipment);
}
///
/// Search shipments
///
/// Vendor identifier; 0 to load all records
/// Warehouse identifier, only shipments with products from a specified warehouse will be loaded; 0 to load all orders
/// Shipping country identifier; 0 to load all records
/// Shipping state identifier; 0 to load all records
/// Shipping county; null to load all records
/// Shipping city; null to load all records
/// Search by tracking number
/// A value indicating whether we should load only not shipped shipments
/// A value indicating whether we should load only not ready for pickup shipments
/// A value indicating whether we should load only not delivered shipments
/// Order identifier; 0 to load all records
/// Created date from (UTC); null to load all records
/// Created date to (UTC); null to load all records
/// Page index
/// Page size
///
/// A task that represents the asynchronous operation
/// The task result contains the shipments
///
public virtual async Task> GetAllShipmentsAsync(int vendorId = 0, int warehouseId = 0,
int shippingCountryId = 0,
int shippingStateId = 0,
string shippingCounty = null,
string shippingCity = null,
string trackingNumber = null,
bool loadNotShipped = false,
bool loadNotReadyForPickup = false,
bool loadNotDelivered = false,
int orderId = 0,
DateTime? createdFromUtc = null, DateTime? createdToUtc = null,
int pageIndex = 0, int pageSize = int.MaxValue)
{
var shipments = await _shipmentRepository.GetAllPagedAsync(query =>
{
if (orderId > 0)
query = query.Where(o => o.OrderId == orderId);
if (!string.IsNullOrEmpty(trackingNumber))
query = query.Where(s => s.TrackingNumber.Contains(trackingNumber));
if (shippingCountryId > 0)
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where _addressRepository.Table.Any(a =>
a.Id == (o.PickupInStore ? o.PickupAddressId : o.ShippingAddressId) &&
a.CountryId == shippingCountryId)
select s;
if (shippingStateId > 0)
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where _addressRepository.Table.Any(a =>
a.Id == (o.PickupInStore ? o.PickupAddressId : o.ShippingAddressId) &&
a.StateProvinceId == shippingStateId)
select s;
if (!string.IsNullOrWhiteSpace(shippingCounty))
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where _addressRepository.Table.Any(a =>
a.Id == (o.PickupInStore ? o.PickupAddressId : o.ShippingAddressId) &&
a.County.Contains(shippingCounty))
select s;
if (!string.IsNullOrWhiteSpace(shippingCity))
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where _addressRepository.Table.Any(a =>
a.Id == (o.PickupInStore ? o.PickupAddressId : o.ShippingAddressId) &&
a.City.Contains(shippingCity))
select s;
if (loadNotShipped)
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where !s.ShippedDateUtc.HasValue && !o.PickupInStore
select s;
if (loadNotReadyForPickup)
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where !s.ReadyForPickupDateUtc.HasValue && o.PickupInStore
select s;
if (loadNotDelivered)
query = query.Where(s => !s.DeliveryDateUtc.HasValue);
if (createdFromUtc.HasValue)
query = query.Where(s => createdFromUtc.Value <= s.CreatedOnUtc);
if (createdToUtc.HasValue)
query = query.Where(s => createdToUtc.Value >= s.CreatedOnUtc);
query = from s in query
join o in _orderRepository.Table on s.OrderId equals o.Id
where !o.Deleted
select s;
query = query.Distinct();
if (vendorId > 0)
{
var queryVendorOrderItems = from orderItem in _orderItemRepository.Table
join p in _productRepository.Table on orderItem.ProductId equals p.Id
where p.VendorId == vendorId
select orderItem.Id;
query = from s in query
join si in _siRepository.Table on s.Id equals si.ShipmentId
where queryVendorOrderItems.Contains(si.OrderItemId)
select s;
query = query.Distinct();
}
if (warehouseId > 0)
{
query = from s in query
join si in _siRepository.Table on s.Id equals si.ShipmentId
where si.WarehouseId == warehouseId
select s;
query = query.Distinct();
}
query = query.OrderByDescending(s => s.CreatedOnUtc);
return query;
}, pageIndex, pageSize);
return shipments;
}
///
/// Get shipment by identifiers
///
/// Shipment identifiers
///
/// A task that represents the asynchronous operation
/// The task result contains the shipments
///
public virtual async Task> GetShipmentsByIdsAsync(int[] shipmentIds)
{
return await _shipmentRepository.GetByIdsAsync(shipmentIds);
}
///
/// Gets a shipment
///
/// Shipment identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the shipment
///
public virtual async Task GetShipmentByIdAsync(int shipmentId)
{
return await _shipmentRepository.GetByIdAsync(shipmentId, cache => default, useShortTermCache: true);
}
///
/// Gets a list of order shipments
///
/// Order identifier
/// A value indicating whether to count only shipped or not shipped shipments; pass null to ignore
/// A value indicating whether to load only ready for pickup shipments; pass null to ignore
/// Vendor identifier; pass 0 to ignore
///
/// A task that represents the asynchronous operation
/// The task result contains the result
///
public virtual async Task> GetShipmentsByOrderIdAsync(int orderId, bool? shipped = null, bool? readyForPickup = null, int vendorId = 0)
{
if (orderId == 0)
return new List();
var shipments = _shipmentRepository.Table;
if (shipped.HasValue)
shipments = shipments.Where(s => s.ShippedDateUtc.HasValue == shipped);
if (readyForPickup.HasValue)
shipments = shipments.Where(s => s.ReadyForPickupDateUtc.HasValue == readyForPickup);
return await shipments.Where(shipment => shipment.OrderId == orderId).ToListAsync();
}
///
/// Inserts a shipment
///
/// Shipment
/// A task that represents the asynchronous operation
public virtual async Task InsertShipmentAsync(Shipment shipment)
{
await _shipmentRepository.InsertAsync(shipment);
}
///
/// Updates the shipment
///
/// Shipment
/// A task that represents the asynchronous operation
public virtual async Task UpdateShipmentAsync(Shipment shipment)
{
await _shipmentRepository.UpdateAsync(shipment);
}
///
/// Gets a shipment items of shipment
///
/// Shipment identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the shipment items
///
public virtual async Task> GetShipmentItemsByShipmentIdAsync(int shipmentId)
{
if (shipmentId == 0)
return null;
return await _siRepository.Table.Where(si => si.ShipmentId == shipmentId).ToListAsync();
}
///
/// Inserts a shipment item
///
/// Shipment item
/// A task that represents the asynchronous operation
public virtual async Task InsertShipmentItemAsync(ShipmentItem shipmentItem)
{
await _siRepository.InsertAsync(shipmentItem);
}
///
/// Deletes a shipment item
///
/// Shipment Item
/// A task that represents the asynchronous operation
public virtual async Task DeleteShipmentItemAsync(ShipmentItem shipmentItem)
{
await _siRepository.DeleteAsync(shipmentItem);
}
///
/// Updates a shipment item
///
/// Shipment item
/// A task that represents the asynchronous operation
public virtual async Task UpdateShipmentItemAsync(ShipmentItem shipmentItem)
{
await _siRepository.UpdateAsync(shipmentItem);
}
///
/// Gets a shipment item
///
/// Shipment item identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the shipment item
///
public virtual async Task GetShipmentItemByIdAsync(int shipmentItemId)
{
return await _siRepository.GetByIdAsync(shipmentItemId, cache => default, useShortTermCache: true);
}
///
/// Get quantity in shipments. For example, get planned quantity to be shipped
///
/// Product
/// Warehouse identifier
/// Ignore already shipped shipments
/// Ignore already delivered shipments
///
/// A task that represents the asynchronous operation
/// The task result contains the quantity
///
public virtual async Task GetQuantityInShipmentsAsync(Product product, int warehouseId,
bool ignoreShipped, bool ignoreDelivered)
{
ArgumentNullException.ThrowIfNull(product);
//only products with "use multiple warehouses" are handled this way
if (product.ManageInventoryMethod != ManageInventoryMethod.ManageStock)
return 0;
if (!product.UseMultipleWarehouses)
return 0;
const int cancelledOrderStatusId = (int)OrderStatus.Cancelled;
var query = _siRepository.Table;
query = from si in query
join s in _shipmentRepository.Table on si.ShipmentId equals s.Id
join o in _orderRepository.Table on s.OrderId equals o.Id
where !o.Deleted && o.OrderStatusId != cancelledOrderStatusId
select si;
query = query.Distinct();
if (warehouseId > 0)
query = query.Where(si => si.WarehouseId == warehouseId);
if (ignoreShipped)
{
query = from si in query
join s in _shipmentRepository.Table on si.ShipmentId equals s.Id
where !s.ShippedDateUtc.HasValue
select si;
}
if (ignoreDelivered)
{
query = from si in query
join s in _shipmentRepository.Table on si.ShipmentId equals s.Id
where !s.DeliveryDateUtc.HasValue
select si;
}
var queryProductOrderItems = from orderItem in _orderItemRepository.Table
where orderItem.ProductId == product.Id
select orderItem.Id;
query = from si in query
where queryProductOrderItems.Any(orderItemId => orderItemId == si.OrderItemId)
select si;
//some null validation
var result = Convert.ToInt32(await query.SumAsync(si => (int?)si.Quantity));
return result;
}
///
/// Get the tracker of the shipment
///
/// Shipment
///
/// A task that represents the asynchronous operation
/// The task result contains the shipment tracker
///
public virtual async Task GetShipmentTrackerAsync(Shipment shipment)
{
var order = await _orderRepository.GetByIdAsync(shipment.OrderId, cache => default, useShortTermCache: true);
IShipmentTracker shipmentTracker = null;
if (order.PickupInStore)
{
var pickupPointProvider = await _pickupPluginManager
.LoadPluginBySystemNameAsync(order.ShippingRateComputationMethodSystemName);
if (pickupPointProvider != null)
shipmentTracker = await pickupPointProvider.GetShipmentTrackerAsync();
}
else
{
var shippingRateComputationMethod = await _shippingPluginManager
.LoadPluginBySystemNameAsync(order.ShippingRateComputationMethodSystemName);
if (shippingRateComputationMethod != null)
shipmentTracker = await shippingRateComputationMethod.GetShipmentTrackerAsync();
}
return shipmentTracker;
}
#endregion
}