123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using Comal.Classes;
- using HarfBuzzSharp;
- using InABox.Core;
- using InABox.Mobile;
- using Xamarin.CommunityToolkit.ObjectModel;
- using Xamarin.Forms;
- namespace PRS.Mobile
- {
- public enum StockTransactionType
- {
- Transfer,
- Issue,
- Receive,
- StockTake
- }
- public enum StockTransactionView
- {
- Source,
- Target
- }
- public enum StockTransactionProperty
- {
- Location,
- Style,
- Job
- }
-
- public class StockTransactionHolding : BindableObject
- {
- public StockHoldingShell? Shell { get; set; }
- public Guid LocationID { get; set; }
- public String LocationCode { get; set; }
- public String LocationDescription { get; set; }
- public String LocationDisplay => LocationID == Guid.Empty ? "" : $"{LocationCode}: {LocationDescription}";
-
- public Guid StyleID { get; set; }
- public String StyleCode { get; set; }
- public String StyleDescription { get; set; }
- public String StyleDisplay => StyleID == Guid.Empty ? "" : $"{StyleCode}: {StyleDescription}";
-
- public Guid JobID { get; set; }
- public String JobNumber { get; set; }
- public String JobName { get; set; }
- public String JobDisplay => JobID == Guid.Empty ? "" : $"{JobNumber}: {JobName}";
- public double Units { get; set; }
- public bool HasAllocations => !(Shell?.Units ?? 0.0).IsEffectivelyEqual(Shell?.Available ?? 0.0);
-
- public StockTransactionHolding(StockHoldingShell? shell)
- {
- Shell = shell;
- LocationID = shell?.LocationID ?? Guid.Empty;
- LocationCode = shell?.LocationCode ?? string.Empty;
- LocationDescription = shell?.LocationDescription ?? string.Empty;
- StyleID = shell?.StyleID ?? Guid.Empty;
- StyleCode = shell?.StyleCode ?? string.Empty;
- StyleDescription = shell?.StyleDescription ?? string.Empty;
- JobID = shell?.JobID ?? Guid.Empty;
- JobNumber = shell?.JobNumber ?? string.Empty;
- JobName = shell?.JobName ?? string.Empty;
- Units = shell?.Units ?? 0.0d;
- }
-
- }
- public class StockTransactionAllocation : BindableObject
- {
- public Guid ID { get; set; }
-
- public Guid JobID { get; set; }
-
- public String Description { get; set; }
-
- public double Quantity { get; set; }
-
- public double Maximum { get; set; }
-
- }
-
- public class StockTransaction : BindableObject
- {
- private double _dimensionsQuantity;
- private double _dimensionsLength;
- private double _dimensionsWidth;
- private double _dimensionsHeight;
- private double _dimensionsWeight;
- public StockTransactionType Type { get; set; }
-
- public Guid TransactionID { get; private set; }
-
- public Guid EmployeeID { get; private set; }
- public Guid ProductID { get; set; }
-
- public String ProductCode { get; set; }
-
- public String ProductName { get; set; }
- public String ProductDisplay => ProductID == Guid.Empty ? "" : $"{ProductCode}: {ProductName}";
-
- public Guid ImageID { get; set; }
-
- public byte[]? Image { get; set; }
-
- public Guid DimensionsUnitID { get; set; }
- public double DimensionsQuantity
- {
- get => _dimensionsQuantity;
- set
- {
- _dimensionsQuantity = value;
- CalculateDimensions();
- }
- }
- public double DimensionsLength
- {
- get => _dimensionsLength;
- set
- {
- _dimensionsLength = value;
- CalculateDimensions();
- }
- }
- public double DimensionsWidth
- {
- get => _dimensionsWidth;
- set
- {
- _dimensionsWidth = value;
- CalculateDimensions();
- }
- }
- public double DimensionsHeight
- {
- get => _dimensionsHeight;
- set
- {
- _dimensionsHeight = value;
- CalculateDimensions();
- }
- }
- public double DimensionsWeight
- {
- get => _dimensionsWeight;
- set
- {
- _dimensionsWeight = value;
- CalculateDimensions();
- }
- }
- public String DimensionsUnitSize { get; set; }
-
- public double DimensionsValue { get; set; }
-
- public double Cost { get; set; }
- public StockTransactionAllocation[]? Allocations { get; set; }
-
- public double Quantity => Allocations?.Aggregate(0.0, (t, a) => t += a.Quantity) ?? 0.0;
- public void RefreshQuantity() => OnPropertyChanged(nameof(Quantity));
-
- public bool HasAllocations => Allocations?.Any(x => x.ID != Guid.Empty) ?? false;
-
- public StockTransactionHolding Source { get; private set; }
-
- public StockTransactionHolding Target { get; private set; }
- public bool LocationChanged => (Source?.LocationID ?? Guid.Empty) != (Target?.LocationID ?? Guid.Empty);
- public bool StyleChanged => (Source?.StyleID ?? Guid.Empty) != (Target?.StyleID ?? Guid.Empty);
- public bool JobChanged => (Source?.JobID ?? Guid.Empty) != (Target?.JobID ?? Guid.Empty);
- public StockTransaction(StockTransactionType type, StockHoldingShell? source, StockHoldingShell? target)
- {
- var shell = source ?? target;
- Type = type;
- TransactionID = Guid.NewGuid();
- EmployeeID = App.Data.Me.ID;
-
- ProductID = shell?.ProductID ?? Guid.Empty;
- ProductCode = shell?.ProductCode ?? string.Empty;
- ProductName = shell?.ProductName ?? string.Empty;
- ImageID = shell?.ImageID ?? Guid.Empty;
- Image = shell?.Image ?? new byte[] { };
- DimensionsUnitID = shell?.DimensionsUnitID ?? Guid.Empty;
- DimensionsQuantity = shell?.DimensionsQuantity ?? 0.0;
- DimensionsLength = shell?.DimensionsLength ?? 0.0;
- DimensionsWidth = shell?.DimensionsWidth ?? 0.0;
- DimensionsHeight = shell?.DimensionsHeight ?? 0.0;
- DimensionsWeight = shell?.DimensionsWeight ?? 0.0;
- DimensionsUnitSize = shell?.DimensionsUnitSize ?? string.Empty;
- DimensionsValue = shell?.DimensionsValue ?? 0.0;
- Cost = shell?.AverageCost ?? 0.0;
-
- Source = new StockTransactionHolding(source);
- Source.PropertyChanged += (sender, args) => OnPropertyChanged(nameof(Source));
- Target = new StockTransactionHolding(target);
- Target.PropertyChanged += (sender, args) => OnPropertyChanged(nameof(Target));
- }
-
- private void CalculateDimensions()
- {
- var dimensions = App.Data.ProductDimensionUnits.FirstOrDefault(x => x.ID == DimensionsUnitID);
- Dictionary<string, object?> variables = new Dictionary<string, object?>();
- variables["Length"] = DimensionsLength;
- variables["Width"] = DimensionsWidth;
- variables["Height"] = DimensionsHeight;
- variables["Quantity"] = DimensionsQuantity;
- variables["Weight"] = DimensionsHeight;
- if (! String.IsNullOrWhiteSpace(dimensions?.Format))
- DimensionsUnitSize = new CoreExpression(dimensions.Format).Evaluate(variables)?.ToString() ?? string.Empty;
- if (!String.IsNullOrWhiteSpace(dimensions?.Formula))
- {
- var value = new CoreExpression(dimensions.Format).Evaluate(variables)?.ToString() ?? "0.0";
- DimensionsValue = double.TryParse(value, out double val)
- ? val
- : 0.0;
- }
-
- }
- public string Display(StockTransactionView? view = null)
- {
- List<String> results = new List<string>();
-
- if ((Source?.LocationID ?? Guid.Empty) != (Target?.LocationID ?? Guid.Empty))
- {
- string location = Type switch
- {
- StockTransactionType.Issue => "Issued",
- StockTransactionType.Receive => "Received",
- _ => "Transferred"
- };
- string fromlocation = "";
- string tolocation = "";
- if ((view == null) || (view == StockTransactionView.Target))
- fromlocation = (Source?.LocationID ?? Guid.Empty) != Guid.Empty
- ? $" From {Source?.LocationCode ?? "--"}"
- : " From --";
- if ((view == null) || (view == StockTransactionView.Source))
- tolocation = (Target?.LocationID ?? Guid.Empty) != Guid.Empty
- ? $" To {Target?.LocationCode ?? "--"}"
- : " To --";
- results.Add($"{location}{fromlocation}{tolocation}");
- }
- if ((Source?.StyleID ?? Guid.Empty) != (Target?.StyleID ?? Guid.Empty))
- {
- string fromstyle = "";
- string tostyle = "";
-
- if ((view == null) || (view == StockTransactionView.Target))
- fromstyle = (Source?.StyleID ?? Guid.Empty) != Guid.Empty
- ? $" From {Source?.StyleCode ?? "(none)"}"
- : " From (none)";
-
- if ((view == null) || (view == StockTransactionView.Source))
- tostyle = (Target?.StyleID ?? Guid.Empty) != Guid.Empty
- ? $" To {Target?.StyleCode ?? "(none)"}"
- : " To (none)";
-
- results.Add($"Changed Style{fromstyle}{tostyle}");
- }
-
- if ((Source?.JobID ?? Guid.Empty) != (Target?.JobID ?? Guid.Empty))
- {
- string fromjob = "";
- string tojob = "";
- if ((view == null) || (view == StockTransactionView.Target))
- fromjob = (Source?.JobID ?? Guid.Empty) != Guid.Empty
- ? $" From {Source?.JobNumber ?? "(none)"}"
- : " From (none)";
-
- if ((view == null) || (view == StockTransactionView.Source))
- tojob = (Target?.JobID ?? Guid.Empty) != Guid.Empty
- ? $" To {Target?.JobNumber ?? "(none)"}"
- : " To (none)";
-
- results.Add($"Changed Job{fromjob}{tojob}");
- }
-
- return String.Join("\n", results);
-
- }
-
- }
-
- public class StockTransactionImage : BindableObject
- {
- public MobileDocument Document { get; private set; }
- public byte[] Thumbnail { get; set; }
- public StockTransactionImage(MobileDocument document, byte[] thumbnail)
- {
- Document = document;
- Thumbnail = thumbnail;
- }
-
- }
- public class StockTransactions : ObservableRangeCollection<StockTransaction>
- {
- private enum TransactionDirection
- {
- Issue,
- Receive
- }
- public void ProcessTransactions(StockMovementModel model, Guid batchid)
- {
- void CreateMovement(
- StockMovementType type,
- StockTransaction transaction,
- Guid locationid,
- Guid styleid,
- Guid jobid,
- DateTime timestamp,
- TransactionDirection direction,
- Action<StockTransaction, StockTransactionAllocation, StockMovementShell>? oncreate = null
- )
- {
- foreach (var allocation in transaction.Allocations)
- {
- var movement = model.AddItem();
- movement.BatchID = batchid;
- movement.Date = timestamp;
- movement.Type = type;
- movement.TransactionID = transaction.TransactionID;
- movement.ProductID = transaction.ProductID;
- movement.DimensionsUnitID = transaction.DimensionsUnitID;
- movement.DimensionsQuantity = transaction.DimensionsQuantity;
- movement.DimensionsLength = transaction.DimensionsLength;
- movement.DimensionsWidth = transaction.DimensionsWidth;
- movement.DimensionsHeight = transaction.DimensionsHeight;
- movement.DimensionsWeight = transaction.DimensionsWeight;
- movement.DimensionsValue = transaction.DimensionsValue;
- movement.DimensionsUnitSize = transaction.DimensionsUnitSize;
- movement.LocationID = locationid;
- movement.StyleID = styleid;
- movement.JobID = jobid;
- movement.RequisitionItemID = allocation.ID;
- movement.Received = direction == TransactionDirection.Receive ? allocation.Quantity : 0.0F;
- movement.Issued = direction == TransactionDirection.Issue ? allocation.Quantity : 0.0F;
- movement.Cost = transaction.Cost;
- movement.EmployeeID = transaction.EmployeeID;
- oncreate?.Invoke(transaction, allocation, movement);
- }
- }
-
- var now = DateTime.Now;
- foreach (var transaction in this)
- {
- if (transaction.Type == StockTransactionType.Receive)
- {
- CreateMovement(
- StockMovementType.Receive,
- transaction,
- transaction.Target.LocationID,
- transaction.Target.StyleID,
- transaction.Target.JobID,
- now,
- TransactionDirection.Receive
- );
- }
- else if (transaction.Type == StockTransactionType.Issue)
- {
- if (transaction.Source.StyleID != transaction.Target.StyleID ||
- transaction.Source.JobID != transaction.Target.JobID)
- {
- CreateMovement(
- StockMovementType.TransferOut,
- transaction,
- transaction.Source.LocationID,
- transaction.Source.StyleID,
- transaction.Source.JobID,
- now,
- TransactionDirection.Issue);
-
- CreateMovement(
- StockMovementType.TransferIn,
- transaction,
- transaction.Source.LocationID,
- transaction.Target.StyleID,
- transaction.Target.JobID,
- now,
- TransactionDirection.Receive);
- }
- CreateMovement(
- StockMovementType.Issue,
- transaction,
- transaction.Source.LocationID,
- transaction.Target.StyleID,
- transaction.Target.JobID,
- now,
- TransactionDirection.Issue);
- }
- else if (transaction.Type == StockTransactionType.Transfer)
- {
- CreateMovement(
- StockMovementType.TransferOut,
- transaction,
- transaction.Source.LocationID,
- transaction.Source.StyleID,
- transaction.Source.JobID,
- now,
- TransactionDirection.Issue);
- CreateMovement(
- StockMovementType.TransferIn,
- transaction,
- transaction.Target.LocationID,
- transaction.Target.StyleID,
- transaction.Target.JobID,
- now,
- TransactionDirection.Receive);
- }
- else if (transaction.Type == StockTransactionType.StockTake)
- {
- CreateMovement(
- StockMovementType.StockTake,
- transaction,
- transaction.Target.LocationID,
- transaction.Target.StyleID,
- transaction.Target.JobID,
- now,
- transaction.Quantity > 0 ? TransactionDirection.Receive : TransactionDirection.Issue,
- (t, a, m) =>
- {
- var srcAlloc = t.Source.Shell.Allocations.FirstOrDefault(x => x.ID == a.ID);
- m.Issued = Math.Max(0, (srcAlloc?.Quantity ?? t.Source.Units) - a.Quantity);
- m.Received = Math.Max(0, a.Quantity - (srcAlloc?.Quantity ?? t.Source.Units));
- m.Notes = m.Issued.IsEffectivelyEqual(0.0F) && m.Received.IsEffectivelyEqual(0.0F)
- ? $"Correct Quantity Confirmed"
- : $"Quantity Adjusted from {(srcAlloc?.Quantity ?? t.Source.Units):F2} to {a.Quantity:F2}";
- m.Balance = a.Quantity;
- }
- );
- }
- }
- }
- public IEnumerable<StockTransaction> Get(StockHoldingShell shell)
- {
- bool IsHoldingReferenced(StockTransactionHolding holding) =>
- holding.LocationID == shell.LocationID
- && holding.StyleID == shell.StyleID
- && holding.JobID == shell.JobID;
-
- var results = this.Where(x => x.ProductID == shell.ProductID
- && String.Equals(x.DimensionsUnitSize, shell.DimensionsUnitSize)
- && (IsHoldingReferenced(x.Source) || IsHoldingReferenced(x.Target))).ToArray();
- return results;
- }
-
- }
-
- }
|