Default PO Type to 'Drop Ship' not working properly - acumatica

I'm trying to default the OrderType.POOrderType to POOrderType.DropShip. I've tried altering the attributes in the customization manager to the following:
[PXDBString(2, IsKey = true, IsFixed = true)]
[PXDefault(POOrderType.DropShip)]
[POOrderType.List()]
[PXUIField(DisplayName = "Type", Visibility = PXUIVisibility.SelectorVisible, Enabled = true)]
[PX.Data.EP.PXFieldDescription]
But upon insertion of a new record, it does nothing. I've also tried using the CacheAttached event in a graph extension of POOrderEntry as follows:
public class POOrderEntryExt : PXGraphExtension<POOrderEntry>
{
[PXDBString(2, IsKey = true, IsFixed = true)]
[PXDefault(POOrderType.DropShip)]
[POOrderType.List()]
[PXUIField(DisplayName = "Type", Visibility = PXUIVisibility.SelectorVisible, Enabled = true)]
[PX.Data.EP.PXFieldDescription]
protected virtual void POOrder_OrderType_CacheAttached(PXCache sender) { }
}
This also does NOT work.
I've finally tried using the RowInserting event as follows
protected virtual void POOrder_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
POOrder poorder = (POOrder)e.Row;
if (poorder == null) return;
poorder.OrderType = POOrderType.DropShip;
}
This DOES default to DropShip, however, when I use the dropdown on the screen to change back to 'Normal', it empties all the fields, and the Type is also empty. If I select Normal again, then it displays the data in the fields correctly. I can't figure out what's going on here. I always have to select the Type twice to get anything to show. I can't see why the RowInserting event would cause this behavior...

There is POOrder_OrderType_FieldDefaulting event in the POOrderEntry, where default order type is set.
protected virtual void POOrder_OrderType_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
{
e.NewValue = POOrderType.RegularOrder;
}
It have 'higher priority' than PXDefault attribute (check T200 training for more information).
So you need to override this event handler.

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);

Mix Manual\Auto Numbering Sequences

In Numbering Sequences settings (CS201010), there is an option for manual numbering.
However, depending on the document type. There are instances where the reference number can be left blank. If it's blank, I'd want the auto numbering to kick in. Or something like call the NextNumber() function before saving the document. Is it possible ? How do I do that ?
At the moment, if I enforce the auto numbering. It doesn't allow me to type anything on the Reference number for example.
TIA
There are two ways: easy and little bit more complicated. Easy one will be attach to FieldDefaulting, and inside of that event check if that field is empty then assign some value into it.
Another way which better feet to Acumatica style is to implement your own AutoNumbering attribute and then apply that Autonumbering attribute to your DAC class. N.B. you can substitute Acumatica autonumbering attribute with yours with PXCacheExtension
below goes example of code with removing default autonumbering with implementing autonumbering via FieldDefaulting:
public class ARInvoiceEntryExt : PXGraphExtension<ARInvoiceEntry>
{
[PXDBString(15, InputMask = ">CCCCCCCCCCCCCCC", IsKey = true, IsUnicode = true)]
[PXDefault]
[PXUIField(DisplayName = "Reference Nbr.", TabOrder = 1, Visibility = PXUIVisibility.SelectorVisible)]
//[ARInvoiceType.RefNbr(typeof(Search2<ARRegisterAlias.refNbr, InnerJoinSingleTable<ARInvoice, On<ARInvoice.docType, Equal<ARRegisterAlias.docType>, And<ARInvoice.refNbr, Equal<ARRegisterAlias.refNbr>>>, InnerJoinSingleTable<Customer, On<ARRegisterAlias.customerID, Equal<Customer.bAccountID>>>>, Where<ARRegisterAlias.docType, Equal<Optional<ARInvoice.docType>>, And2<Where<ARRegisterAlias.origModule, Equal<BatchModule.moduleAR>, Or<ARRegisterAlias.released, Equal<True>>>, And<Match<Customer, Current<AccessInfo.userName>>>>>, OrderBy<Desc<ARRegisterAlias.refNbr>>>), Filterable = true, IsPrimaryViewCompatible = true)]
//[ARInvoiceType.Numbering]
//This is example of throwing away Acumatica autonumbering
//[ARInvoiceNbr]
[PXFieldDescription]
protected void ARInvoice_RefNbr_Cacheattached()
{
}
protected void ARInvoice_RefNbr_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
{
//here you can implement your way of initialization of this field
}
}
Or with attribute you can try something like this:
//somewhere in your code
public class RickAutonumberingAttribute : ARInvoiceNbrAttribute
{
//Here you'll need to play with implementation of your autonumbering
}
public class ARInvoiceEntryExt : PXGraphExtension<ARInvoiceEntry>
{
[PXDBString(15, InputMask = ">CCCCCCCCCCCCCCC", IsKey = true, IsUnicode = true)]
[PXDefault]
[PXUIField(DisplayName = "Reference Nbr.", TabOrder = 1, Visibility = PXUIVisibility.SelectorVisible)]
[ARInvoiceType.RefNbr(typeof(Search2<ARRegisterAlias.refNbr, InnerJoinSingleTable<ARInvoice, On<ARInvoice.docType, Equal<ARRegisterAlias.docType>, And<ARInvoice.refNbr, Equal<ARRegisterAlias.refNbr>>>, InnerJoinSingleTable<Customer, On<ARRegisterAlias.customerID, Equal<Customer.bAccountID>>>>, Where<ARRegisterAlias.docType, Equal<Optional<ARInvoice.docType>>, And2<Where<ARRegisterAlias.origModule, Equal<BatchModule.moduleAR>, Or<ARRegisterAlias.released, Equal<True>>>, And<Match<Customer, Current<AccessInfo.userName>>>>>, OrderBy<Desc<ARRegisterAlias.refNbr>>>), Filterable = true, IsPrimaryViewCompatible = true)]
//[ARInvoiceType.Numbering]
//This is example of throwing away Acumatica autonumbering
[RickAutonumberingAttribute]
[PXFieldDescription]
protected void ARInvoice_RefNbr_Cacheattached()
{
}
}

