PXFormula 屬性

一般說明

Acumatica 中的公式是 DAC 欄位,它是根據其他物件欄位的值計算的。

為了計算公式,Aсumatiсa 框架提供了一組各種操作和函式(例如算術,邏輯和比較運算以及字串處理函式;請參閱內建公式列表 )。除了欄位值之外,公式還可以使用 Acumatica 核心和應用程式解決方案提供的各種常量。此外,公式不僅可以從當前記錄中獲得計算值,還可以從其他來源獲得計算值(請參閱公式上下文及其修飾符 )。

公式的美妙之處在於它們會在適當的時間自動重新計算價值:

  • 欄位預設(插入新行;公式欄位的 FieldDefaulting 事件處理程式)
  • 關於依賴欄位的更新(每個依賴欄位的 FieldUpdated 事件處理程式)
  • 關於資料庫選擇(僅適用於未繫結欄位; RowSelecting 事件處理程式)
  • 在需要時保持資料庫持久化(開發人員應明確指定它; RowPersisted 事件處理程式)

在依賴欄位的更新上重新計算公式欄位值會引發公式欄位的 FieldUpdated 事件。這允許你建立一系列相關公式(請參閱公式中的直接和中介迴圈引用)。

應用程式開發人員可以編寫自己的應用程式端公式

使用方式

