Extension of Scan Components: To Add an Alternate Way to Search for Entities
This activity will walk you through the implementation of an alternate way to search for entities.
Story
Suppose that on the Receive and Put Away (PO302020) form, you need to be able to search purchase receipts by their date because you have only one unreleased purchase receipt per day.
Process Overview
You will override the DecorateScanState method by using the PXOverride attribute, and in this method, you will intercept the HandleAbsence method by using the ByAppend strategy. You will not override the GetByBarcode method, but instead will override the HandleAbsence method because it contains the logic of entity searching if the entity has not been found by the GetByBarcode method.
System Preparation
Before you begin performing the step of this activity, do the following:
- Prepare an MYOB Acumatica instance by performing the Test Instance: To Deploy an Instance prerequisite activity.
- Enable the following features on the Enable/Disable Features (CS100000) form, where they are in the Inventory and Order Management
group of features:
- Multiple Warehouse Locations
- Warehouse Management
- Receiving
Step: Adding an Alternate Way to Search for Entities
To add another way to search for entities, do the following:
- In the
PhoneRepairShop_Code
Visual Studio project, add a reference to the PX.BarcodeProcessing.dll file. - Create the
SearchReceiptsByDate
class, and make itpublic
. - Add the
using
directives shown in the following code to the file.using System; using PX.Data; using PX.BarcodeProcessing; using PX.Objects.PO.WMS; using PX.Objects.PO; using PX.Data.BQL.Fluent; using PX.Objects.AP; using PX.Data.BQL;
- Make the class an extension of the
PX.Objects.PO.WMS.ReceivePutAway
class.
public class SearchReceiptsByDate : ReceivePutAway.ScanExtension { }
- Override the DecorateScanState
method.
public class SearchReceiptsByDate : ReceivePutAway.ScanExtension { [PXOverride] public virtual ScanState<ReceivePutAway> DecorateScanState( ScanState<ReceivePutAway> original, Func<ScanState<ReceivePutAway>, ScanState<ReceivePutAway>> base_DecorateScanState) { return base_DecorateScanState(original); } }
- Search for the receipt input state of the receive
mode.
public class SearchReceiptsByDate : ReceivePutAway.ScanExtension { [PXOverride] public virtual ScanState<ReceivePutAway> DecorateScanState( ScanState<ReceivePutAway> original, Func<ScanState<ReceivePutAway>, ScanState<ReceivePutAway>> base_DecorateScanState) { var state = base_DecorateScanState(original); if (state is ReceivePutAway.ReceiveMode.ReceiptState receiptState) { } return state; } }
- Patch the logic of the component by using the interceptor
functionality.
public class SearchReceiptsByDate : ReceivePutAway.ScanExtension { [PXOverride] public virtual ScanState<ReceivePutAway> DecoracteScanState( ScanState<ReceivePutAway> original, Func<ScanState<ReceivePutAway>, ScanState<ReceivePutAway>> base_DecoracteScanState) { var state = base_DecoracteScanState(original); if (state is ReceivePutAway.ReceiveMode.ReceiptState receiptState) { receiptState .Intercept.HandleAbsence.ByAppend((basis, barcode) => { if (DateTime.TryParse(barcode.Trim(), out var date)) { POReceipt receiptByDate = SelectFrom<POReceipt>. LeftJoin<Vendor>.On<POReceipt.vendorID. IsEqual<Vendor.bAccountID>>.SingleTableOnly. Where< // The date parameter POReceipt.receiptDate.IsEqual<@P.AsDateTime>. // Other conditions are for narrowing the scope And<POReceipt.released.IsEqual<False>>. And<POReceipt.hold.IsEqual<False>>. And<POReceipt.receiptType.IsEqual<POReceiptType.poreceipt>>. And< Vendor.bAccountID.IsNull. Or<Match<Vendor, AccessInfo.userName.FromCurrent>>>>. View.ReadOnly.Select(basis, date); if (receiptByDate != null) return AbsenceHandling.ReplaceWith(receiptByDate); } return AbsenceHandling.Skipped; }); } return state; } }
- Optional: Extract the exact patching logic to a separate virtual method of the
extension for being able to suppress this patch in the
future.
public class SearchReceiptsByDate : ReceivePutAway.ScanExtension { [PXOverride] public virtual ScanState<ReceivePutAway> DecorateScanState( ScanState<ReceivePutAway> original, Func<ScanState<ReceivePutAway>, ScanState<ReceivePutAway>> base_DecorateScanState) { var state = base_DecorateScanState(original); if (state is ReceivePutAway.ReceiveMode.ReceiptState receiptState) PatchReceiptStateInReceiveMode(receiptState); return state; } protected virtual void PatchReceiptStateInReceiveMode( ReceivePutAway.ReceiveMode.ReceiptState receiptState) { receiptState .Intercept.HandleAbsence.ByAppend((basis, barcode) => { if (DateTime.TryParse(barcode.Trim(), out var date)) { POReceipt receiptByDate = SelectFrom<POReceipt>. LeftJoin<Vendor>.On<POReceipt.vendorID. IsEqual<Vendor.bAccountID>>.SingleTableOnly. Where< POReceipt.receiptDate.IsEqual<@P.AsDateTime>. And<POReceipt.receiptType. IsEqual<POReceiptType.poreceipt>>. And< Vendor.bAccountID.IsNull. Or<Match<Vendor, AccessInfo.userName.FromCurrent>>>>. View.ReadOnly.Select(basis, date); if (receiptByDate != null) return AbsenceHandling.ReplaceWith(receiptByDate); } return AbsenceHandling.Skipped; }); } }
- Fix or suppress the PX1016 error that is displayed by Acuminator.
- Build the project, and test the custom behavior on the Receive and Put Away (PO302020) form.