| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 | 
							- using Comal.Classes;
 
- using InABox.Clients;
 
- using InABox.Core;
 
- namespace PRS.Shared
 
- {
 
-     
 
-     public enum InvoiceTimeCalculation
 
-     {
 
-         Detailed,
 
-         Activity,
 
-         Collapsed,
 
-     }
 
-         
 
-     public enum InvoiceMaterialCalculation
 
-     {
 
-         Detailed,
 
-         Product,
 
-         CostCentre,
 
-         Collapsed,
 
-     }
 
-     
 
-     public static class InvoiceUtilities
 
-     {
 
-         
 
-         private class InvoiceLineDetail
 
-         {
 
-             public Guid ID { get; set; }
 
-             public String Description { get; set; }
 
-             public TaxCodeLink TaxCode { get; set; }
 
-             public double Quantity { get; set; }
 
-             public double Charge { get; set; }
 
-             public InvoiceLineDetail()
 
-             {
 
-                 TaxCode = new TaxCodeLink();
 
-             }
 
-         }
 
-         
 
-         public static void GenerateInvoiceLines(Guid invoiceid, InvoiceTimeCalculation timesummary, InvoiceMaterialCalculation partsummary, IProgress<String>? progress )
 
-         {
 
-             
 
-             CustomerActivitySummary[] activities = new CustomerActivitySummary[] { };
 
-             CustomerProductSummary[] products = new CustomerProductSummary[] { };
 
-             Assignment[] assignments = new Assignment[] { };
 
-             RequisitionItem[] requisitionitems = new RequisitionItem[] { };
 
-             progress?.Report("Loading Invoice");
 
-             var invoice = new Client<Invoice>().Load(new Filter<Invoice>(x => x.ID).IsEqualTo(invoiceid)).FirstOrDefault();
 
-             
 
-             progress?.Report("Loading Detail Data");
 
-             var setup = new Task[]
 
-             {
 
-                 
 
-                 
 
-                 Task.Run(() =>
 
-                 {
 
-                     var oldlines = new Client<InvoiceLine>().Query(
 
-                         new Filter<InvoiceLine>(x => x.InvoiceLink.ID).IsEqualTo(invoice.ID),
 
-                         new Columns<InvoiceLine>(x => x.ID)
 
-                     ).Rows.Select(x => x.ToObject<InvoiceLine>()).ToArray();
 
-                     new Client<InvoiceLine>().Delete(oldlines, "");
 
-                 }),
 
-                 Task.Run(() =>
 
-                 {
 
-                     activities =
 
-                         new Client<CustomerActivitySummary>().Query(
 
-                             new Filter<CustomerActivitySummary>(x => x.Customer.ID).InList(invoice.CustomerLink.ID, Guid.Empty),
 
-                             new Columns<CustomerActivitySummary>(x => x.Customer.ID)
 
-                                 .Add(x => x.Activity.ID)
 
-                                 .Add(x => x.Activity.Code)
 
-                                 .Add(x => x.Activity.Description)
 
-                                 .Add(x => x.Charge.TaxCode.ID)
 
-                                 .Add(x => x.Charge.TaxCode.Rate)
 
-                                 .Add(x => x.Charge.Chargeable)
 
-                                 .Add(x => x.Charge.FixedCharge)
 
-                                 .Add(x => x.Charge.ChargeRate)
 
-                                 .Add(x => x.Charge.ChargePeriod)
 
-                                 .Add(x => x.Charge.MinimumCharge)
 
-                         ).Rows.Select(r => r.ToObject<CustomerActivitySummary>()).ToArray();
 
-                 }),
 
-                 Task.Run(() =>
 
-                 {
 
-                     assignments = new Client<Assignment>().Query(
 
-                         new Filter<Assignment>(x => x.Invoice.ID).IsEqualTo(invoice.ID).And(x => x.Charge.Chargeable).IsEqualTo(true),
 
-                         null,
 
-                         new SortOrder<Assignment>(x => x.Date)
 
-                     ).Rows.Select(x => x.ToObject<Assignment>()).ToArray();
 
-                 }),
 
-                 Task.Run(() =>
 
-                 {
 
-                     products =
 
-                         new Client<CustomerProductSummary>().Query(
 
-                             new Filter<CustomerProductSummary>(x => x.Customer.ID).InList(invoice.CustomerLink.ID, Guid.Empty),
 
-                             new Columns<CustomerProductSummary>(x => x.Customer.ID)
 
-                                 .Add(x => x.Product.ID)
 
-                                 .Add(x => x.Product.Code)
 
-                                 .Add(x => x.Product.Name)
 
-                                 .Add(x => x.Product.TaxCode.ID)
 
-                                 .Add(x => x.Product.TaxCode.Rate)
 
-                                 .Add(x => x.Charge.Chargeable)
 
-                                 .Add(x => x.Charge.PriceType)
 
-                                 .Add(x => x.Charge.Price)
 
-                                 .Add(x => x.Charge.Markup)
 
-                         ).Rows.Select(r => r.ToObject<CustomerProductSummary>()).ToArray();
 
-                 }),
 
-                 Task.Run(() =>
 
-                 {
 
-                     requisitionitems = new Client<RequisitionItem>().Query(
 
-                         new Filter<RequisitionItem>(x => x.Invoice.ID).IsEqualTo(invoice.ID).And(x => x.Charge.Chargeable).IsEqualTo(true),
 
-                         null,
 
-                         new SortOrder<RequisitionItem>(x => x.Picked)
 
-                     ).Rows.Select(x => x.ToObject<RequisitionItem>()).ToArray();
 
-                 })
 
-             };
 
-             
 
-             Task.WaitAll(setup);
 
-             
 
-             List<InvoiceLine> updates = new List<InvoiceLine>();
 
-             progress?.Report("Calculating...");
 
-             var timelines = new List<InvoiceLineDetail>();
 
-             foreach (var assignment in assignments)
 
-             {
 
-                 
 
-                 var id = timesummary switch
 
-                 {
 
-                     InvoiceTimeCalculation.Detailed => assignment.ID,
 
-                     InvoiceTimeCalculation.Activity => assignment.ActivityLink.ID,
 
-                     _ => Guid.Empty
 
-                 };
 
-                 var description = timesummary switch
 
-                 {
 
-                     InvoiceTimeCalculation.Detailed => string.Format("{0:dd MMM yy} - {1}", assignment.Date, assignment.Description),
 
-                     InvoiceTimeCalculation.Activity => assignment.ActivityLink.Description,
 
-                     _ => "Labour"
 
-                 };
 
-                 
 
-                 var quantity = assignment.Charge.OverrideQuantity
 
-                     ? TimeSpan.FromHours(assignment.Charge.Quantity)
 
-                     : assignment.Actual.Duration;
 
-                 
 
-                 var activity = 
 
-                     activities.FirstOrDefault(x => x.Customer.ID.Equals(invoice.CustomerLink.ID) && x.Activity.ID.Equals(assignment.ActivityLink.ID))
 
-                     ?? activities.FirstOrDefault(x => x.Customer.ID.Equals(Guid.Empty) && x.Activity.ID.Equals(assignment.ActivityLink.ID))
 
-                     ?? new CustomerActivitySummary();
 
-                 
 
-                 double charge = 0.0F;
 
-                 if (assignment.Charge.OverrideCharge)
 
-                     charge = quantity.TotalHours * assignment.Charge.Charge;
 
-                 else
 
-                 {
 
-                     
 
-                     double fixedcharge = activity.Charge.FixedCharge;
 
-                     
 
-                     TimeSpan chargeperiod = !activity.Charge.ChargePeriod.Equals(TimeSpan.Zero)
 
-                         ? activity.Charge.ChargePeriod
 
-                         : TimeSpan.FromHours(1);
 
-                     
 
-                     var rounded = quantity.Ceiling(chargeperiod);
 
-                     double multiplier = TimeSpan.FromHours(1).TotalHours / chargeperiod.TotalHours;
 
-                     double rate = activity.Charge.ChargeRate * multiplier;
 
-                     
 
-                     double mincharge = activity.Charge.MinimumCharge;
 
-                     charge = Math.Max(fixedcharge + (rounded.TotalHours * rate), mincharge);
 
-                 }
 
-                 var timeline = timelines.FirstOrDefault(x => x.ID == id);
 
-                 if (timeline == null)
 
-                 {
 
-                     timeline = new InvoiceLineDetail();
 
-                     timeline.Description = description;
 
-                     timeline.TaxCode.ID = activity.Charge.TaxCode.ID;
 
-                     timeline.TaxCode.Synchronise(activity.Charge.TaxCode);
 
-                     timelines.Add(timeline);
 
-                 }
 
-                 timeline.Quantity += quantity.TotalHours;
 
-                 timeline.Charge += charge;
 
-             }
 
-             
 
-             foreach (var line in timelines)
 
-             {
 
-                 var update = new InvoiceLine();
 
-                 update.InvoiceLink.ID = invoice.ID;
 
-                 update.Description = line.Description;
 
-                 update.TaxCode.ID = line.TaxCode.ID;
 
-                 update.TaxCode.Synchronise(line.TaxCode);
 
-                 update.Quantity = timesummary != InvoiceTimeCalculation.Collapsed ? line.Quantity : 1;
 
-                 update.ExTax = line.Charge;
 
-                 updates.Add(update);
 
-             }
 
-             
 
-             var partlines = new List<InvoiceLineDetail>();
 
-             
 
-             foreach (var item in requisitionitems)
 
-             {
 
-                 var id = partsummary switch
 
-                 {
 
-                     InvoiceMaterialCalculation.Detailed => item.ID,
 
-                     InvoiceMaterialCalculation.Product => item.Product.ID,
 
-                     InvoiceMaterialCalculation.CostCentre => item.Product.CostCentre.ID,
 
-                     _ => Guid.Empty
 
-                 };
 
-                 var description = partsummary switch
 
-                 {
 
-                     InvoiceMaterialCalculation.Detailed => item.Description,
 
-                     InvoiceMaterialCalculation.Product => item.Product.Name,
 
-                     InvoiceMaterialCalculation.CostCentre => item.Product.CostCentre.Description,
 
-                     _ => "Materials"
 
-                 };
 
-                 
 
-                 var quantity = item.Charge.OverrideQuantity
 
-                     ? item.Charge.Quantity
 
-                     : item.Quantity;
 
-                 
 
-                 var product = 
 
-                     products.FirstOrDefault(x => x.Customer.ID.Equals(invoice.CustomerLink.ID) && x.Product.ID.Equals(item.Product.ID))
 
-                     ?? products.FirstOrDefault(x => x.Customer.ID.Equals(Guid.Empty) && x.Product.ID.Equals(item.Product.ID))
 
-                     ?? new CustomerProductSummary();
 
-                 
 
-                 double charge = 0.0F;
 
-                 if (item.Charge.OverrideCharge)
 
-                     charge = quantity * item.Charge.Charge;
 
-                 else
 
-                 {
 
-                     charge = quantity * product.Charge.PriceType switch
 
-                     {
 
-                         ProductPriceType.CostPlus => 0.0F * product.Charge.Markup,
 
-                         _ => product.Charge.Price
 
-                     };
 
-                     
 
-                 }
 
-                 var partline = partlines.FirstOrDefault(x => x.ID == id);
 
-                 if (partline == null)
 
-                 {
 
-                     partline = new InvoiceLineDetail();
 
-                     partline.Description = description;
 
-                     partline.TaxCode.ID = product.Product.TaxCode.ID;
 
-                     partline.TaxCode.Synchronise(product.Product.TaxCode);
 
-                     partlines.Add(partline);
 
-                 }
 
-                 partline.Quantity += quantity;
 
-                 partline.Charge += charge;               
 
-                 
 
-             }
 
-             foreach (var line in partlines)
 
-             {
 
-                 var update = new InvoiceLine();
 
-                 update.InvoiceLink.ID = invoice.ID;
 
-                 update.Description = line.Description;
 
-                 update.TaxCode.ID = line.TaxCode.ID;
 
-                 update.TaxCode.Synchronise(line.TaxCode);
 
-                 update.Quantity = new[] { InvoiceMaterialCalculation.Detailed, InvoiceMaterialCalculation.Product}.Contains(partsummary) ? line.Quantity : 1.0F;
 
-                 update.ExTax = line.Charge;
 
-                 updates.Add(update);               
 
-             }
 
-             progress?.Report("Creating Invoice Lines");
 
-             if (updates.Any())
 
-                 new Client<InvoiceLine>().Save(updates, "Recalculating Invoice from Time and Materials");
 
-             
 
-         }
 
-     }
 
- }
 
 
  |