公式可以用於三種主要模式:

  • 只需計算值並將其分配給公式欄位(請參閱基本用法
  • 從公式欄位的現有值計算聚合值並將其分配給父物件中的指定欄位(請參閱聚合用法
  • 混合模式:計算公式值,將其分配給公式欄位,計算聚合值,並將其分配給父物件中的欄位(請參閱組合使用

還有另一種輔助模式,未繫結的公式,與混合模式非常相似,但公式的計算值未分配給公式欄位。立即計算聚合值並將其分配給父物件的欄位。有關詳細資訊,請參閱未繫結公式的用法

PXFormulaAttribute 屬性和建構函式引數

公式功能由 PXFormulaAttribute 實現。PXFormulaAttribute 的建構函式具有以下簽名:

public PXFormulaAttribute(Type formulaType)
{
    // ...
}

單個引數 formulaType 是一種公式表示式,用於計算來自同一資料記錄的其他欄位的欄位值。此引數必須滿足以下條件之一:

  • 必須實現 IBqlField 介面
  • 必須是 BQL 常量
  • 必須實現 IBqlCreator 介面(參見內建常用公式列表
public PXFormulaAttribute(Type formulaType, Type aggregateType)
{
    // ...
}

第一個引數 formulaType 與第一個建構函式中的相同。第二個引數 aggregateType 是一種聚合公式,用於計運算元資料記錄欄位中的父資料記錄欄位。可以使用聚合函式,例如 SumCalc,CountCalc,MinCalc 和 MaxCalc。應用開發人員可以建立自己的聚合公式。

聚合公式型別必須是泛型型別,並且必須實現 IBqlAggregateCalculator 介面。聚合公式型別的第一個通用引數必須實現 IBqlField 介面,並且必須具有父物件的欄位型別。

public virtual bool Persistent { get; set; }

PXFormulaAttribute.Persistent 屬性指示在將更改儲存到資料庫後屬性是否重新計算公式。如果在 RowPersisting 事件中更新了公式所依賴的欄位,則可能需要重新計算。預設情況下,該屬性等於 false

用法

在大多數情況下,公式用於直接計算來自同一資料記錄的其他欄位的公式欄位的值。

最簡單的公式用法示例:

[PXDBDate]
[PXFormula(typeof(FADetails.receiptDate))]
[PXDefault]
[PXUIField(DisplayName = Messages.PlacedInServiceDate)]
public virtual DateTime? DepreciateFromDate { get; set; }

在此示例中,ReceiptDate 欄位的值在插入新記錄和 ReceiptDate 欄位更新時分配給 DepreciateFromDate 欄位。

一個稍微複雜的例子:

[PXCurrency(typeof(APPayment.curyInfoID), typeof(APPayment.unappliedBal))]
[PXUIField(DisplayName = "Unapplied Balance", Visibility = PXUIVisibility.Visible, Enabled = false)]
[PXFormula(typeof(Sub<APPayment.curyDocBal, APPayment.curyApplAmt>))]
public virtual Decimal? CuryUnappliedBal { get; set; }

這裡,文件的未應用餘額計算為文件餘額與應用金額之間的差額。

具有預設值的多項選擇示例:

[PXUIField(DisplayName = "Class Icon", IsReadOnly = true)]
[PXImage]
[PXFormula(typeof(Switch<
    Case<Where<EPActivity.classID, Equal<CRActivityClass.task>>, EPActivity.classIcon.task,
    Case<Where<EPActivity.classID, Equal<CRActivityClass.events>>, EPActivity.classIcon.events,
    Case<Where<EPActivity.classID, Equal<CRActivityClass.email>,
        And<EPActivity.isIncome, NotEqual<True>>>, EPActivity.classIcon.email,
    Case<Where<EPActivity.classID, Equal<CRActivityClass.email>,
        And<EPActivity.isIncome, Equal<True>>>, EPActivity.classIcon.emailResponse,
    Case<Where<EPActivity.classID, Equal<CRActivityClass.history>>, EPActivity.classIcon.history>>>>>,
    Selector<Current2<EPActivity.type>, EPActivityType.imageUrl>>))]
public virtual string ClassIcon { get; set; }

領域順序

DAC 中的欄位順序對於校正公式計算很重要。必須在公式欄位之前的 DAC 中定義包括其他公式的所有源欄位(從中計算公式)。否則,可能會錯誤地計算欄位,或者可能導致執行時錯誤。

公式語境及其修飾語

預設情況下,公式計算的上下文受包含公式宣告的類的當前物件(記錄)限制。它也允許使用常量(Constant<> 類的後代)。

僅使用其物件欄位的公式:

public partial class Contract : IBqlTable, IAttributeSupport
{
    //...
    [PXDecimal(4)]
    [PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
    [PXFormula(typeof(Add<Contract.pendingRecurring, Add<Contract.pendingRenewal, Contract.pendingSetup>>))]
    [PXUIField(DisplayName = "Total Pending", Enabled=false)]
    public virtual decimal? TotalPending { get; set; }
    //...
}

但是,可以從其他來源獲取公式計算的輸入值:

  • BLC 中任何快取的當前記錄(如果已分配)。
  • PXSelectorAttribute 指定的外國記錄。
  • PXParentAttribute 指定的父記錄。

該公式支援以下上下文修飾符。

Current<TRecord.field>Current2<TRecord.field>

從儲存在 TRecord 快取的 Current 屬性中的記錄中獲取欄位值。

如果快取的 Current 屬性或欄位本身包含 null:

  • 當前<>強制欄位預設並返回預設欄位值。
  • Current2 <>返回 null。

例:

[PXFormula(typeof(Switch<
    Case<Where<
        ARAdjust.adjgDocType, Equal<Current<ARPayment.docType>>,
        And<ARAdjust.adjgRefNbr, Equal<Current<ARPayment.refNbr>>>>,
        ARAdjust.classIcon.outgoing>,
    ARAdjust.classIcon.incoming>))]
protected virtual void ARAdjust_ClassIcon_CacheAttached(PXCache sender)

Parent<TParent.field>

從駐留在當前 DAC 上的 PXParentAttribute 定義的父資料記錄中獲取欄位值。

public class INTran : IBqlTable
{
    [PXParent(typeof(Select<
        INRegister, 
        Where<
            INRegister.docType, Equal<Current<INTran.docType>>,
            And<INRegister.refNbr,Equal<Current<INTran.refNbr>>>>>))]
    public virtual String RefNbr { ... }
  
    [PXFormula(typeof(Parent<INRegister.origModule>))]
    public virtual String OrigModule { ... }
}

IsTableEmpty<TRecord>

如果對應於指定 DAC 的 DB 表不包含記錄,則返回 true,否則返回 false

public class APRegister : IBqlTable
{
    [PXFormula(typeof(Switch<
        Case<Where<
            IsTableEmpty<APSetupApproval>, Equal<True>>,
            True,
        Case<Where<
            APRegister.requestApproval, Equal<True>>,
            False>>,
        True>))]
    public virtual bool? DontApprove { get; set; }
}

Selector<KeyField, ForeignOperand>

獲取在當前 DAC 的外來鍵欄位(KeyField)上定義的 PXSelectorAttribute

獲取選擇器當前引用的外部資料記錄

計算並返回 ForeignOperand 定義的資料記錄上的表示式

public class APVendorPrice : IBqlTable
{
    // Note: inventory attribute is an
    // aggregate containing a PXSelectorAttribute
    // inside, which is also valid for Selector<>.
    // -
    [Inventory(DisplayName = "Inventory ID")]
    public virtual int? InventoryID
  
    [PXFormula(typeof(Selector<
        APVendorPrice.inventoryID, 
        InventoryItem.purchaseUnit>))]
    public virtual string UOM { get; set; }
}

在未繫結欄位上使用公式

如果公式欄位是標記有 PXFieldAttribute 後代之一的未繫結欄位(例如 PXIntAttributePXStringAttribute),則在 RowSelecting 事件期間另外觸發其計算。

內建常用公式列表

TBD

公式中的直接和中介迴圈引用

TBD

條件公式中的控制流程

TBD

在一個場上使用多個公式

TBD