fiscal area in the supplier information tab of the purchase order - acumatica

Could you help me, I am changing the tax area code by adaptation, however the taxes are not updated, what am I missing or how can I change the related taxes when I change the tax area?
This is my code, through this event that I'm doing.
protected void POLine_SiteID_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (POLine)e.Row;
var head = Base.Document.Current;
if (head == null) return;
if (row != null && row.OrderType == POOrderType.RegularOrder)
{
POLine line = PXSelect<POLine, Where<POLine.orderType,
Equal<Required<POLine.orderType>>,
And<POLine.orderNbr, Equal<Required<POLine.orderNbr>>>>>.Select(Base, row.OrderType, row.OrderNbr);
bool? xchange = false;
if (line != null)
{
INSite site = PXSelect<INSite, Where<INSite.siteID,
Equal<Required<INSite.siteID>>>>.Select(Base, line.SiteID);
if (site != null && line.SiteID == site.SiteID)
{
var ext = site.GetExtension<INSiteExt>();
if (ext != null)
{
head.TaxZoneID = ext.UsrTaxZone;
xchange = true;
}
}
if (xchange == true)
{
foreach (PEMclTaxZone zone in PXSelect<PEMclTaxZone,
Where<PEMclTaxZone.taxZoneID, Equal<Required<PEMclTaxZone.taxZoneID>>,
And<PEMclTaxZone.taxCategoryID, Equal<Required<PEMclTaxZone.taxCategoryID>>>>>.Select(Base, head.TaxZoneID, line.TaxCategoryID))
{
if (zone != null)
{
foreach (POTaxTran potax in PXSelect<POTaxTran,
Where<POTaxTran.orderType, Equal<Required<POTaxTran.orderType>>,
And<POTaxTran.orderNbr, Equal<Required<POTaxTran.orderNbr>>>>>.Select(Base, head.OrderType, head.OrderNbr))
{
if (potax != null)
{
potax.TaxID = zone.Taxid;
potax.TaxZoneID = zone.TaxZoneID;
Base.Taxes.Cache.Update(potax);
}
}
}
}
}
}
}
}
When I select the tax area manually, two elements are registered in the tax grid, if I do it by event it only updates the last one, I follow it by code and I see that if it updates, however, it does not reflect in the tax grid.
Here I show evidence, with images.
This step is with an event that is not working.
step 1
step 2:
step 3:
manually select the tax area, selected from the same tab.
step 1:
step 2:
That's how it should go, that's what I want the event to do.
Please tell me what I am failing in the event, I hope I have been clear, thanks.

The functions that grab these are the Tax Zone Extensions. You would want to override the GetDefaultTaxZone function of POOrderEntry
[PXOverride]
public virtual string GetDefaultTaxZone(POOrder row,
Func<POOrder, string> baseMethod)
{
//logic before base function
baseMethod(row);
//logic after base function
}
If you do not want any of the code to be run, feel free to copy the initial function and do not call the baseMethod delegate.

Related

Unable to Copy UDF from POLine (PO301000) to POReceiptLine(PO302000) on "Enter PO Receipt" Action