Hide/Disable other fields based on Input field

I want to hide or update a field on the UI based on conditions of another field.
For example, if I have a field called Color:
[PXUIField(DisplayName="Color")]
[PXStringList("Red,Blue,Other")]
[PXDefault("Red")]
And text field for comments only shown when "Other" is selected, how is this accomplished?
The requested behavior can either be accomplished either with a series of event handlers or with a bunch of attributes. You can find several examples on how to subscribe to the RowSelected and FieldUpdated events in the T200 training course, available at Acumatica University and Acumatica Open University
Going with field attributes is a more convenient and way easier option for your particular scenario. I would recommend setting CommitChanges to True for the drop-down, so the Comments field is cleared and disabled/enabled immediately after the user updates Color. Also, it's very to have your Color declared after Comments, so the framework will process Comments field first and always clear the current Comments value after the Color field got updated.
public class Other : Constant<string>
{
public Other() : base("Other") { }
}
public abstract class comments : IBqlField { }
[PXDBString(255, IsUnicode = true)]
[PXUIField(DisplayName = "Comments")]
[PXUIEnabled(typeof(Where<color, Equal<Other>>))]
[PXFormula(typeof(Default<color>))]
[PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]
public string Comments { get; set; }
public abstract class color : IBqlField { }
[PXDBString(10, IsUnicode = true)]
[PXUIField(DisplayName = "Color")]
[PXStringList("Red,Blue,Other")]
[PXDefault("Red")]
public string Color { get; set; }
The only way to conditionally hide/show editor on a form is though the RowSelected event handler:
public void YourDAC_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
YourDAC row = e.Row as YourDAC;
if (row == null) return;
PXUIFieldAttribute.SetVisible<YourDAC.comments>(sender, row, row.Color == "Other");
}
I believe, in the T200 training course, there are several examples on the PXUIFieldAttribute.SetVisible method.

How to change auto numbering to existing auto numbering sequence in Acumatica?

