|
@@ -187,12 +187,14 @@ public class Module
|
|
|
|
|
|
public void ProcessHeader(IDataModel<PurchaseOrder> model, PurchaseOrder purchaseOrder, PurchaseOrderTimberlineHeader header)
|
|
|
{
|
|
|
- // Do extra processing for a purchase order
|
|
|
+ // Do extra processing for a purchase order; return false to fail this purchase order
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
public void ProcessLine(IDataModel<PurchaseOrder> model, PurchaseOrderItem purchaseOrderItem, PurchaseOrderTimberlineLine line)
|
|
|
{
|
|
|
- // Do extra processing for a purchase order line
|
|
|
+ // Do extra processing for a purchase order line; return false to fail this purchase order
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
public void AfterPost(IDataModel<PurchaseOrder> model)
|
|
@@ -203,13 +205,15 @@ public class Module
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public class PurchaseOrderTimberlineResult : TimberlinePostResult<PurchaseOrderTimberlineHeader, PurchaseOrder>
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
public class PurchaseOrderTimberlinePoster : ITimberlinePoster<PurchaseOrder, PurchaseOrderTimberlineSettings>
|
|
|
{
|
|
|
public ScriptDocument? Script { get; set; }
|
|
|
public PurchaseOrderTimberlineSettings Settings { get; set; }
|
|
|
|
|
|
- public event ITimberlinePoster<PurchaseOrder, PurchaseOrderTimberlineSettings>.AddFragmentCallback? AddFragment;
|
|
|
-
|
|
|
public bool BeforePost(IDataModel<PurchaseOrder> model)
|
|
|
{
|
|
|
model.SetIsDefault<Document>(false, alias: "CompanyLogo");
|
|
@@ -241,20 +245,18 @@ public class Module
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- private void ProcessHeader(IDataModel<PurchaseOrder> model, PurchaseOrder bill, PurchaseOrderTimberlineHeader header)
|
|
|
+ private bool ProcessHeader(IDataModel<PurchaseOrder> model, PurchaseOrder purchaseOrder, PurchaseOrderTimberlineHeader header)
|
|
|
{
|
|
|
- Script?.Execute(methodname: "ProcessHeader", parameters: new object[] { model, bill, header });
|
|
|
+ return Script?.Execute(methodname: "ProcessHeader", parameters: new object[] { model, purchaseOrder, header }) != false;
|
|
|
}
|
|
|
- private void ProcessLine(IDataModel<PurchaseOrder> model, PurchaseOrderItem purchaseOrderItem, PurchaseOrderTimberlineLine line)
|
|
|
+ private bool ProcessLine(IDataModel<PurchaseOrder> model, PurchaseOrderItem purchaseOrderItem, PurchaseOrderTimberlineLine line)
|
|
|
{
|
|
|
- Script?.Execute(methodname: "ProcessLine", parameters: new object[] { model, purchaseOrderItem, line });
|
|
|
+ return Script?.Execute(methodname: "ProcessLine", parameters: new object[] { model, purchaseOrderItem, line }) != false;
|
|
|
}
|
|
|
|
|
|
- private List<PurchaseOrderTimberlineHeader> DoProcess(IDataModel<PurchaseOrder> model)
|
|
|
+ private PurchaseOrderTimberlineResult DoProcess(IDataModel<PurchaseOrder> model)
|
|
|
{
|
|
|
- List<IPostableFragment> Fragments = new List<IPostableFragment>();
|
|
|
-
|
|
|
- var cs = new List<PurchaseOrderTimberlineHeader>();
|
|
|
+ var cs = new PurchaseOrderTimberlineResult();
|
|
|
|
|
|
var lines = model.GetTable<PurchaseOrderItem>("PurchaseOrder_PurchaseOrderItem").ToObjects<PurchaseOrderItem>()
|
|
|
.GroupBy(x => x.PurchaseOrderLink.ID).ToDictionary(x => x.Key, x => x.ToList());
|
|
@@ -272,73 +274,92 @@ public class Module
|
|
|
Closed = purchaseOrder.ClosedDate != DateTime.MinValue,
|
|
|
// Printed
|
|
|
};
|
|
|
- ProcessHeader(model, purchaseOrder, c);
|
|
|
-
|
|
|
- // Dictionary from line number to POItem.
|
|
|
- var items = new Dictionary<int, PurchaseOrderItem>();
|
|
|
- var POItems = lines.GetValueOrDefault(purchaseOrder.ID)?.ToList() ?? new List<PurchaseOrderItem>();
|
|
|
- foreach (var purchaseOrderItem in POItems)
|
|
|
+ if(!ProcessHeader(model, purchaseOrder, c))
|
|
|
+ {
|
|
|
+ cs.AddFailed(purchaseOrder, "Failed by script.");
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- if(int.TryParse(purchaseOrderItem.PostedReference, out var itemNumber))
|
|
|
+ // Dictionary from line number to POItem.
|
|
|
+ var items = new Dictionary<int, PurchaseOrderItem>();
|
|
|
+ var POItems = lines.GetValueOrDefault(purchaseOrder.ID)?.ToList() ?? new List<PurchaseOrderItem>();
|
|
|
+ foreach (var purchaseOrderItem in POItems)
|
|
|
{
|
|
|
- if (items.TryGetValue(itemNumber, out var oldItem))
|
|
|
+ if (int.TryParse(purchaseOrderItem.PostedReference, out var itemNumber))
|
|
|
{
|
|
|
- // Theoretically shouldn't happen, but just in case.
|
|
|
- MessageBox.Show($"Warning: Multiple PurchaseOrder Items have the same line number for export; the line number for '{purchaseOrderItem.Description}' will be changed in the export.");
|
|
|
- Logger.Send(LogType.Error, "", $"Purchase Order Post: Multiple POItems with the same Line Number; changing line number of POItem {purchaseOrderItem.ID}");
|
|
|
- purchaseOrderItem.PostedReference = "";
|
|
|
+ if (items.TryGetValue(itemNumber, out var oldItem))
|
|
|
+ {
|
|
|
+ // Theoretically shouldn't happen, but just in case.
|
|
|
+ MessageBox.Show($"Warning: Multiple PurchaseOrder Items have the same line number for export; the line number for '{purchaseOrderItem.Description}' will be changed in the export.");
|
|
|
+ Logger.Send(LogType.Error, "", $"Purchase Order Post: Multiple POItems with the same Line Number; changing line number of POItem {purchaseOrderItem.ID}");
|
|
|
+ purchaseOrderItem.PostedReference = "";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ items[itemNumber] = purchaseOrderItem;
|
|
|
+ }
|
|
|
}
|
|
|
- else
|
|
|
+ }
|
|
|
+
|
|
|
+ var success = true;
|
|
|
+ foreach (var purchaseOrderItem in POItems)
|
|
|
+ {
|
|
|
+ if (!int.TryParse(purchaseOrderItem.PostedReference, out var itemNumber))
|
|
|
{
|
|
|
+ itemNumber = 1;
|
|
|
+ while (items.ContainsKey(itemNumber))
|
|
|
+ {
|
|
|
+ ++itemNumber;
|
|
|
+ }
|
|
|
+
|
|
|
items[itemNumber] = purchaseOrderItem;
|
|
|
+ purchaseOrderItem.PostedReference = itemNumber.ToString();
|
|
|
}
|
|
|
+ var ci = new PurchaseOrderTimberlineLine
|
|
|
+ {
|
|
|
+ CommitmentID = purchaseOrder.PONumber,
|
|
|
+ ItemNumber = itemNumber,
|
|
|
+ Description = purchaseOrderItem.Description,
|
|
|
+ // RetainagePercent = ,
|
|
|
+ DeliveryDate = purchaseOrderItem.ReceivedDate,
|
|
|
+ //ScopeOfWork
|
|
|
+ Job = purchaseOrderItem.Job.JobNumber,
|
|
|
+ //Extra = purchaseOrderItem.Job
|
|
|
+ CostCode = purchaseOrderItem.CostCentre.Code,
|
|
|
+ //Category = purchaseOrderItem.cat
|
|
|
+ TaxGroup = purchaseOrderItem.TaxCode.Code,
|
|
|
+ Units = purchaseOrderItem.Qty,
|
|
|
+ UnitCost = purchaseOrderItem.Cost,
|
|
|
+ UnitDescription = purchaseOrderItem.Dimensions.UnitSize,
|
|
|
+ Amount = purchaseOrderItem.IncTax,
|
|
|
+ // BoughtOut
|
|
|
+ };
|
|
|
+
|
|
|
+ if(!ProcessLine(model, purchaseOrderItem, ci))
|
|
|
+ {
|
|
|
+ success = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ c.Lines.Add(ci);
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- foreach (var purchaseOrderItem in POItems)
|
|
|
- {
|
|
|
- if (!int.TryParse(purchaseOrderItem.PostedReference, out var itemNumber))
|
|
|
+ if (success)
|
|
|
{
|
|
|
- itemNumber = 1;
|
|
|
- while(items.ContainsKey(itemNumber))
|
|
|
+ foreach(var item in POItems)
|
|
|
{
|
|
|
- ++itemNumber;
|
|
|
+ cs.AddFragment(item);
|
|
|
}
|
|
|
-
|
|
|
- items[itemNumber] = purchaseOrderItem;
|
|
|
- purchaseOrderItem.PostedReference = itemNumber.ToString();
|
|
|
+ cs.AddSuccess(purchaseOrder, c);
|
|
|
}
|
|
|
- var ci = new PurchaseOrderTimberlineLine
|
|
|
+ else
|
|
|
{
|
|
|
- CommitmentID = purchaseOrder.PONumber,
|
|
|
- ItemNumber = itemNumber,
|
|
|
- Description = purchaseOrderItem.Description,
|
|
|
- // RetainagePercent = ,
|
|
|
- DeliveryDate = purchaseOrderItem.ReceivedDate,
|
|
|
- //ScopeOfWork
|
|
|
- Job = purchaseOrderItem.Job.JobNumber,
|
|
|
- //Extra = purchaseOrderItem.Job
|
|
|
- CostCode = purchaseOrderItem.CostCentre.Code,
|
|
|
- //Category = purchaseOrderItem.cat
|
|
|
- TaxGroup = purchaseOrderItem.TaxCode.Code,
|
|
|
- Units = purchaseOrderItem.Qty,
|
|
|
- UnitCost = purchaseOrderItem.Cost,
|
|
|
- UnitDescription = purchaseOrderItem.Dimensions.UnitSize,
|
|
|
- Amount = purchaseOrderItem.IncTax,
|
|
|
- // BoughtOut
|
|
|
- };
|
|
|
-
|
|
|
- ProcessLine(model, purchaseOrderItem, ci);
|
|
|
- c.Lines.Add(ci);
|
|
|
-
|
|
|
- AddFragment?.Invoke(purchaseOrderItem);
|
|
|
+ cs.AddFailed(purchaseOrder, "Failed by script.");
|
|
|
+ }
|
|
|
}
|
|
|
- cs.Add(c);
|
|
|
}
|
|
|
return cs;
|
|
|
}
|
|
|
|
|
|
- public bool Process(IDataModel<PurchaseOrder> model)
|
|
|
+ public IPostResult<PurchaseOrder> Process(IDataModel<PurchaseOrder> model)
|
|
|
{
|
|
|
var POs = DoProcess(model);
|
|
|
|
|
@@ -352,7 +373,7 @@ public class Module
|
|
|
using (var writer = new StreamWriter(dlg.FileName))
|
|
|
{
|
|
|
using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);
|
|
|
- foreach (var header in POs)
|
|
|
+ foreach (var header in POs.Exports)
|
|
|
{
|
|
|
// Write the record.
|
|
|
csv.WriteRecord(header);
|
|
@@ -414,23 +435,49 @@ public class Module
|
|
|
var id = csv.GetField(0);
|
|
|
if(id == "C")
|
|
|
{
|
|
|
- rejectedHeaders.Add(csv.GetRecord<PurchaseOrderTimberlineHeader>());
|
|
|
+ var header = csv.GetRecord<PurchaseOrderTimberlineHeader>();
|
|
|
+ if(header is not null)
|
|
|
+ {
|
|
|
+ var entry = POs.Items.FirstOrDefault(x => x.Item2?.CommitmentID.Equals(header.CommitmentID) == true);
|
|
|
+ if(entry is not null)
|
|
|
+ {
|
|
|
+ (entry.Item1 as IPostable).FailPost("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Logger.Send(LogType.Error, "", "PO Timberline export: Unable to parse header from CSV line in rejection file.");
|
|
|
+ MessageBox.Show("Invalid line in file; skipping.");
|
|
|
+ }
|
|
|
}
|
|
|
else if(id == "CI")
|
|
|
{
|
|
|
- rejectedLines.Add(csv.GetRecord<PurchaseOrderTimberlineLine>());
|
|
|
+ var line = csv.GetRecord<PurchaseOrderTimberlineLine>();
|
|
|
+ if (line is not null)
|
|
|
+ {
|
|
|
+ var entry = POs.Items.FirstOrDefault(x => x.Item2?.CommitmentID.Equals(line.CommitmentID) == true);
|
|
|
+ if (entry is not null)
|
|
|
+ {
|
|
|
+ (entry.Item1 as IPostable).FailPost("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Logger.Send(LogType.Error, "", "PO Timberline export: Unable to parse line from CSV line in rejection file.");
|
|
|
+ MessageBox.Show("Invalid line in file; skipping.");
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return true;
|
|
|
+ return POs;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new PostCancelledException();
|
|
|
}
|
|
|
}
|
|
|
- public void AfterPost(IDataModel<PurchaseOrder> model)
|
|
|
+ public void AfterPost(IDataModel<PurchaseOrder> model, IPostResult<PurchaseOrder> result)
|
|
|
{
|
|
|
Script?.Execute(methodname: "AfterPost", parameters: new object[] { model });
|
|
|
}
|