I have created 2 UDF's in POLine and POReceiptLine, I am trying to copy values of those UDF's from POLine to POReceiptLine on "Enter PO Receipt" action in PO Screen(PO301000). My code is getting executed but the values are not getting copied. Please suggest, Thanks
protected void POReceipt_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
var row = (POReceipt)e.Row;
POReceiptLine row1 = new POReceiptLine();
if (Base.Document.Current != null)
{
foreach (POReceiptLine tran in Base.transactions.Select())
{
POLine xPOLine = PXSelect<POLine,
Where<POLine.orderNbr, Equal<Current<POLine.orderNbr>>,
And<POLine.orderType, Equal<Current<POLine.orderType>>>>>.Select(Base, tran.PONbr, tran.POType);
if (xPOLine != null)
{
POLineExt poLineExt = PXCache<POLine>.GetExtension<POLineExt>(xPOLine);
POReceiptLineExt poReceiptLineExt = PXCache<POReceiptLine>.GetExtension<POReceiptLineExt>(row1);
poReceiptLineExt.UsrWarrantyTerms = poLineExt.UsrWarrantyTerms;
poReceiptLineExt.UsrVendorWarrantyDate = poLineExt.UsrVendorWarrantyDate;
}
return;
}
}
}
####...Section 2..####### I have tried using this below code as well but No Luck.
protected virtual void _(Events.FieldDefaulting<POReceiptLineExt.usrWarrantyTerms> e)
{
POReceiptLine row = (POReceiptLine)e.Row;
if (row != null)
{
POReceiptLineExt receiptLineExt = row.GetExtension<POReceiptLineExt>();
POLine line = SelectFrom<POLine>
.Where<POLine.pONbr.IsEqual<#P.AsString>
.And<POLine.lineNbr.IsEqual<#P.AsInt>>>
.View.Select(Base, row.PONbr, row.POLineNbr);
POLineExt lineExt = line.GetExtension<POLineExt>();
if (lineExt?.UsrWarrantyTerms != null && receiptLineExt != null)
{
e.NewValue = receiptLineExt.UsrWarrantyTerms;
}
}
}
protected void POReceiptLine_ReceiptNbr_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (POReceiptLine)e.Row;
if (row == null) return;
cache.SetDefaultExt<POReceiptLineExt.usrWarrantyTerms>(row);
}
Not sure of your version, so I'll answer per version 2020R2 that I am running.
Observations:
You seem to be returning after the 1st POReceiptLine in the transactions view. More importantly, the placement would seem more appropriate on the POReceiptLine_RowPersisting event where you would not have to do the foreach within the RowPersisting. Lastly, off the top of my head, I can't recall if you need to update the cache when doing this in row persisting if you are working on the record being persisted, but you are working on a different record meaning you likely need to update the cache which gets tricky inside RowPersisting events. (For example, you may not know if the other cache was already persisted.)
Flow of the action:
POOrderEntry contains the action CreatePOReceipt which, in turn, initializes POReceiptEntry and creates the receipt from the order via CreateReceiptFrom(...) which then calls AddPOLine(...). Subsequently, the POReceiptLine is created via line = this.transactions.Insert(line);.
Recommendation:
In 2020R2, it seems your code belongs in POReceiptEntry, but you did not specify where you are putting it. If you placed it in POOrderEntry, the event never fires.
Try putting something like this in POReceiptEntry (do similar for the other field also).
protected virtual void _(Events.FieldDefaulting<POReceiptLineExt.UsrWarrantyTerms> e)
{
POReceiptLine row = (POReceiptLine) e.Row;
if(row != null)
{
POReceiptLineExt receiptLineExt = row.GetExtension<POReceiptLineExt>();
POLine line = SelectFrom<POLine>
.Where<POLine.pONbr.IsEqual<#P.AsString>
.And<POLine.lineNbr.IsEqual<#P.AsInt>>>
.View.Select(Base, row.PONbr, row.POLineNbr);
POLineExt lineExt = line.GetExtension<POLineExt>();
if(lineExt?.UsrWarrantyTerms != null && receiptLineExt != null)
{
e.NewValue = receiptLineExt.UsrWarrantyTerms;
}
}
}
Since the PONbr and LineNbr fields may not be set yet, you may need to use SetDefaultExt for those 2 fields at the appropriate place. (I'd suggest maybe trying in the POReceiptLine.POLineNbr FieldUpdated event.) I believe the insert from the action coming from POOrderEntry already has the fields filled in, but that may not be the case in every way the POReceiptLine record is created, so you want to be sure you are setting the values EVERY time that it is warranted.
I have got a solution to this issue i.e. by using field level event and calling the function from a field level event, the below code is working perfectly fine for me. Thanks.
protected void POReceiptLine_POLineNbr_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (POReceiptLine)e.Row;
CarryForwardFromPO(row);
}
public void CarryForwardFromPO(POReceiptLine row)
{
if (row.PONbr == null || row.POType == null || row.POLineNbr == null)
return;
POReceiptLineExt _polext = PXCache<POReceiptLine>.GetExtension<POReceiptLineExt>(row);
if (row.PONbr != null)
{
POLine xPOLine = PXSelect<POLine,
Where<POLine.orderNbr, Equal<Required<POLine.orderNbr>>,
And<POLine.orderType, Equal<Required<POLine.orderType>>,
And<POLine.lineNbr, Equal<Required<POLine.lineNbr>>>>>>.Select(Base, row.PONbr, row.POType, row.POLineNbr);
if (xPOLine != null)
{
POLineExt xPOLineExt = PXCache<POLine>.GetExtension<POLineExt>(xPOLine);
if (xPOLineExt != null)
{
if (xPOLineExt.UsrVendWarrantyType != null)
{
_polext.UsrVendWarrantyType = xPOLineExt.UsrVendWarrantyType.Trim();
}
if (xPOLineExt.UsrWarrantyTerms != null)
{
_polext.UsrWarrantyTerms = xPOLineExt.UsrWarrantyTerms.Trim();
}
if (xPOLineExt.UsrVendorWarrantyDate != null)
{
_polext.UsrVendorWarrantyDate = xPOLineExt.UsrVendorWarrantyDate;
}
}
}
}
}

