123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- using Comal.Classes;
- using Comal.Stores;
- using InABox.Core;
- using InABox.Database;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace PRSStores;
- public enum JobRequisitionItemAction
- {
- Created,
- Updated,
- Deleted,
- None
- }
- public class JobRequisitionItemStore : BaseStore<JobRequisitionItem>
- {
- protected override void BeforeSave(JobRequisitionItem item)
- {
- if (item.ID != Guid.Empty)
- {
- if (CalculateStatus(this, item))
- item.Notes += $"{(!String.IsNullOrWhiteSpace(item.Notes) ? "\n" : "")}Status updated to {item.Status.ToString().SplitCamelCase()} because the record was changed";
- }
- base.BeforeSave(item);
- }
- public static Columns<JobRequisitionItem> StatusRequiredColumns()
- {
- return new Columns<JobRequisitionItem>(
- x => x.ID,
- x => x.Archived,
- x => x.Cancelled,
- x => x.OrderRequired,
- x => x.Status,
- x => x.Style.ID,
- x => x.Product.ID,
- x => x.Qty,
- x => x.Notes);
- }
- /// <summary>
- /// Ensure that the columns of <paramref name="item"/> match <see cref="StatusRequiredColumns"/>.
- /// </summary>
- /// <param name="store"></param>
- /// <param name="item"></param>
- /// <returns></returns>
- public static bool CalculateStatus(IStore store, JobRequisitionItem item)
- {
- if (item.Archived != DateTime.MinValue)
- item.Status = JobRequisitionItemStatus.Archived;
- else if (item.Cancelled != DateTime.MinValue)
- item.Status = JobRequisitionItemStatus.Cancelled;
- else
- {
- var stockMovements = store.Provider
- .Query(
- new Filter<StockMovement>(x => x.JobRequisitionItem.ID).IsEqualTo(item.ID).And(x=>x.Type).IsNotEqualTo(StockMovementType.Issue),
- new Columns<StockMovement>(x => x.Units)
- .Add(x => x.Style.ID)
- .Add(x=>x.Type)
- )
- .ToObjects<StockMovement>();
- var styleTotal = 0.0;
- var total = 0.0;
- foreach (var mvt in stockMovements)
- {
- if (mvt.Style.ID == item.Style.ID)
- {
- styleTotal += mvt.Units;
- }
- total += mvt.Units;
- }
- var remStyle = item.Qty - styleTotal;
- var remTotal = item.Qty - total;
- if (remStyle <= 0)
- item.Status = JobRequisitionItemStatus.Allocated;
- else if (remTotal <= 0)
- {
- // Find all unreceived POItems for this guy that are treatments (i.e., wrong product ID).
- var jriPois = store.Provider.Query(
- new Filter<JobRequisitionItemPurchaseOrderItem>(x => x.JobRequisitionItem.ID).IsEqualTo(item.ID)
- .And(x => x.PurchaseOrderItem.ReceivedDate).IsEqualTo(DateTime.MinValue)
- .And(x => x.PurchaseOrderItem.Product.ID).IsNotEqualTo(item.Product.ID),
- new Columns<JobRequisitionItemPurchaseOrderItem>(x => x.ID));
- if (jriPois.Rows.Count > 0)
- item.Status = JobRequisitionItemStatus.TreatmentOnOrder;
- else
- item.Status = JobRequisitionItemStatus.TreatmentRequired;
- }
- else
- {
- // Find all unreceived POItems for this guy.
- var jriPois = store.Provider.Query(
- new Filter<JobRequisitionItemPurchaseOrderItem>(x => x.JobRequisitionItem.ID).IsEqualTo(item.ID)
- .And(x => x.PurchaseOrderItem.ReceivedDate).IsEqualTo(DateTime.MinValue),
- new Columns<JobRequisitionItemPurchaseOrderItem>(x => x.PurchaseOrderItem.Product.ID)
- .Add(x => x.PurchaseOrderItem.Qty))
- .ToObjects<JobRequisitionItemPurchaseOrderItem>()
- .ToList();
- var stockOrders = jriPois.Where(x => x.PurchaseOrderItem.Product.ID == item.Product.ID).ToList();
- var treatmentOrders = jriPois.Where(x => x.PurchaseOrderItem.Product.ID != item.Product.ID).ToList();
- remTotal -= stockOrders.Sum(x => x.PurchaseOrderItem.Qty);
- if (remTotal <= 0)
- {
- if (stockOrders.Count > 0)
- item.Status = JobRequisitionItemStatus.OnOrder;
- else
- {
- // This should be impossible to reach. We are at this point because remTotal <= 0, but stockOrders was an empty list. Therefore
- // remTotal is was <= 0 before checking PurchaseOrderItems, but then we should be TreatmentRequired, as above.
- Logger.Send(LogType.Error, store.UserID, $"Internal assertion failed: there is enough stock, but we didn't reach the correct clause.");
- if (treatmentOrders.Count > 0)
- item.Status = JobRequisitionItemStatus.TreatmentOnOrder;
- else
- item.Status = JobRequisitionItemStatus.TreatmentRequired;
- }
- }
- else if (item.OrderRequired != DateTime.MinValue)
- item.Status = JobRequisitionItemStatus.OrderRequired;
- else
- {
- // Even after all the orders have come through, we still don't have enough. We must order more.
- item.Status = JobRequisitionItemStatus.NotChecked;
- }
- }
- }
- return item.HasOriginalValue(x => x.Status);
- }
- public static bool CalculateStatus(IStore store, Guid jobRequiItemID)
- {
- var item = store.Provider.Query(
- new Filter<JobRequisitionItem>(x => x.ID).IsEqualTo(jobRequiItemID),
- StatusRequiredColumns())
- .ToObjects<JobRequisitionItem>()
- .FirstOrDefault();
- if(item is null)
- {
- Logger.Send(LogType.Error, store.UserID, $"No {nameof(JobRequisitionItem)} with ID {jobRequiItemID}");
- return false;
- }
- return CalculateStatus(store, item);
- }
-
- public static void UpdateStatus(IStore store, Guid jobRequiItemID, JobRequisitionItemAction action)
- {
- Logger.Send(LogType.Information, "", " ** Updating Requisition Item Status ({0}) -> {1}",
- store.GetType().EntityName(), jobRequiItemID);
- var item = store.Provider.Query(
- new Filter<JobRequisitionItem>(x => x.ID).IsEqualTo(jobRequiItemID),
- StatusRequiredColumns())
- .ToObjects<JobRequisitionItem>()
- .FirstOrDefault();
- if (item is null)
- {
- Logger.Send(LogType.Error, store.UserID, $"No {nameof(JobRequisitionItem)} with ID {jobRequiItemID}");
- }
- else
- {
- if (CalculateStatus(store, item))
- {
- if (action != JobRequisitionItemAction.None)
- item.Notes += $"{(!String.IsNullOrWhiteSpace(item.Notes) ? "\n" : "")}Status updated to {item.Status.ToString().SplitCamelCase()} because a {store.Type.EntityName().Split('.').Last().SplitCamelCase()} was {action.ToString().ToLower()}";
- store.Provider.Save(item);
- }
- }
- }
- }
|