Error when creating a Sales Order using the graph object - acumatica

I'm trying to create a Sales Order from the PO screen using the SOOrderEntry graph object. I'm selecting the branch using a technique from another Stack Overflow case, and I continuously get the following error:
I can't figure out why this error is coming up, since I'm setting the CustomerID. Here's the code:
public class POOrderEntryExt : PXGraphExtension<POOrderEntry>
{
public override void Initialize()
{
Base.action.AddMenuAction(CreateSO);
}
public PXAction<POOrder> CreateSO;
[PXUIField(DisplayName = "Create Sales Order", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXButton]
protected virtual void createSO()
{
SOOrderEntry sograph = null;
SOOrder soorder = null;
SOLine soline = null;
//Let's get the current data from the screen we're in...
var poorder = (POOrder)Base.Document.Current;
PXResultset<POLine> res = PXSelect<POLine, Where<POLine.orderNbr, Equal<Required<POLine.orderNbr>>>>.Select(Base, poorder.OrderNbr);
using (PXLoginScope ls = new PXLoginScope("admin"))
{
//Create a new instance of the AP Bills screen graph..
sograph = PXGraph.CreateInstance<SOOrderEntry>();
//Get the branch...
var branch = (Branch)PXSelect<Branch, Where<Branch.branchCD, Equal<Required<Branch.branchCD>>>>.Select(Base, "WI-NVC VET");
//soorder.BranchID = branch.BranchID;
//This handler is added per RD from another Stack Overflow case. It's necessary to select the Branch...
sograph.FieldDefaulting.AddHandler<SOOrder.branchID>((s, e) =>
{
e.NewValue = branch.BranchID;
e.Cancel = true;
});
soorder = new SOOrder();
//The OrderType...
soorder.OrderType = SOOrderTypeConstants.SalesOrder;
sograph.Document.Insert(soorder);
soorder.OrderDate = (DateTime?)DateTime.Now;
soorder.RequestDate = (DateTime?)DateTime.Now;
//Get the customer id...
var bacct = (BAccountR)PXSelect<BAccountR, Where<BAccountR.acctCD, Equal<Required<BAccountR.acctCD>>>>.Select(Base, "NE-C003118");
soorder.CustomerID = bacct.BAccountID; // (int?)5454;
sograph.Document.Update(soorder);
sograph.Actions.PressSave();

This is very import to always assign the result of PXCache Insert or Update method invocation to some local variable so further you make changes to the object from the cache, rather than to a legacy record, which has nothing in common with PXCache.
The issue should be resolved by the following tiny change:
soorder = new SOOrder();
soorder.OrderType = SOOrderTypeConstants.SalesOrder;
soorder = sograph.Document.Insert(soorder);

Related

Why is my hyperlink / button in the grid to launch a screen disabled?

I have a customization to the Sales Orders screen, where I've added a user field (non-bound / [PXString] to hold the value of a PO Receipt Nbr. I populate it with the RowSelected event, and I'm trying to launch the Purchase Receipts screen from that field with a PXAction tied to that field's Linked Command:
The Field:
public abstract class usrPOReceiptNbr : BqlString.Field<usrPOReceiptNbr> { }
[PXString(15, IsUnicode = true)]
[PXUIField(DisplayName = "PO Receipt Nbr", Enabled = true)]
public virtual string UsrPOReceiptNbr { get; set; }
The RowSelected event code to populate the field:
var soordershipment = e.Row as SOOrderShipment;
using (new PXConnectionScope())
{
//get the extension
var soordershipmentext = PXCache<SOOrderShipment>.GetExtension<SOOrderShipmentExt>(soordershipment);
//Get the soorder cache...
SOOrder soorder = Base.Document.Current;
if (soorder != null)
{
//Now get the POReceiptLine record:
PXResultset<POReceiptLine> res = PXSelectJoin<POReceiptLine,
InnerJoin<SOOrder,
On<SOOrder.orderNbr, Equal<POReceiptLine.sOOrderNbr>,
And<SOOrder.orderType, Equal<POReceiptLine.sOOrderType>>>>,
Where<SOOrder.orderNbr, Equal<Required<SOOrder.orderNbr>>>,
OrderBy<Desc<POReceiptLine.receiptNbr>>>.Select(Base, soorder.OrderNbr);
foreach (PXResult<POReceiptLine> rec in res)
{
POReceiptLine porl = (POReceiptLine)rec;
soordershipmentext.UsrPOReceiptNbr = porl.ReceiptNbr;
break; //Stop after the first record, since I only want the highest sorted field
}
}
}
The code to launch the Purchase Receipts screen is as follows:
public PXAction<SOOrder> LaunchPurchaseReceipts;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Launch Purchase Receipts", Enabled = true)]
protected virtual IEnumerable launchPurchaseReceipts(PXAdapter adapter)
{
var soorder = (SOOrder)Base.Document.Current;
POReceiptEntry graph = PXGraph.CreateInstance<POReceiptEntry>();
var soordershipment = (SOOrderShipment)Base.shipmentlist.Current;
var soordershipmentext = PXCache<SOOrderShipment>.GetExtension<SOOrderShipmentExt>(soordershipment);
graph.Document.Current = graph.Document.Search<POReceipt.receiptNbr, POReceipt.receiptType>(soordershipmentext.UsrPOReceiptNbr, soordershipment.ShipmentType);
throw new PXRedirectRequiredException(graph, "Purchase Receipts")
{
Mode = PXBaseRedirectException.WindowMode.NewWindow
};
}
The problem is that I continue to get this error when launching the hyperlink on the PO Receipt Nbr field for that screen (it never even gets to the code to launch the screen):
...and here's the error...
I've tried forcing the field to enabled with the RowSelected event, using:
PXUIFieldAttribute.SetEnabled<SOOrderShipmentExt.usrPOReceiptNbr>(e.Cache, null, true);
But that doesn't do anything.
Any ideas?
This issue has been resolved with a suggestion from Brendan (thanks much) by using the RowSelected event to set the method's enabled property to true:
LaunchPurchaseReceipts.SetEnabled(true);

Hiding custom fields in copy past option

How to hide a field while copy and past. The field is part of the extension of the sales order.DAC.
I have tried [PXCopyPasteHiddenFields(typeof(PSSOOrderExtNV.usrIsInHandsDate))] and I am getting the following compilation error.
Error CS0592 Attribute 'PXCopyPasteHiddenFields' is not valid on this declaration type. It is only valid on 'class, field' declarations.
I have tried to Override the method CopyPasteGetScript I did not get the desired result.
public delegate void CopyPasteGetScriptDelegate(Boolean isImportSimple, List<Command> script, List<Container> containers);
[PXOverride]
public void CopyPasteGetScript(Boolean isImportSimple, List<Command> script, List<Container> containers, CopyPasteGetScriptDelegate baseMethod)
{
baseMethod(isImportSimple, script, containers);
SOOrder order = Base.Document.Current;
if(Base.Document.Cache.GetStatus(order) == PXEntryStatus.Inserted)
{
PSSOOrderExtNV extn = PXCache<SOOrder>.GetExtension<PSSOOrderExtNV>(order);
extn.UsrHoldUntil = null;
extn.UsrReadyforProductionapproval = null;
extn.UsrReadyForProduction = null;
extn.UsrIsOrdered = null;
extn.UsrIsAllocated = null;
extn.UsrEmbPaperReceived = null;
extn.UsrEmbGoodsReceived = null;
extn.UsrWorksheetPrinted = null;
extn.UsrGoodsOnCarts = null;
Base.Document.Update(order);
}
}
Update
I have modified the code as bellow in graph extension of SOOrderEntry. It is not giving error while compiling, but it is copying the values to new order.
[PXCopyPasteHiddenFields(typeof(SOOrder.cancelled), typeof(SOOrder.preAuthTranNumber), typeof(SOOrder.ownerID), typeof(SOOrder.workgroupID),
typeof(PSSOOrderExtNV.usrHoldUntil),typeof(PSSOOrderExtNV.usrReadyForProduction),typeof(PSSOOrderExtNV.usrReadyforProductionapproval),typeof(PSSOOrderExtNV.usrIsOrdered),
typeof(PSSOOrderExtNV.usrIsAllocated),typeof(PSSOOrderExtNV.usrEmbPaperReceived),typeof(PSSOOrderExtNV.usrEmbGoodsReceived),typeof(PSSOOrderExtNV.usrWorksheetPrinted),
typeof(PSSOOrderExtNV.usrGoodsOnCarts))]
public PXSelect<SOOrder, Where<SOOrder.orderType, Equal<Current<SOOrder.orderType>>, And<SOOrder.orderNbr, Equal<Current<SOOrder.orderNbr>>>>> CurrentDocument;
PXCopyPasteHiddenFields attribute typically decorates DataViews.
This example in Sales Order graph, hides the SOLine.Completed field from the Transactions DataView:
[PXViewName(Messages.SOLine)]
[PXImport(typeof(SOOrder))]
[PXCopyPasteHiddenFields(typeof(SOLine.completed))]
public PXOrderedSelect<SOOrder, SOLine,
Where<SOLine.orderType, Equal<Current<SOOrder.orderType>>,
And<SOLine.orderNbr, Equal<Current<SOOrder.orderNbr>>>>,
OrderBy<Asc<SOLine.orderType, Asc<SOLine.orderNbr, Asc<SOLine.sortOrder, Asc<SOLine.lineNbr>>>>>> Transactions;

Acumatica Redirect to a Dashboard and pass parameter value issue

I'm successfully redirecting to a Dashboard passing parameter from Customers screen (AR303000) but, not able to replicate the result when I redirect to the Dashboard from Customer Pop Up Panel. it call the Dashboard without the parameter. I can see the code passing the value correctly, but the Dashboard does not display any value.
Any Help will be appreciated.
Thanks.
Alfredo
Here is a copy of the code.
#region CustomerCard
public PXAction<PX.Objects.AR.Customer> customerCard;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Customer Card")]
protected void CustomerCard()
{
Customer customer = Base.BAccount.Current;
if (customer != null)
{
string screenID = "DBPS0007"; //DashboardID
PXSiteMapNode sm = GIScreenHelper.GetSiteMapNode(screenID);
PXGraph graph = GIScreenHelper.InstantiateGraph(screenID);
if (graph is LayoutMaint)
{
LayoutMaint copygraph = graph as LayoutMaint;
Dictionary<string, object> parameters = new
Dictionary<string, object>();
parameters["CustomerAccountID"] = customer.AcctCD;
copygraph.Filter.Current.Values = parameters;
throw new PXRedirectRequiredException(sm.Url, copygraph,
PXBaseRedirectException.WindowMode.New, string.Empty);
}
}
}
#endregion

Need to use updated Requested Date on Prepare Invoice process

I have a customization to the Sales Orders screen, where I use a RowPersisting event to update the Requested Date to the current date upon saving. The problem is, if the save is not executed, but the Actions.PrepareInvoice is initiated, the new Requested Date (hopefully set by the RowPersisting event) is not used. I've tried to override the base method as follows (to save the Sales Order record with the new Requested Date before the Prepare Invoice process is run):
public delegate IEnumerable PrepareInvoiceDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable PrepareInvoice(PXAdapter adapter, PrepareInvoiceDelegate baseMethod)
{
Base.Actions.PressSave();
return baseMethod(adapter);
}
But I receive the following error - "Error: The previous operation has not been complete yet."
How can I ensure that a modified Requested Date is used for the Prepare Invoice process if the Sales Order record is not yet saved?
The PrepareInvoice method in case if the call is not from Processing Page(adapter.MassProcess==false) is calling this.Save.Press() anyway.
Below is the code from PrepareInvoice action. Before creation of the Invoice there is being called this.Save.Press() so any your update will be saved and used for creation of the invoice.
[PXUIField(DisplayName = "Prepare Invoice", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false), PXButton]
public virtual IEnumerable PrepareInvoice(PXAdapter adapter)
{
List<SOOrder> list = adapter.Get<SOOrder>().ToList<SOOrder>();
foreach (SOOrder current in list)
{
if (this.Document.Cache.GetStatus(current) != PXEntryStatus.Inserted)
{
this.Document.Cache.SetStatus(current, PXEntryStatus.Updated);
}
}
if (!adapter.MassProcess)
{
try
{
this.RecalculateAvalaraTaxesSync = true;
this.Save.Press();
}
finally
{
this.RecalculateAvalaraTaxesSync = false;
}
}
PXLongOperation.StartOperation(this, delegate
{
DocumentList<ARInvoice, SOInvoice> documentList = new DocumentList<ARInvoice, SOInvoice>(PXGraph.CreateInstance<SOShipmentEntry>());
SOOrderEntry.InvoiceOrder(adapter.Arguments, list, documentList, adapter.MassProcess);
if (!adapter.MassProcess && documentList.Count > 0)
{
using (new PXTimeStampScope(null))
{
SOInvoiceEntry sOInvoiceEntry = PXGraph.CreateInstance<SOInvoiceEntry>();
sOInvoiceEntry.Document.Current = sOInvoiceEntry.Document.Search<ARInvoice.docType, ARInvoice.refNbr>(documentList[0].DocType, documentList[0].RefNbr, new object[]
{
documentList[0].DocType
});
throw new PXRedirectRequiredException(sOInvoiceEntry, "Invoice");
}
}
});
return list;
}
The solution seems to be to recreate the Action method in a graph extension and add the following code:
if (!adapter.MassProcess)
{
//****Code added to update the Requested Date to today's date...
var soorder = (SOOrder)Base.Caches[typeof(SOOrder)].Current;
soorder.RequestDate = DateTime.Now;
Base.Caches[typeof(SOOrder)].Update(soorder);
//****End of code added...
try
{
Base.RecalculateAvalaraTaxesSync = true;
Base.Save.Press();
}
finally
{
Base.RecalculateAvalaraTaxesSync = false;
}
}

Have processing icons appear during custom button action

I have a process which is activated by a button on a screen - but I'd like to know how to make it work like a process button, where the spinning wheel happens and the green checkbox appears at the end. I've got the following code, which I had wrapped in a PXLongOperation.StartOperation(...) as follows (the PXLongOperation is commented out here, because it didn't seem to be doing anything):
public PXAction<APInvoice> CreatePOBillings;
// [PXButton(CommitChanges = true)]
[PXProcessButton]
[PXUIField(DisplayName = "Create PO Billings", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
protected void createPOBillings()
{
int i = 0;
try
{
//This wraps the whole process into a 'PXLongOperation' function that will create the spinning 'busy' wheel at the top toolbar...
//PXLongOperation.StartOperation(this, delegate()
//{
var apinvoice = (APInvoice)Base.Document.Current;
if (apinvoice == null) return;
string RefNbr = apinvoice.RefNbr;
//Run the stored procedure which will get the records to create the Project Transactions. This will populate the table 'xCreatePOBilings':
var pars = new PXSPParameter[] { new PXSPInParameter("#p_RefNbr", RefNbr) }; //, new PXSPOutParameter("p2", outp2) };
var results = PXDatabase.Execute("xspMarketingPOBilling", pars);
//Get the dataset from the xCreatePOBillings table which was populated from the stored procedure above:
PXResultset<xCreatePOBillings> res = PXSelect<xCreatePOBillings,
Where<xCreatePOBillings.ponbr, Equal<Required<xCreatePOBillings.ponbr>>>
,OrderBy<Asc<xCreatePOBillings.ponbr
,Asc<xCreatePOBillings.destProject
,Asc<xCreatePOBillings.startDate>>>>>.Select(Base, RefNbr);
//Create the graph for the Project Transactions screen:
RegisterEntry graph = PXGraph.CreateInstance<RegisterEntry>();
//Create a new cache object for the header of Project Transactions:
PMRegister pmreg = new PMRegister();
pmreg.Module = "PM";
graph.Document.Insert(pmreg);
//Define the cache for the Project Transactions screen's grid records:
PMTran pmtrn;
foreach (PXResult<xCreatePOBillings> rec in res)
{
....
graph.Actions.PressSave();
//});
What is the best way to achieve this, if it's possible?
When the static PXLongOperation.StartOperation method is invoked inside a BLC extension class, as first parameter it can only accept Base property instead of this keyword:
PXLongOperation.StartOperation(Base, delegate()
{
...
}

Resources