Acumatica: Update Service Order from Appointment

I need to customize the Appointment screen so that if a user selects the Billable Checkbox on the appointment, it will update the original service order. I was able to get this to work with a PXUpdate, but that didn't do any of the service order graph logic that updates document totals and taxes. I need to update the IsBillable checkbox on the service order but also have it run the ServiceOrderEntry events. I have the following code which runs through but doesn't update the service order. I'm at a loss. Any help is appreciated!
protected void FSAppointmentDetPart_RowPersisted(PXCache cache, PXRowPersistedEventArgs e)
{
var aptRow = e.Row as FSAppointmentDetPart;
if (aptRow == null) return;
var soGraph = PXGraph.CreateInstance<ServiceOrderEntry>();
FSSODet soDetRow = PXSelect<FSSODet, Where<FSSODet.sODetID, Equal<Required<FSSODet.sODetID>>>>.Select(soGraph, aptRow.SODetID);
if (soDetRow == null) return;
soGraph.Caches<FSSODet>().Current = soDetRow;
FSServiceOrder serviceOrderRow = soGraph.ServiceOrderRecords.Current = soGraph.ServiceOrderRecords
.Search<FSServiceOrder.refNbr>(soDetRow.RefNbr, soDetRow.SrvOrdType);
if (serviceOrderRow == null) return;
if (soDetRow is FSSODetPart)
{
if (e.Operation == PXDBOperation.Delete)
{
soGraph.ServiceOrderDetParts.Delete(soDetRow as FSSODetPart);
}
else if (e.Operation == PXDBOperation.Update)
{
bool? isBillable = aptRow.IsBillable;
soDetRow.IsBillable = aptRow.IsBillable;
soGraph.Caches<FSSODet>().SetValueExt<FSSODet.isBillable>(soGraph, isBillable);
decimal? estimatedQty = aptRow.EstimatedQty;
soDetRow.EstimatedQty = aptRow.EstimatedQty;
soGraph.Caches<FSSODet>().SetValueExt<FSSODet.estimatedQty>(soGraph, estimatedQty);
soGraph.ServiceOrderDetParts.Cache.Update(soDetRow);
soGraph.ServiceOrderRecords.Cache.Update(serviceOrderRow);
soGraph.Actions.PressSave();
}
}
}
I was able to get this to work using soGraph.ServiceOrderRecords.Cache.RaiseFieldUpdated(soDetRow, null);

Need help carrying Sales Order user fields to Create Purchase order screen

