Created
October 26, 2021 14:06
-
-
Save BrianMRO/b8e9a1bab9d047f44c461b11791257c9 to your computer and use it in GitHub Desktop.
Create Purchase Orders Without Merging Demand Into Single PO Lines - Full Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region CreatePOOrders - Replace base version (clone and inject code) | |
public static PXRedirectRequiredException CreatePOOrders(List<POFixedDemand> list, DateTime? PurchDate, bool extSort) | |
{ | |
POOrderEntry docgraph = PXGraph.CreateInstance<POOrderEntry>(); | |
docgraph.Views.Caches.Add(typeof(SOLineSplit3)); | |
POSetup setup = docgraph.POSetup.Current; | |
DocumentList<POOrder> created = new DocumentList<POOrder>(docgraph); | |
Dictionary<String, DocumentList<POLine>> orderedByPlantype = new Dictionary<String, DocumentList<POLine>>(); | |
DocumentList<POLine> ordered; | |
list = docgraph.SortPOFixDemandList(list); | |
POOrder order = null; | |
bool hasErrors = false; | |
foreach (POFixedDemand demand in list) | |
{ | |
if (demand.FixedSource != INReplenishmentSource.Purchased) | |
continue; | |
string OrderType = | |
demand.PlanType == INPlanConstants.Plan6D ? POOrderType.DropShip : | |
demand.PlanType == INPlanConstants.Plan6E ? POOrderType.DropShip : | |
POOrderType.RegularOrder; | |
string replanType = null; | |
if (demand.VendorID == null || demand.VendorLocationID == null) | |
{ | |
PXProcessing<POFixedDemand>.SetWarning(list.IndexOf(demand), Messages.MissingVendorOrLocation); | |
continue; | |
} | |
PXErrorLevel ErrorLevel = PXErrorLevel.RowInfo; | |
string ErrorText = string.Empty; | |
try | |
{ | |
SOOrder soorder = PXSelect<SOOrder, Where<SOOrder.noteID, Equal<Required<SOOrder.noteID>>>>.Select(docgraph, demand.RefNoteID); | |
SOLineSplit3 soline = PXSelect<SOLineSplit3, Where<SOLineSplit3.planID, Equal<Required<SOLineSplit3.planID>>>>.Select(docgraph, demand.PlanID); | |
if (soline?.POSource.IsIn(INReplenishmentSource.DropShipToOrder, INReplenishmentSource.BlanketDropShipToOrder) == true && soline.IsValidForDropShip != true) | |
{ | |
throw new PXException(SO.Messages.DropShipSOLineCantHaveMultipleSplitsOrAllocation); | |
} | |
string BLType = null; | |
string BLOrderNbr = null; | |
if (demand.PlanType == INPlanConstants.Plan6B || | |
demand.PlanType == INPlanConstants.Plan6E) | |
{ | |
BLType = soline.POType; | |
BLOrderNbr = soline.PONbr; | |
} | |
var orderSearchValues = new List<FieldLookup>() | |
{ | |
new FieldLookup<POOrder.orderType>(OrderType), | |
new FieldLookup<POOrder.vendorID>(demand.VendorID), | |
new FieldLookup<POOrder.vendorLocationID>(demand.VendorLocationID), | |
new FieldLookup<POOrder.bLOrderNbr>(BLOrderNbr), | |
}; | |
if (OrderType == POOrderType.RegularOrder) | |
{ | |
bool requireSingleProject = (docgraph.apsetup.Current.RequireSingleProjectPerDocument == true); | |
if (requireSingleProject) | |
{ | |
int? project = demand.ProjectID ?? PM.ProjectDefaultAttribute.NonProject(); | |
orderSearchValues.Add(new FieldLookup<POOrder.projectID>(project)); | |
} | |
if (order != null && order.ShipDestType == POShippingDestination.CompanyLocation && order.SiteID == null) | |
{ | |
//When previous order was shipped to Company then we would never find it if we search by POSiteID | |
} | |
else | |
{ | |
orderSearchValues.Add(new FieldLookup<POOrder.siteID>(demand.POSiteID)); | |
} | |
} | |
else if (OrderType == POOrderType.DropShip) | |
{ | |
orderSearchValues.Add(new FieldLookup<POOrder.sOOrderType>(soline.OrderType)); | |
orderSearchValues.Add(new FieldLookup<POOrder.sOOrderNbr>(soline.OrderNbr)); | |
} | |
else | |
{ | |
orderSearchValues.Add(new FieldLookup<POOrder.shipToBAccountID>(soorder.CustomerID)); | |
orderSearchValues.Add(new FieldLookup<POOrder.shipToLocationID>(soorder.CustomerLocationID)); | |
orderSearchValues.Add(new FieldLookup<POOrder.siteID>(demand.POSiteID)); | |
} | |
order = created.Find(orderSearchValues.ToArray()) ?? new POOrder(); | |
if (order.OrderNbr == null) | |
{ | |
docgraph.Clear(); | |
order.OrderType = OrderType; | |
order = PXCache<POOrder>.CreateCopy(docgraph.Document.Insert(order)); | |
order.VendorID = demand.VendorID; | |
order.VendorLocationID = demand.VendorLocationID; | |
order.SiteID = demand.POSiteID; | |
if (demand.ProjectID != null) | |
{ | |
order.ProjectID = demand.ProjectID; | |
} | |
order.OrderDate = PurchDate; | |
order.BLType = BLType; | |
order.BLOrderNbr = BLOrderNbr; | |
if (OrderType == POOrderType.DropShip || extSort) | |
{ | |
order.SOOrderType = soline.OrderType; | |
order.SOOrderNbr = soline.OrderNbr; | |
} | |
if (!string.IsNullOrEmpty(order.BLOrderNbr)) | |
{ | |
POOrder blanket = PXSelect<POOrder, Where<POOrder.orderType, Equal<Current<POOrder.bLType>>, And<POOrder.orderNbr, Equal<Current<POOrder.bLOrderNbr>>>>>.SelectSingleBound(docgraph, new object[] { order }); | |
if (blanket != null) | |
{ | |
order.VendorRefNbr = blanket.VendorRefNbr; | |
} | |
} | |
if (OrderType == POOrderType.DropShip) | |
{ | |
order.ShipDestType = POShippingDestination.Customer; | |
order.ShipToBAccountID = soorder.CustomerID; | |
order.ShipToLocationID = soorder.CustomerLocationID; | |
} | |
else if (setup.ShipDestType == POShipDestType.Site) | |
{ | |
order.ShipDestType = POShippingDestination.Site; | |
order.SiteID = demand.POSiteID; | |
} | |
if (PXAccess.FeatureInstalled<FeaturesSet.multicurrency>()) | |
{ | |
//GetValuePending will fall in CurrencyInfo_CuryIdFieldSelecting() | |
docgraph.currencyinfo.Current.CuryID = null; | |
} | |
order = docgraph.Document.Update(order); | |
if (OrderType == POOrderType.DropShip) | |
{ | |
SOAddress soAddress = PXSelect<SOAddress, Where<SOAddress.addressID, Equal<Required<SOOrder.shipAddressID>>>>.Select(docgraph, soorder.ShipAddressID); | |
if (soAddress.IsDefaultAddress == false) | |
{ | |
AddressAttribute.CopyRecord<POOrder.shipAddressID>(docgraph.Document.Cache, order, soAddress, true); | |
} | |
SOContact soContact = PXSelect<SOContact, Where<SOContact.contactID, Equal<Required<SOOrder.shipContactID>>>>.Select(docgraph, soorder.ShipContactID); | |
if (soContact.IsDefaultContact == false) | |
{ | |
ContactAttribute.CopyRecord<POOrder.shipContactID>(docgraph.Document.Cache, order, soContact, true); | |
} | |
if (order.ExpectedDate < soorder.RequestDate) | |
{ | |
order = PXCache<POOrder>.CreateCopy(order); | |
order.ExpectedDate = soorder.RequestDate; | |
order = docgraph.Document.Update(order); | |
} | |
} | |
} | |
else if (docgraph.Document.Cache.ObjectsEqual(docgraph.Document.Current, order) == false) | |
{ | |
docgraph.Document.Current = docgraph.Document.Search<POOrder.orderNbr>(order.OrderNbr, order.OrderType); | |
} | |
//we do not want vendor inventory updated in this case | |
order.UpdateVendorCost = false; | |
POLine line = null; | |
//Sales Orders to Blanket should not be grouped together | |
//Drop Ships to Blankets are not grouped either | |
if (!orderedByPlantype.TryGetValue(demand.PlanType, out ordered)) | |
{ | |
ordered = orderedByPlantype[demand.PlanType] = new DocumentList<POLine>(docgraph); | |
} | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
// Get MyField from Plan - stored in INItemPlanExt | |
INItemPlan plan = demand as INItemPlan; | |
INItemPlanExt planExt = plan.GetExtension<INItemPlanExt>(); | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
if (OrderType == POOrderType.RegularOrder && demand.PlanType != INPlanConstants.Plan6B) | |
{ | |
var lineSearchValues = new List<FieldLookup>() | |
{ | |
new FieldLookup<POLine.vendorID>(demand.VendorID), | |
new FieldLookup<POLine.vendorLocationID>(demand.VendorLocationID), | |
new FieldLookup<POLine.siteID>(demand.POSiteID), | |
new FieldLookup<POLine.inventoryID>(demand.InventoryID), | |
new FieldLookup<POLine.subItemID>(demand.SubItemID), | |
new FieldLookup<POLine.requestedDate>(soline?.ShipDate), | |
new FieldLookup<POLine.projectID>(soline?.ProjectID), | |
new FieldLookup<POLine.taskID>(soline?.TaskID), | |
new FieldLookup<POLine.costCodeID>(soline?.CostCodeID), | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//Add MyField to Search | |
new FieldLookup<POLineExt.usrXXMyField>(planExt?.UsrXXMyField), | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
}; | |
if (setup.CopyLineDescrSO == true && soline != null) | |
{ | |
lineSearchValues.Add(new FieldLookup<POLine.tranDesc>(soline.TranDesc)); | |
line = ordered.Find(lineSearchValues.ToArray()); | |
if (line != null && setup.CopyLineNoteSO == true && | |
(PXNoteAttribute.GetNote(docgraph.Caches[typeof(POLine)], line) != null || PXNoteAttribute.GetNote(docgraph.Caches[typeof(SOLineSplit3)], soline) != null)) | |
{ | |
line = null; | |
} | |
} | |
else | |
line = ordered.Find(lineSearchValues.ToArray()); | |
} | |
line = line ?? new POLine(); | |
if (line.OrderNbr == null) | |
{ | |
docgraph.FillPOLineFromDemand(line, demand, OrderType, soline); | |
line = docgraph.Transactions.Insert(line); | |
if (setup.CopyLineNoteSO == true && soline != null) | |
{ | |
PXNoteAttribute.SetNote(docgraph.Transactions.Cache, line, | |
PXNoteAttribute.GetNote(docgraph.Caches[typeof(SOLineSplit3)], soline)); | |
} | |
if (docgraph.onCopyPOLineFields != null) | |
{ | |
docgraph.onCopyPOLineFields(demand, line); | |
} | |
line = PXCache<POLine>.CreateCopy(line); | |
ordered.Add(line); | |
} | |
else | |
{ | |
line = (POLine) | |
PXSelect<POLine, | |
Where<POLine.orderType, Equal<Current<POOrder.orderType>>, | |
And<POLine.orderNbr, Equal<Current<POOrder.orderNbr>>, | |
And<POLine.lineNbr, Equal<Current<POLine.lineNbr>>>>>> | |
.SelectSingleBound(docgraph, new object[] { line }); | |
line = PXCache<POLine>.CreateCopy(line); | |
line.OrderQty += demand.OrderQty; | |
} | |
if (demand.PlanType == INPlanConstants.Plan6B || | |
demand.PlanType == INPlanConstants.Plan6E) | |
{ | |
replanType = | |
demand.PlanType == INPlanConstants.Plan6B | |
? INPlanConstants.Plan66 | |
: INPlanConstants.Plan6D; | |
demand.FixedSource = INReplenishmentSource.Purchased; | |
line.POType = soline.POType; | |
line.PONbr = soline.PONbr; | |
line.POLineNbr = soline.POLineNbr; | |
POLine blanket_line = | |
PXSelect<POLine, | |
Where<POLine.orderType, Equal<Current<POLine.pOType>>, | |
And<POLine.orderNbr, Equal<Current<POLine.pONbr>>, | |
And<POLine.lineNbr, Equal<Current<POLine.pOLineNbr>>>>>> | |
.SelectSingleBound(docgraph, new object[] { line }); | |
if (blanket_line != null) | |
{ | |
//POOrderEntry() is persisted on each loop, BaseOpenQty will include everything in List<POLine> ordered | |
if (demand.PlanQty > blanket_line.BaseOpenQty) | |
{ | |
line.OrderQty -= demand.OrderQty; | |
if (string.Equals(line.UOM, blanket_line.UOM)) | |
{ | |
line.OrderQty += blanket_line.OpenQty; | |
} | |
else | |
{ | |
PXDBQuantityAttribute.CalcBaseQty<POLine.orderQty>(docgraph.Transactions.Cache, line); | |
line.BaseOrderQty += blanket_line.BaseOpenQty; | |
PXDBQuantityAttribute.CalcTranQty<POLine.orderQty>(docgraph.Transactions.Cache, line); | |
} | |
ErrorLevel = PXErrorLevel.RowWarning; | |
ErrorText += PXMessages.LocalizeFormatNoPrefixNLA(Messages.QuantityReducedToBlanketOpen, line.PONbr); | |
} | |
line.CuryUnitCost = blanket_line.CuryUnitCost; | |
line.UnitCost = blanket_line.UnitCost; | |
} | |
} | |
line = docgraph.Transactions.Update(line); | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
// Save MyField to PO Line | |
POLineExt lineExt = line.GetExtension<POLineExt>(); | |
lineExt.UsrXXMyField = planExt.UsrXXMyField; | |
docgraph.Caches[typeof(POLine)].Update(lineExt); | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
//////////////////////////////////////// | |
var dsLinksExt = docgraph.GetExtension<DropShipLinksExt>(); | |
if (soline != null && line.LineType.IsIn(POLineType.GoodsForDropShip, POLineType.NonStockForDropShip) && dsLinksExt != null) | |
{ | |
DropShipLink newLink = new DropShipLink(); | |
newLink.POOrderType = line.OrderType; | |
newLink.POOrderNbr = line.OrderNbr; | |
newLink.POLineNbr = line.LineNbr; | |
newLink.SOOrderType = soline.OrderType; | |
newLink.SOOrderNbr = soline.OrderNbr; | |
newLink.SOLineNbr = soline.LineNbr; | |
newLink.Active = true; | |
newLink.POInventoryID = soline.InventoryID; | |
newLink.POSiteID = soline.SiteID; | |
newLink.POBaseOrderQty = soline.BaseOrderQty; | |
newLink.SOInventoryID = soline.InventoryID; | |
newLink.SOSiteID = soline.SiteID; | |
newLink.SOBaseOrderQty = soline.BaseOrderQty; | |
dsLinksExt.DropShipLinks.Insert(newLink); | |
} | |
PXCache cache = docgraph.Caches[typeof(INItemPlan)]; | |
CreateSplitDemand(cache, demand); | |
cache.SetStatus(demand, PXEntryStatus.Updated); | |
demand.SupplyPlanID = line.PlanID; | |
if (replanType != null) | |
{ | |
cache.RaiseRowDeleted(demand); | |
demand.PlanType = replanType; | |
cache.RaiseRowInserted(demand); | |
} | |
if (soline != null) | |
{ | |
if (demand.AlternateID != null && demand.InventoryID != null) | |
{ | |
PXSelectBase<INItemXRef> xref = new PXSelect<INItemXRef, | |
Where<INItemXRef.inventoryID, Equal<Required<INItemXRef.inventoryID>>, | |
And<INItemXRef.alternateID, Equal<Required<INItemXRef.alternateID>>>>>(docgraph); | |
INItemXRef soXRef = xref.Select(demand.InventoryID, demand.AlternateID); | |
if (soXRef != null && soXRef.AlternateType == INAlternateType.Global) | |
{ | |
if (line.AlternateID != null && line.InventoryID != null) | |
{ | |
INItemXRef poXRef = xref.Select(line.InventoryID, line.AlternateID); | |
if (poXRef != null && poXRef.AlternateType == INAlternateType.Global) | |
{ | |
line.AlternateID = demand.AlternateID; | |
} | |
} | |
else | |
{ | |
line.AlternateID = demand.AlternateID; | |
} | |
} | |
} | |
soline.POType = line.OrderType; | |
soline.PONbr = line.OrderNbr; | |
soline.POLineNbr = line.LineNbr; | |
soline.RefNoteID = docgraph.Document.Current.NoteID; | |
string targetPOSource = soline.POSource == INReplenishmentSource.BlanketDropShipToOrder ? INReplenishmentSource.DropShipToOrder | |
: soline.POSource == INReplenishmentSource.BlanketPurchaseToOrder ? INReplenishmentSource.PurchaseToOrder | |
: null; | |
if (targetPOSource != null) | |
{ | |
soline.POSource = targetPOSource; | |
POOrderEntry.SOLine5 origsoline = docgraph.FixedDemandOrigSOLine.Select(soline.OrderType, soline.OrderNbr, soline.LineNbr); | |
if (origsoline != null) | |
{ | |
origsoline.POSource = targetPOSource; | |
docgraph.FixedDemandOrigSOLine.Cache.MarkUpdated(origsoline); | |
} | |
} | |
var docgraphext = docgraph.GetExtension<POOrderEntry_Extension>(); | |
docgraphext.UpdateSOLine(soline, docgraph.Document.Current.VendorID, true); | |
docgraph.FixedDemand.Cache.SetStatus(soline, PXEntryStatus.Updated); | |
} | |
if (docgraph.Transactions.Cache.IsInsertedUpdatedDeleted) | |
{ | |
using (PXTransactionScope scope = new PXTransactionScope()) | |
{ | |
docgraph.Save.Press(); | |
if (demand.PlanType == INPlanConstants.Plan90) | |
{ | |
docgraph.Replenihment.Current = docgraph.Replenihment.Search<INReplenishmentOrder.noteID>(demand.RefNoteID); | |
if (docgraph.Replenihment.Current != null) | |
{ | |
INReplenishmentLine rLine = | |
PXCache<INReplenishmentLine>.CreateCopy(docgraph.ReplenishmentLines.Insert(new INReplenishmentLine())); | |
rLine.InventoryID = line.InventoryID; | |
rLine.SubItemID = line.SubItemID; | |
rLine.UOM = line.UOM; | |
rLine.VendorID = line.VendorID; | |
rLine.VendorLocationID = line.VendorLocationID; | |
rLine.Qty = line.OrderQty; | |
rLine.POType = line.OrderType; | |
rLine.PONbr = docgraph.Document.Current.OrderNbr; | |
rLine.POLineNbr = line.LineNbr; | |
rLine.SiteID = demand.POSiteID; | |
rLine.PlanID = demand.PlanID; | |
docgraph.ReplenishmentLines.Update(rLine); | |
docgraph.Caches[typeof(INItemPlan)].Delete(demand); | |
docgraph.Save.Press(); | |
} | |
} | |
scope.Complete(); | |
} | |
if (ErrorLevel == PXErrorLevel.RowInfo) | |
{ | |
PXProcessing<POFixedDemand>.SetInfo(list.IndexOf(demand), PXMessages.LocalizeFormatNoPrefixNLA(Messages.PurchaseOrderCreated, docgraph.Document.Current.OrderNbr) + "\r\n" + ErrorText); | |
} | |
else | |
{ | |
PXProcessing<POFixedDemand>.SetWarning(list.IndexOf(demand), PXMessages.LocalizeFormatNoPrefixNLA(Messages.PurchaseOrderCreated, docgraph.Document.Current.OrderNbr) + "\r\n" + ErrorText); | |
} | |
if (created.Find(docgraph.Document.Current) == null) | |
{ | |
created.Add(docgraph.Document.Current); | |
} | |
} | |
} | |
catch (Exception e) | |
{ | |
PXProcessing<POFixedDemand>.SetError(list.IndexOf(demand), e); | |
PXTrace.WriteError(e); | |
hasErrors = true; | |
} | |
} | |
if (!hasErrors && created.Count == 1) | |
{ | |
using (new PXTimeStampScope(null)) | |
{ | |
docgraph.Clear(); | |
docgraph.Document.Current = docgraph.Document.Search<POOrder.orderNbr>(created[0].OrderNbr, created[0].OrderType); | |
return new PXRedirectRequiredException(docgraph, Messages.POOrder); | |
} | |
} | |
return null; | |
} | |
#endregion | |
#region CreateSplitDemand - Copy Private Static Method From Base | |
private static void CreateSplitDemand(PXCache cache, POFixedDemand demand) | |
{ | |
if (demand.OrderQty != demand.PlanUnitQty) | |
{ | |
INItemPlan orig_demand = PXSelectReadonly<INItemPlan, | |
Where<INItemPlan.planID, Equal<Current<INItemPlan.planID>>>> | |
.SelectSingleBound(cache.Graph, new object[] { demand }); | |
INItemPlan split = PXCache<INItemPlan>.CreateCopy(orig_demand); | |
split.PlanID = null; | |
split.PlanQty = demand.PlanUnitQty - demand.OrderQty; | |
if (demand.UnitMultDiv == MultDiv.Multiply) | |
split.PlanQty *= demand.UnitRate; | |
else | |
split.PlanQty /= demand.UnitRate; | |
cache.Insert(split); | |
cache.RaiseRowDeleted(demand); | |
demand.PlanQty = orig_demand.PlanQty - split.PlanQty; | |
cache.RaiseRowInserted(demand); | |
} | |
} | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment