|
@@ -84,16 +84,18 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
var locationid = entity.StockLocation.ID;
|
|
|
var locationValid = entity.StockLocation.IsValid();
|
|
|
|
|
|
- var jriTask = Task<Guid>.Run(() =>
|
|
|
+ var poiaTask = Task.Run(() =>
|
|
|
{
|
|
|
return Provider.Query(
|
|
|
new Filter<PurchaseOrderItemAllocation>(x => x.Item.ID).IsEqualTo(entity.ID),
|
|
|
- Columns.Required<PurchaseOrderItemAllocation>()
|
|
|
- )
|
|
|
- .ToObjects<JobRequisitionItem>();
|
|
|
+ Columns.None<PurchaseOrderItemAllocation>()
|
|
|
+ .Add(x => x.ID)
|
|
|
+ .Add(x => x.JobRequisitionItem.ID)
|
|
|
+ .Add(x => x.JobRequisitionItem.Cancelled))
|
|
|
+ .ToArray<PurchaseOrderItemAllocation>();
|
|
|
});
|
|
|
|
|
|
- var consigntask = Task<double>.Run(() =>
|
|
|
+ var consigntask = Task.Run(() =>
|
|
|
{
|
|
|
if (entity.Consignment.ID != Guid.Empty && !entity.Consignment.ExTax.IsEffectivelyEqual(0.0))
|
|
|
{
|
|
@@ -101,102 +103,56 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
new Filter<PurchaseOrderItem>(x => x.Consignment.ID).IsEqualTo(entity.Consignment.ID),
|
|
|
Columns.None<PurchaseOrderItem>().Add(x => x.ExTax)
|
|
|
).Rows.Select(r => r.Get<PurchaseOrderItem, double>(c => c.ExTax));
|
|
|
- return values.Sum(x => x);
|
|
|
+ return values.Sum();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return 0.0;
|
|
|
}
|
|
|
-
|
|
|
- return 0.0;
|
|
|
});
|
|
|
|
|
|
- var instancetask = new Task<CoreRow?>(() =>
|
|
|
+ var instancetask = Task.Run(() =>
|
|
|
{
|
|
|
return Provider.Query(
|
|
|
new Filter<ProductInstance>(x => x.Product.ID).IsEqualTo(entity.Product.ID)
|
|
|
- .And(x=>x.Style.ID).IsEqualTo(entity.Style.ID)
|
|
|
+ .And(x => x.Style.ID).IsEqualTo(entity.Style.ID)
|
|
|
.And(x => x.Dimensions).DimensionEquals(entity.Dimensions),
|
|
|
- Columns.Required<ProductInstance>().Add(
|
|
|
- x => x.ID,
|
|
|
- x => x.Product.NonStock,
|
|
|
- x => x.Product.DefaultLocation.ID,
|
|
|
- x => x.Product.Warehouse.ID,
|
|
|
- x => x.Dimensions.Unit.ID,
|
|
|
- x => x.Dimensions.Unit.Formula,
|
|
|
- x => x.Dimensions.Unit.Format,
|
|
|
- x => x.Dimensions.Quantity,
|
|
|
- x => x.Dimensions.Length,
|
|
|
- x => x.Dimensions.Width,
|
|
|
- x => x.Dimensions.Height,
|
|
|
- x => x.Dimensions.Weight,
|
|
|
- x => x.Dimensions.Unit.HasHeight,
|
|
|
- x => x.Dimensions.Unit.HasLength,
|
|
|
- x => x.Dimensions.Unit.HasWidth,
|
|
|
- x => x.Dimensions.Unit.HasWeight,
|
|
|
- x => x.Dimensions.Unit.HasQuantity,
|
|
|
- x => x.Dimensions.Unit.Formula,
|
|
|
- x => x.Dimensions.Unit.Format,
|
|
|
- x => x.Dimensions.Unit.Code,
|
|
|
- x => x.Dimensions.Unit.Description,
|
|
|
-
|
|
|
- x => x.FreeStock,
|
|
|
- x => x.AverageCost,
|
|
|
- x => x.LastCost
|
|
|
- )
|
|
|
+ Columns.Required<ProductInstance>()
|
|
|
+ .Add(x => x.ID)
|
|
|
+ .Add(x => x.FreeStock)
|
|
|
+ .Add(x => x.AverageCost)
|
|
|
+ .Add(x => x.LastCost)
|
|
|
).Rows.FirstOrDefault();
|
|
|
});
|
|
|
- instancetask.Start();
|
|
|
|
|
|
- var producttask = new Task<CoreRow?>(() =>
|
|
|
- {
|
|
|
- return Provider.Query(
|
|
|
+ var producttask = Task.Run(
|
|
|
+ () => Provider.Query(
|
|
|
new Filter<Product>(x => x.ID).IsEqualTo(entity.Product.ID),
|
|
|
- Columns.None<Product>().Add(
|
|
|
- x => x.ID,
|
|
|
- x => x.DefaultLocation.ID,
|
|
|
- x => x.Warehouse.ID,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.ID,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.Formula,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.Format,
|
|
|
- x => x.DefaultInstance.Dimensions.Quantity,
|
|
|
- x => x.DefaultInstance.Dimensions.Length,
|
|
|
- x => x.DefaultInstance.Dimensions.Width,
|
|
|
- x => x.DefaultInstance.Dimensions.Height,
|
|
|
- x => x.DefaultInstance.Dimensions.Weight,
|
|
|
- x => x.NonStock,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.HasHeight,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.HasLength,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.HasWidth,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.HasWeight,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.HasQuantity,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.Formula,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.Format,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.Code,
|
|
|
- x => x.DefaultInstance.Dimensions.Unit.Description
|
|
|
- )
|
|
|
- ).Rows.FirstOrDefault();
|
|
|
- });
|
|
|
- producttask.Start();
|
|
|
-
|
|
|
- var locationtask = new Task<CoreTable>(() =>
|
|
|
- {
|
|
|
- return Provider.Query(
|
|
|
+ Columns.None<Product>()
|
|
|
+ .Add(x => x.ID)
|
|
|
+ .Add(x => x.DefaultLocation.ID)
|
|
|
+ .Add(x => x.Warehouse.ID)
|
|
|
+ .AddDimensionsColumns(x => x.DefaultInstance.Dimensions, Dimensions.ColumnsType.All)
|
|
|
+ .Add(x => x.NonStock))
|
|
|
+ .Rows.FirstOrDefault());
|
|
|
+
|
|
|
+ var locationtask = Task.Run(
|
|
|
+ () => Provider.Query(
|
|
|
new Filter<StockLocation>(x => x.Default).IsEqualTo(true),
|
|
|
- Columns.None<StockLocation>().Add(x => x.ID, x => x.Warehouse.ID, x => x.Warehouse.Default)
|
|
|
- );
|
|
|
- });
|
|
|
- locationtask.Start();
|
|
|
+ Columns.None<StockLocation>().Add(x => x.ID, x => x.Warehouse.ID, x => x.Warehouse.Default)));
|
|
|
|
|
|
- Task.WaitAll(producttask, locationtask, instancetask, jriTask, consigntask);
|
|
|
+ Task.WaitAll(producttask, locationtask, instancetask, poiaTask, consigntask);
|
|
|
|
|
|
var instancerow = instancetask.Result;
|
|
|
var productrow = producttask.Result;
|
|
|
var defaultlocations = locationtask.Result;
|
|
|
- var jris = jriTask.Result.ToArray();
|
|
|
+ var allocations = poiaTask.Result.ToArray();
|
|
|
|
|
|
if (productrow is null)
|
|
|
{
|
|
|
Logger.Send(LogType.Information, UserID, "Cannot Find PurchaseOrderItem.Product.ID!");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
if (productrow.Get<Product, bool>(x => x.NonStock))
|
|
|
{
|
|
|
Logger.Send(LogType.Information, UserID, "PurchaseOrderItem.Product is marked as Non Stock!");
|
|
@@ -241,13 +197,11 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (
|
|
|
- (entity.Dimensions.Unit.ID == Guid.Empty)
|
|
|
- && (entity.Dimensions.Height == 0)
|
|
|
- && (entity.Dimensions.Width == 0)
|
|
|
- && (entity.Dimensions.Length == 0)
|
|
|
- && (entity.Dimensions.Weight == 0)
|
|
|
- )
|
|
|
+ if (entity.Dimensions.Unit.ID == Guid.Empty
|
|
|
+ && entity.Dimensions.Height == 0
|
|
|
+ && entity.Dimensions.Width == 0
|
|
|
+ && entity.Dimensions.Length == 0
|
|
|
+ && entity.Dimensions.Weight == 0)
|
|
|
{
|
|
|
Logger.Send(LogType.Information, UserID, "PurchaseOrderItem.Unit Size is zero!");
|
|
|
entity.Dimensions.CopyFrom(productrow.ToObject<Product>().DefaultInstance.Dimensions);
|
|
@@ -267,8 +221,6 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
}
|
|
|
|
|
|
instance.LastCost = entity.Cost;
|
|
|
-
|
|
|
- //var product = productrow.ToObject<Product>();
|
|
|
|
|
|
var freeqty = instance.FreeStock;
|
|
|
var freeavg = instance.AverageCost;
|
|
@@ -297,6 +249,8 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Actual logic begins here.
|
|
|
+
|
|
|
var batch = new StockMovementBatch
|
|
|
{
|
|
|
Type = StockMovementBatchType.Receipt,
|
|
@@ -313,22 +267,28 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
poCost += entity.Cost * entity.Consignment.ExTax / consigntask.Result;
|
|
|
}
|
|
|
|
|
|
- foreach (var jri in jris)
|
|
|
+ foreach (var poia in allocations)
|
|
|
{
|
|
|
- // Going through each jri, make sure we don't allocate more than the po line allows
|
|
|
- var jriQty = Math.Min(jri.Qty, _pototal);
|
|
|
- // And reduce the po balance by the jri Allocation
|
|
|
- _pototal -= jriQty;
|
|
|
-
|
|
|
- // Let's not make zero-quantity transactions
|
|
|
- if (!jriQty.IsEffectivelyEqual(0.0))
|
|
|
- CreateMovement(entity, locationid, movements, jri, jriQty, poCost);
|
|
|
+ var jri = poia.JobRequisitionItem.ID == Guid.Empty ? null : poia.JobRequisitionItem;
|
|
|
+ CreateMovement(entity, locationid, movements, poia.Job, jri, poia.Quantity, poCost);
|
|
|
+
|
|
|
+ //CreateMovement(entity, locationid, movements, poia.Job, poia.JobRequisitionItem, poia.Quantity, poCost);
|
|
|
+
|
|
|
+ //// Going through each jri, make sure we don't allocate more than the po line allows
|
|
|
+ //var jriQty = Math.Min(jri.Qty, _pototal);
|
|
|
+ //// And reduce the po balance by the jri Allocation
|
|
|
+ //_pototal -= jriQty;
|
|
|
+ //
|
|
|
+ //// Let's not make zero-quantity transactions
|
|
|
+ //if (!jriQty.IsEffectivelyEqual(0.0))
|
|
|
+ // CreateMovement(entity, locationid, movements, jri, jriQty, poCost);
|
|
|
}
|
|
|
+
|
|
|
+ var totalAllocations = allocations.Sum(x => x.Quantity);
|
|
|
|
|
|
- // If there is any left over (ie over-ordered), now we can create a
|
|
|
- // second transaction to receive the unallocated stock
|
|
|
- if (!_pototal.IsEffectivelyEqual(0.0F))
|
|
|
- CreateMovement(entity, locationid, movements, null, _pototal, poCost);
|
|
|
+ // If there is any left over (ie over/under-ordered), now we can create
|
|
|
+ // a second transaction to receive the unallocated stock
|
|
|
+ CreateMovement(entity, locationid, movements, null, null, entity.Qty - totalAllocations, poCost);
|
|
|
|
|
|
FindSubStore<StockMovementBatch>().Save(batch, "Received on PO");
|
|
|
foreach(var mvt in movements)
|
|
@@ -340,11 +300,16 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
entity.CancelChanges();
|
|
|
}
|
|
|
|
|
|
- private static void CreateMovement(PurchaseOrderItem entity, Guid locationid, List<StockMovement> movements, JobRequisitionItem jri, double qty, double cost)
|
|
|
+ private static void CreateMovement(PurchaseOrderItem entity, Guid locationid, List<StockMovement> movements, IJob? job, IJobRequisitionItem? jri, double qty, double cost)
|
|
|
{
|
|
|
+ if (qty.IsEffectivelyEqual(0.0)) return;
|
|
|
+
|
|
|
var movement = new StockMovement();
|
|
|
movement.Product.ID = entity.Product.ID;
|
|
|
- movement.Job.ID = entity.Job.ID;
|
|
|
+ if(job is not null)
|
|
|
+ {
|
|
|
+ movement.Job.ID = job.ID;
|
|
|
+ }
|
|
|
movement.Location.ID = locationid;
|
|
|
movement.Style.ID = entity.Style.ID;
|
|
|
movement.Dimensions.CopyFrom(entity.Dimensions);
|
|
@@ -368,7 +333,7 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
var tOut = movement.CreateMovement();
|
|
|
tOut.JobRequisitionItem.ID = jri.ID;
|
|
|
tOut.Date = entity.ReceivedDate;
|
|
|
- tOut.Issued = jri.Qty;
|
|
|
+ tOut.Issued = qty;
|
|
|
tOut.OrderItem.ID = entity.ID;
|
|
|
tOut.Notes = "Internal transfer from cancelled requisition";
|
|
|
tOut.System = true;
|
|
@@ -378,7 +343,7 @@ internal class PurchaseOrderItemStore : BaseStore<PurchaseOrderItem>
|
|
|
var tIn = movement.CreateMovement();
|
|
|
tIn.Transaction = tOut.Transaction;
|
|
|
tIn.Date = entity.ReceivedDate;
|
|
|
- tIn.Received = jri.Qty;
|
|
|
+ tIn.Received = qty;
|
|
|
tIn.OrderItem.ID = entity.ID;
|
|
|
tOut.Notes = "Internal transfer from cancelled requisition";
|
|
|
tOut.System = true;
|