I have a customization where I have added three user fields to the Sales Order (SO301000) screen transactions grid. I would like to set fields on the 'Create Purchase Order' screen (PO505000). I had used the POFixedDemand's 'RowSelected' event, which works fine - but that causes a problem when anyone tries to modify anything in a row - which re-triggers that event - not a desired outcome.
I've tried the 'RowInserting' and 'RowInserted' events - but they're never triggered. I'm assuming at this point that I'll have to intercept some code in the 'POCreate' BLC that creates the POFixedDemand records in the Create Purchase Order screen - but I don't really know where to start. Would I put it somewhere in the EnumerateAndPrepareFixedDemands method?
Here's the code I created which works for the RowSelected event, but is no good for when a row is modified by a user. Any help is appreciated. Thank you.
protected virtual void POFixedDemand_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var pofd = (POFixedDemand)e.Row;
if (pofd == null) return;
var filter = Base.Filter.Current;
var ordernbr = filter.OrderNbr;
var ordertype = filter.OrderType;
var solinesplit = (SOLineSplit)PXSelect<SOLineSplit, Where<SOLineSplit.planID, Equal<Required<SOLineSplit.planID>>>>.Select(Base, pofd.PlanID);
if (solinesplit != null)
{
var soline = (SOLine)PXSelect<SOLine,
Where<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>,
And<SOLine.orderType, Equal<Required<SOLine.orderType>>,
And<SOLine.lineNbr, Equal<Required<SOLine.lineNbr>>>>>>.Select(Base, solinesplit.OrderNbr, solinesplit.OrderType, solinesplit.LineNbr);
if (soline != null)
{
var solineext = PXCache<SOLine>.GetExtension<SOLineExt>(soline);
pofd.VendorID = solineext.UsrVendor;
pofd.EffPrice = solineext.UsrVendorUnitCost;
pofd.ExtCost = solineext.UsrVendorExtendedCost;
//Now set the Vendor location...
var location = (Location)PXSelect<Location,
Where<Location.bAccountID, Equal<Required<Location.bAccountID>>>>.Select(Base, pofd.VendorID);
if (location != null)
{
pofd.LocationID = location.LocationID;
}
}
}
}
I'm assuming at this point that I'll have to intercept some code in
the 'POCreate' BLC
Yes you need to do something along those lines.
There's a similar answer here for initializing the POLine instead of POFixedDemand:
https://stackoverflow.com/a/37255340/7376238
With some minor adjustments, the general pattern would be:
public class POCreateExt : PXGraphExtension<POCreate>
{
public override void Initialize()
{
PXGraph.InstanceCreated.AddHandler<POOrderEntry>((graph) =>
{
graph.RowInserting.AddHandler<POFixedDemand>((sender, e) =>
{
// Initialize fields when row is inserted
POFixedDemand demand = e.Row as POFixedDemand;
demand.DACField = [initialization value];
});
graph.RowUpdating.AddHandler<POFixedDemand>((sender, e) =>
{
// Sometimes fields are updated so you need to
// hook RowUpdating too and re-initialize
POFixedDemand demand = e.NewRow as POFixedDemand;
demand.DACField = [initialization value];
});
});
}
}
What I came up with after some investigation is to override the 'EnumerateAndPrepareFixedDemands' method to set the values. Code is as follows:
public delegate IEnumerable EnumerateAndPrepareFixedDemandsDelegate(PXResultset<POFixedDemand> fixedDemands);
[PXOverride]
public IEnumerable EnumerateAndPrepareFixedDemands(PXResultset<POFixedDemand> fixedDemands, EnumerateAndPrepareFixedDemandsDelegate baseMethod)
{
foreach (PXResult<POFixedDemand> rec in fixedDemands)
{
POFixedDemand demand = rec;
var solinesplit = (SOLineSplit)PXSelect<SOLineSplit, Where<SOLineSplit.planID, Equal<Required<SOLineSplit.planID>>>>.Select(Base, demand.PlanID);
if (solinesplit != null)
{
var soline = (SOLine)PXSelect<SOLine,
Where<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>,
And<SOLine.orderType, Equal<Required<SOLine.orderType>>,
And<SOLine.lineNbr, Equal<Required<SOLine.lineNbr>>>>>>.Select(Base, solinesplit.OrderNbr, solinesplit.OrderType, solinesplit.LineNbr);
if (soline != null)
{
var solineext = PXCache<SOLine>.GetExtension<SOLineExt>(soline);
demand.VendorID = solineext.UsrVendor;
demand.EffPrice = solineext.UsrVendorUnitCost;
demand.ExtCost = solineext.UsrVendorExtendedCost;
//Now set the Vendor location...
var location = (Location)PXSelect<Location,
Where<Location.bAccountID, Equal<Required<Location.bAccountID>>>>.Select(Base, solineext.UsrVendor);
if (location != null)
{
demand.VendorLocationID = location.LocationID;
}
}
}
}
return baseMethod(fixedDemands);
}

