Reusable Business Logic Implementation
Suppose that you want to use the same business logic in multiple places in your application. That is, you have at least two graphs in which you need to insert the logic. The graphs operate with data in the data access classes (DACs) and implement business logic through event handlers, actions, and other methods.
You encapsulate the business logic that you want to reuse in a generic graph extension, which is a graph extension that does not relate to any particular graph and can be used with any base graph. The generic graph extension operates with data by using the mapped cache extensions, which are cache extensions that are not bound to any particular DAC and can extend any DAC.
These classes are described in detail in the sections below. (For details on the implementation of the classes, see To Implement Reusable Business Logic and To Insert Reusable Business Logic That Has Already Been Declared.)
Mapped Cache Extension
A mapped cache extension is an analog of a data access class (DAC) for a generic graph extension. In the mapped cache extension, you include the main fields that are used in the reusable business logic implementation. You map the fields of a mapped cache extension to the fields of a base DAC by using the mapping class, which is described in the following section. The mapped cache extension can also include the fields that are not mapped to any base DAC fields. (For details, see Mapped Cache Extensions and the Application Database.)
The class of a mapped cache extension inherits from the
PXMappedCacheExtension
abstract
class, which derives from
PXCacheExtension and IBqlTable.
- A
public abstract
class (which is also referred to as class field or BQL field).You derive the class from the IBqlField interface and assign it a name that starts with a lowercase letter.
- A
public virtual
property (which is also referred to as property field).You assign the property a name that starts with an uppercase letter. The system assigns the PXMergeAttributes attribute with MergeMethod.Merge to each field of a mapped cache extension automatically. If you define the PXMergeAttributes attribute for a field of a mapped cache extension explicitly, the explicitly defined attribute overrides the automatically defined. You can also define any other attributes for the property field of the mapped cache extension, or not define the attributes at all.
//Mapped cache extension
public class Document : PXMappedCacheExtension
{
//BAccountID field
public abstract class bAccountID : IBqlField
{
}
protected Int32? _BAccountID;
public virtual Int32? BAccountID
{
get
{
return _BAccountID;
}
set
{
_BAccountID = value;
}
}
//CuryID field
public abstract class curyID : IBqlField
{
}
protected String _CuryID;
public virtual String CuryID
{
get
{
return _CuryID;
}
set
{
_CuryID = value;
}
}
...
}
Mapping Class
A mapping class is a protected
class that defines the mapping
between the fields of a mapped cache extension and the fields of a DAC. In a generic
graph extension, you declare a mapping class for each mapped cache extension that
you need to use in the reusable logic implementation.
- Extension: The mapped cache extension
- Table: The DAC to which the extension is mapped
//A mapping class
protected class DocumentMapping : IBqlMapping
{
public Type Extension => typeof(Document);
protected Type _table;
public Type Table => _table;
public DocumentMapping(Type table)
{
_table = table;
}
public Type BAccountID = typeof(Document.bAccountID);
public Type CuryInfoID = typeof(Document.curyInfoID);
public Type CuryID = typeof(Document.curyID);
public Type DocumentDate = typeof(Document.documentDate);
}
Generic Graph Extension
public abstract
class that
encapsulates business logic that can be used in multiple places of an MYOB Acumatica application or an MYOB Acumatica Framework-based application. The class inherits from the
PXGraphExtension<TGraph> class, as the following code
shows.public abstract class MultiCurrencyGraph<TGraph, TPrimary> :
PXGraphExtension<TGraph>
where TGraph : PXGraph
where TPrimary : class, IBqlTable, new()
{
}
- The mapping classes.
- The
protected abstract
methods that return the mapping classes. You have to override these methods in the implementation class. - The views that can have either mapping-based declaration or standard declaration. You declare a mapping-based view by using the PXSelectExtension<Table> class.
- The event handlers, actions, and other methods.
Implementation Class
- The base graph to which you add reusable logic
- The main DAC of the primary data view of the base graph
public class MultiCurrency : MultiCurrencyGraph<OpportunityMaint, CROpportunity>
{
protected override DocumentMapping GetDocumentMapping()
{
return new DocumentMapping(typeof(CROpportunity))
{
DocumentDate = typeof(CROpportunity.closeDate)
};
}
protected override CurySourceMapping GetCurySourceMapping()
{
return new CurySourceMapping(typeof(Customer));
}
public PXSelect<CRSetup> crCurrency;
protected PXSelectExtension<CurySource> SourceSetup =>
new PXSelectExtension<CurySource>(crCurrency);
protected virtual CurySourceMapping GetSourceSetupMapping()
{
return new CurySourceMapping(typeof(CRSetup))
{
CuryID = typeof(CRSetup.defaultCuryID),
CuryRateTypeID = typeof(CRSetup.defaultRateTypeID)
};
}
protected override CurySource CurrentSourceSelect()
{
...
}
}