In Cash Sales (AR304000 screen) i want to set it's auto numbering sequence from invoice number sequence to payment number sequence.
i tried the following code but to no avail. saving new sales throws an error. see attached photo for the error.
here is my DAC code:
public class ARCashSaleExtension : PXCacheExtension<ARCashSale>
{
#region RefNumber
[PXDBString(15, IsKey = true, InputMask = ">CCCCCCCCCCCCCCC", IsUnicode = true, BqlField = typeof(**PX.Objects.AR.ARPayment.refNbr**))]
[PXDefault()]
[PXUIField(DisplayName = "Reference Nbr.", Visibility = PXUIVisibility.SelectorVisible)]
[ARPaymentType.RefNbr(typeof(Search2<ARCashSale.refNbr,
InnerJoinSingleTable<Customer, On<ARCashSale.customerID, Equal<Customer.bAccountID>>>,
Where<ARCashSale.docType, Equal<Current<ARCashSale.docType>>,
And2<Where<ARCashSale.origModule, NotEqual<BatchModule.moduleSO>, Or<ARCashSale.released, Equal<boolTrue>>>,
And<Match<Customer, Current<AccessInfo.userName>>>>>, OrderBy<Desc<ARCashSale.refNbr>>>), Filterable = true)]
[**ARPaymentType.Numbering()**]
[PXFieldDescription]
public String RefNbr
{
get;
set;
}
#endregion
}
I think you should use AutoNumberAttribute instead of ARPaymentType.Numbering attribute.
[AutoNumber(typeof(ARCashSale.docType), typeof(ARCashSale.docDate),
new string[] { CashSale, CashReturn },
new Type[] { typeof(ARSetup.paymentNumberingID), typeof(ARSetup.paymentNumberingID) })]
Besides, I can't see any reasons to use ARPaymentType.RefNbr attribute instead of ARCashSaleType.RefNbr attribute.
One more thing: from my point, it's better to use Cache_Attached on graph extension for rewriting attributes on one field instead of creating DAC extension.
Here is an example of Graph extension with CacheAttached:
public partial class ARCashSaleEntryExt : PXGraphExtension<ARCashSaleEntry>
{
[PXMergeAttributes(Method = MergeMethod.Merge)] // that attribute is here to keep all attributes of base field except the one that should be replaced.
[AutoNumber(typeof(ARCashSale.docType), typeof(ARCashSale.docDate),
new string[] { ARDocType.CashSale, ARDocType.CashReturn },
new Type[] { typeof(ARSetup.paymentNumberingID), typeof(ARSetup.paymentNumberingID) })]
public virtual void ARCashSale_RefNbr_CacheAttached(PXCache sender)
{
}
}
To learn more about cache_attached events see T200 training

Acumatica Extension on SOSitesStatusSelected

I've been having this problem on Acumatica extension for days now and can't seem to figure out the resolution. I've added an action on the Inventory Lookup Dialog of Sales Order screen (see screenshot below), the action is task to update the QtySelected to 1 and also to update my added Field which is the Brand to "testBrand". It is an extension of the SOSitesStatusSelected table, but whenever i clicked on the action, it only updates QtySelected and not my added Field Brand.
You may refer to my code below, thank you and I appreciate all the help.
//DAC
#region UsrBrand
[PXUIField(DisplayName = "Brand", Visible = true, Enabled = true)]
public virtual string UsrBrand{get;set;}
public abstract class usrBrand : IBqlField{}
#endregion
//BLC
public PXAction<PX.Objects.SO.SOOrder> updateAttributes;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Update Attributes")]
protected void UpdateAttributes()
{
this.Base.sitestatus.AllowInsert= true;
this.Base.sitestatus.AllowUpdate= true;
foreach (SOSiteStatusSelected line in this.Base.sitestatus.Select())
{
line.QtySelected = 1;
this.Base.sitestatus.Update(line);
SOSiteStatusSelectedExt rowExt = this.Base.sitestatus.Cache.GetExtension<SOSiteStatusSelectedExt>(line);
rowExt.UsrBrand = "testBrand";
this.Base.sitestatus.Cache.Update(rowExt);
}
}
In this case your extension SOSiteStatusSelectedExt is not a separate item. It's a part of the base record actually. So you don't need to update it separately.
line.QtySelected = 1;
SOSiteStatusSelectedExt rowExt = this.Base.sitestatus.Cache.GetExtension<SOSiteStatusSelectedExt>(line);
rowExt.UsrBrand = "testBrand";
this.Base.sitestatus.Update(line);

Resources