How to set First Dropdown value as default for first line in grid then Second value defaults from second line in grid

In the Product drop-down, there are 2 values, First value (Product) will default for first line only and Second value (Co-Product) will default from the second line.
I tried this in FieldDefaulting event
protected void TSFormulaProdsNCoProds_Product_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (TSFormulaProdsNCoProds)e.Row;
if (row == null)
return;
if (TSFormProdsNCoProds.Select().Count == 0)
{
e.NewValue = "P";
}
else
{
e.NewValue = "C";
}
}
Can anyone provide a suggestion to me?
Most likely you have PXDefault attribute decorated at DAC level. In that case, you need to set Cancel flag to prevent execution of FieldDefaulting event handlers that are defined in attributes.
Example :-
protected void TSFormulaProdsNCoProds_Product_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (TSFormulaProdsNCoProds)e.Row;
if (row == null)
return;
e.NewValue = (TSFormProdsNCoProds.Select().Count == 0) ? "P" : "C";
e.Cancel = true;
}
This is explained in Example 5.2: Inserting a Default Detail Data Record of T200 Acumatica Framework Fundamental course.

Acumatica - FieldDefaulting update ImageUrl from DAC extension

I am trying to update the Inventory Item ImageUrl if it is found to be null with some conditions. I have added a Usr field called UsrStyleImg to the Item Class screen. This field is for a basic image of an item and it is stored in the database. The functionality I want is if the Inventory Item does not have an image in the ImageUrl then it will default to the UsrStyleImg that is connected with the ItemClassID. ItemClassID is also found on the Stock Item Screen. Here is the code I have in the InventoryItemMaint graph:
protected void InventoryItem_ImageUrl_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (InventoryItem)e.Row;
if (row == null) return;
var item = (INItemClass)PXSelect<INItemClass, Where<INItemClass.itemClassID, Equal<Current<InventoryItem.itemClassID>>>>.Select(Base, row.ItemClassID);
var image = PXSelect<InventoryItem, Where<InventoryItem.imageUrl, Equal<Current<InventoryItem.imageUrl>>>>.Select(Base, row.ImageUrl);
if (image != null)
return;
else {
e.NewValue = item.GetExtension<INItemClassExt>().UsrStyleImg;
}
}
The code compiles fine but when I test with an Item that has an Item Class attached to it with an image in the INItemClass table called UsrStyleImg it does not populate to the imageUrl found in the Inventory Item table or the Stock Item screen. I have also tried this with FieldSelecting and using the e.ReturnValue with still the same results.
If I need more clarification please let me know.
Try using a RowSelecting Event
protected virtual void InventoryItem_RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
InventoryItem row = e.Row as InventoryItem;
//Extra checks to prevent infinite loops
if (row != null && !string.IsNullOrWhiteSpace(row.InventoryCD) && Base.Item.Cache.GetStatus(row) == PXEntryStatus.Notchanged)
{
if (!string.IsNullOrWhiteSpace(row.ItemClassID))
{
//You must always use a PXConnectionScope if Selecting during RowSelecting
using (new PXConnectionScope())
{
//If you're going to pass in a value in .Select, use Required instead of Current.
INItemClass itemClass = PXSelectReadonly<INItemClass, Where<INItemClass.itemClassID, Equal<Required<INItemClass.itemClassID>>>>.Select(Base, row.ItemClassID);
if (itemClass != null && string.IsNullOrWhiteSpace(row.ImageUrl))
{
INItemClassExt itemClassExt = itemClass.GetExtension<INItemClassExt>();
//To prevent unneeded update if it's blank
if (!string.IsNullOrWhiteSpace(itemClassExt.UsrStyleImg))
{
row.ImageUrl = itemClassExt .UsrStyleImg;
//Force set the status in the Cache, otherwise it infinite loops
Base.Item.Cache.SetStatus(row, PXEntryStatus.Updated);
Base.Item.Update(row);
}
}
}
}
}
}

Resources