How can I copy the note from a SalesOrder to a Shipment as the shipment is created?
I am trying to use the PXNoteAttribute.GetNote()/PXNoteAttribute.SetNote() functions, but GetNote keeps turning up blank.
#region Event Handlers
string notetext;
protected void SOShipLine_RowInserted(PXCache cache, PXRowInsertedEventArgs e, PXRowInserted InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOShipLine)e.Row;
SOOrder SalesOrder = (SOOrder)PXSelectorAttribute.Select<SOShipLine.origOrderNbr>(cache, e.Row);
string note = PXNoteAttribute.GetNote(cache, SalesOrder);
notetext = note;
}
protected void SOShipment_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOShipment)e.Row;
PXNoteAttribute.SetNote(cache, cache.Current, notetext);
}
The cache you are referencing in your code is the cache for the ShipLine. You need to reference the SalesOrder cache for GetNote() to function properly. You can use Base.Caches[typeof(SOOrder)].
Like so:
#region Event Handlers
string notetext;
protected void SOShipLine_RowInserted(PXCache cache, PXRowInsertedEventArgs e, PXRowInserted InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOShipLine)e.Row;
SOOrder SalesOrder = (SOOrder)PXSelectorAttribute.Select<SOShipLine.origOrderNbr>(cache, e.Row);
string note = PXNoteAttribute.GetNote(Base.Caches[typeof(SOOrder)], SalesOrder);
notetext = note;
}
protected void SOShipment_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOShipment)e.Row;
PXNoteAttribute.SetNote(cache, cache.Current, notetext);
}
Related
I am looking for the best possibility to initialize the tarifs.
using the fielddefaulting event, the amount stays at 0
protected void SOLine_CuryUnitPrice_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (SOLine)e.Row;
SOOrder order = (SOOrder) Base.Document.Current;
BAccount un_compte=PXSelect<BAccount , Where<BAccount.bAccountID, Equal<Required<BAccount.bAccountID>>>>.Select(this.Base,row.CustomerID);
if (row.InventoryID!=null)
{
InventoryItem un_article=PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>>>.Select(this.Base,row.InventoryID);
string taxe=Convert.ToString(order.TaxCalcMode);
if ((un_compte!=null) && (un_article!=null))
{
if ((un_compte.GetExtension<BAccountExt>().Usrcattarifaireclient=="cat1") && (taxe=="N"))
{
decimal? tmp=un_article.GetExtension<InventoryItemExt>().Usrprxht1;
e.NewValue=tmp;
}
if ((un_compte.GetExtension<BAccountExt>().Usrcattarifaireclient=="cat1") && (taxe=="G"))
{
decimal? tmp=un_article.GetExtension<InventoryItemExt>().Usrprxttc1;
e.NewValue=tmp;
}
}
}
}
I finally used the event : SOLine_UOM_FieldUpdated.
Everything works perfectly, including the webservices
protected void SOLine_UOM_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (SOLine)e.Row;
row.CuryUnitPrice=tmp;
}
Application Date to default Document Date:
protected void ARPayment_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (ARPayment)e.Row;
if (row != null)
{
row.AdjDate = row.DocDate;
row.AdjFinPeriodID = row.FinPeriodID;
}
}
The code defaults the fields as required but Application date cannot be edited hence backdating cannot be done
protected void ARPayment_AdjFinPeriodID_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (ARPayment)e.Row;
row.AdjFinPeriodID = row.FinPeriodID;
}
protected void ARPayment_AdjDate_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (ARPayment)e.Row;
row.AdjDate = row.DocDate;
}
Using field defaulting gives index out of range error
By Adding a condition to check the status of the document it seizes to work
protected void ARPayment_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (ARPayment)e.Row;
if (row != null && row.Status == "Open")
{
row.AdjDate = row.DocDate;
row.AdjFinPeriodID = row.FinPeriodID;
}
}
The RowSelected event is not an initialization event. It is run on every callback to the server.
The FieldDefaulting event should assign the default value using the NewValue property of PXFieldDefaultingEventArgs argument parameter.
Using field defaulting gives index out of range error
That should not happen in your FieldDefaulting handler because there are no index access operations. I can't reproduce this issue. Remove all other customization code, keep only the FieldDefaulting event and this error should disappear.
There is another issue though. The DocDate value is always null when I debug the FieldDefaulting event. When I pass a valid Date value for initialization it does work as expected on new payments. Example:
using PX.Data;
using System;
namespace PX.Objects.AR
{
public class ARPaymentEntry_Extension : PXGraphExtension<ARPaymentEntry>
{
public void ARPayment_AdjDate_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
ARPayment row = e.Row as ARPayment;
if (row != null)
e.NewValue = new DateTime(2077, 01, 01);
}
}
}
I am extending ARInvoiceEntry graph and adding an even handler for RowPersisting, but the only data I see in the invoice is ShipAddressID:
namespace PX.Objects.AR
{
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
protected void ARInvoice_RowPersisting(PXCache cache, PXRowPersistingEventArgs e, PXRowPersisting InvokeBaseHandler)
{
var row = (ARInvoice)e.Row;
if (row != null)
{
// ???
}
}
}
}
Do I need to use that ShipAddressID and run a query? If the address is an override, query wouldn't work.
You need to select the current ARShippingAddress record from the base graph Shipping_Address dataview.
public void ARInvoice_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
ARInvoice invoice = e.Row as ARInvoice;
ARShippingAddress shipAddress = Base.Shipping_Address.Select();
if (invoice != null && shipAddress != null)
{
throw new PXException("Address Line 1: " + shipAddress.AddressLine1 + Environment.NewLine +
"Address Line 2: " + shipAddress.AddressLine2 + Environment.NewLine +
"Address Line 3: " + shipAddress.AddressLine3 + Environment.NewLine);
}
}
I have an action button on the QuoteMaint graph. This action is in the actions folder. I set whether or not the button is enabled based on the quote status. When the user submits the quote, the action button should be enabled. I stepped through the code and it runs the routine to enable button, but on the screen it is not enabled. When I refresh the screen it is enabled with no issues. The code is below, thanks for your help!
public PXAction<CRQuote> printQuoteSummary;
[PXButton(CommitChanges = true, SpecialType = PXSpecialButtonType.Report)]
[PXUIField(DisplayName = "Print Quote - Summary")]
public IEnumerable PrintQuoteSummary(PXAdapter adapter)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
string actualReportID = "CR604510";
foreach (CRQuote item in adapter.Get<CRQuote>())
{
parameters[nameof(CRQuote.OpportunityID)] = item.OpportunityID;
parameters[nameof(CRQuote.QuoteNbr)] = item.QuoteNbr;
throw new PXReportRequiredException(parameters, actualReportID, "Report " + actualReportID);
}
return adapter.Get();
}
public override void Initialize()
{
base.Initialize();
Base.actionsFolder.AddMenuAction(printQuoteSummary);
Base.Actions.Move("PrintQuote", "printQuoteSummary");
printQuoteSummary.SetEnabled(Base.Quote.Current?.Status == CRQuoteStatusAttribute.Approved || Base.Quote.Current?.Status == CRQuoteStatusAttribute.Sent);
}
protected virtual void CRQuote_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
CRQuote quote = e.Row as CRQuote;
if (quote == null) return;
using (new PXConnectionScope())
{
CalcTotals(quote);
}
printQuoteSummary.SetEnabled(quote.Status == CRQuoteStatusAttribute.Approved || quote.Status == CRQuoteStatusAttribute.Sent);
}
Adding the additional argument for the event delegate resolved the issue in testing, please find sample below.
protected virtual void CRQuote_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected del)
{
del?.Invoke(cache, e);
CRQuote quote = e.Row as CRQuote;
if (quote == null) return;
using (new PXConnectionScope())
{
CalcTotals(quote);
}
PrintQuoteSummary.SetEnabled(quote.Status == CRQuoteStatusAttribute.Approved || quote.Status == CRQuoteStatusAttribute.Sent);
}
With this you may also remove reference to enable/disable in your initialize method as such it would be as follows.
public override void Initialize()
{
base.Initialize();
Base.actionsFolder.AddMenuAction(PrintQuoteSummary);
Base.Actions.Move("PrintQuote", "printQuoteSummary");
}
While creating GI for sales order screen I want to display the total number of lines in document details tab. Can anyone suggest a way to start implementing this?
After including the custom field in GI it doesn't populate the column with data.
The code for printing the row count is as below which is also discussed in Adding custom button in acumatica
public void SOOrder_UsrTotalTransactions_FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
e.ReturnValue = GetTotalTransactions(sender);
}
// Update values
public void SOLine_RowDeleted(PXCache sender, PXRowDeletedEventArgs e)
{
UpdateTotals(sender, e.Row as SOOrder, true);
}
public void SOLine_RowInserted(PXCache sender, PXRowInsertedEventArgs e)
{
UpdateTotals(sender, e.Row as SOOrder, true);
}
public void SOLine_OrderQty_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
UpdateTotals(sender, e.Row as SOOrder, false);
}
public void UpdateTotals(PXCache sender, SOOrder soOrder, bool isUpdateTranCount)
{
// Get SOOrder DAC extension
if (soOrder != null)
{
SOOrderExt soOrderExt = sender.GetExtension<SOOrderExt>(soOrder);
if (soOrderExt != null)
{
if (isUpdateTranCount)
{
sender.SetValueExt<SOOrderExt.usrTotalTransactions>(soOrder, GetTotalTransactions(sender));
}
}
}
}
public int? GetTotalTransactions(PXCache sender)
{
return Base.Transactions.Select().Count();
}
}
}
the DAC code is:
[PXDBInt]
[PXUIField(DisplayName="Total Lines", Enabled = false)]
If you are trying to set the value I would try a simplified version of your example like this...
namespace PX.Objects.SO
{
public class SOOrderEntry_Extension : PXGraphExtension<SOOrderEntry>
{
public void SOLine_RowDeleted(PXCache sender, PXRowDeletedEventArgs e)
{
UpdateTotals(sender, e.Row as SOOrder);
}
public void SOLine_RowInserted(PXCache sender, PXRowInsertedEventArgs e)
{
UpdateTotals(sender, e.Row as SOOrder);
}
public void UpdateTotals(PXCache sender, SOOrder soOrder)
{
if (soOrder != null)
{
SOOrderExt soOrderExt = sender.GetExtension<SOOrderExt>(soOrder);
if (soOrderExt != null)
{
sender.SetValueExt<SOOrderExt.usrRowCount>(soOrder, GetRowCount());
}
}
}
public int GetRowCount()
{
return Base.Transactions?.Select().Count() ?? 0;
}
}
}
You would use FieldSelecting to set unbound field values. Because your field is bound you do not want to call fieldselecting for your example.