수색…


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>

반환 true 지정된 DAC에 해당하는 DB 테이블 레코드, 포함되지 않는 경우 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를 꺼냅니다.

selector에 의해 현재 참조 된 외부 데이터 레코드를 가져옵니다.

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 자손 중 하나 (예 : PXIntAttribute 또는 PXStringAttribute )로 표시된 언 바운드 필드이면 RowSelecting 이벤트 중에 해당 계산이 추가로 트리거됩니다.

기본 제공 일반 수식 목록

미정

수식의 직접 및 중재 순환 참조

미정

조건부 수식의 제어 흐름

미정

한 필드에서 여러 수식 사용

미정

PXRestrictor 특성

소개

그러나 중요하고 자주 사용되는 PXSelectorAttribute 특성 (선택기라고도 함)에는 두 가지 주요 단점이 있습니다.

  • 선택기 조건을 만족하는 항목이없는 경우 정보 메시지 "<object_name> cannot be found in the system" 제공합니다.
  • 레코드의 다른 필드를 업데이트하지만 선택기에서 참조하는 개체가 이미 변경되어 해당 조건을 더 이상 충족하지 않으면 동일한 오류 메시지가 나타납니다. 법이 소급해서는 안되기 때문에이 행동은 분명히 잘못되었습니다.

PXRestrictorAttribute (제한 PXRestrictorAttribute 도 함)는 이러한 문제를 해결하는 데 사용할 수 있습니다.

세부

PXRestrictorAttribute 가 단독으로 작동하지 않습니다. 항상 PXSelectorAttribute 와 쌍을 PXSelectorAttribute 합니다. 선택자없이리스트 릭터를 사용하면 효과가 없습니다.

제한 기는 동일한 필드에서 선택기를 찾아서 추가 조건과 해당 오류 메시지를 주입합니다. 제한 조건은 부울 AND를 통해 선택기 조건에 추가되며 참조 된 개체가 제한 조건 제약 조건을 위반하는 경우 적절한 오류 메시지가 생성됩니다. 또한 참조 된 객체가 변경되어 더 이상 제한 조건을 충족시키지 않으면 참조 객체의 다른 필드를 변경할 때 오류 메시지가 생성되지 않습니다.

일반적인 사용법 :

[PXDBInt]
[PXSelector(typeof(Search<FAClass.assetID, Where<FAClass.recordType, Equal<FARecordType.classType>>>),
    typeof(FAClass.assetCD), typeof(FAClass.assetTypeID), typeof(FAClass.description), typeof(FAClass.usefulLife),
    SubstituteKey = typeof(FAClass.assetCD),
    DescriptionField = typeof(FAClass.description), CacheGlobal = true)]
[PXRestrictor(typeof(Where<FAClass.active, Equal<True>>), Messages.InactiveFAClass, typeof(FAClass.assetCD))]
[PXUIField(DisplayName = "Asset Class", Visibility = PXUIVisibility.Visible)]
public virtual int? ClassID { get; set; }

하나의 선택자 속성과 함께 여러 제한자가 사용될 수 있습니다. 이 경우 모든 추가 제한 기 조건은 결정되지 않은 순서로 적용됩니다. 조건을 위반하면 해당 오류 메시지가 생성됩니다.

선택기 자체의 Where<> 조건은 모든 제한 자 조건 후에 적용됩니다.

[PXDefault]
//  An aggregate attribute containing the selector inside.
// -
[ContractTemplate(Required = true)]
[PXRestrictor(typeof(Where<ContractTemplate.status, Equal<Contract.status.active>>), Messages.TemplateIsNotActivated, typeof(ContractTemplate.contractCD))]
[PXRestrictor(typeof(Where<ContractTemplate.effectiveFrom, LessEqual<Current<AccessInfo.businessDate>>, 
    Or<ContractTemplate.effectiveFrom, IsNull>>), Messages.TemplateIsNotStarted)]
[PXRestrictor(typeof(Where<ContractTemplate.discontinueAfter, GreaterEqual<Current<AccessInfo.businessDate>>, 
    Or<ContractTemplate.discontinueAfter, IsNull>>), Messages.TemplateIsExpired)]
public virtual int? TemplateID { get; set; }

옵션

PXRestrictorAttribute의 생성자는 세 개의 매개 변수를 사용합니다.

  1. 제한 기의 추가 조건. 이 BQL 유형은 IBqlWhere 인터페이스를 구현해야합니다.
  2. 적절한 오류 메시지. 메시지에는 컨텍스트를 표시하는 형식 요소 (중괄호)가 포함될 수 있습니다. 메시지는 지역화 가능한 정적 클래스 (예 : PX.Objects.GL.Messages )에 정의 된 문자열 상수 여야합니다.
  3. 필드 유형의 배열입니다. 이러한 필드는 현재 개체에 속해야하며 IBqlField 인터페이스를 구현해야합니다. 필드 값은 오류 메시지 형식으로 사용됩니다.

또한 제한 기 동작을 지정하는 몇 가지 옵션이 있습니다.

상속 된 제한 자 재정의

ReplaceInherited 속성은 현재 제한자가 상속 된 제한을 재정의해야하는지 여부를 나타냅니다. 이 속성을 true로 설정하면 모든 집계 속성 또는 기본 속성에 배치 된 모든 상속 된 제한자가 대체됩니다.

상속 된 제한 기 대체 :

 [CustomerActive(Visibility = PXUIVisibility.SelectorVisible, Filterable = true, TabOrder = 2)]
 [PXRestrictor(typeof(Where<Customer.status, Equal<CR.BAccount.status.active>,
    Or<Customer.status, Equal<CR.BAccount.status.oneTime>,
    Or<Customer.status, Equal<CR.BAccount.status.hold>,
    Or<Customer.status, Equal<CR.BAccount.status.creditHold>>>>>), Messages.CustomerIsInStatus, typeof(Customer.status), 
    ReplaceInherited = true)] // Replaced all restrictors from CustomerActiveAttribute
[PXUIField(DisplayName = "Customer")]
[PXDefault()]
public override int? CustomerID { get; set; }

합리적인 대안이있는 경우 응용 프로그램 코드에서 ReplaceInherited 속성을 사용하는 것을 권장하지 않습니다. 이 속성은 주로 사용자 지정에 사용하기위한 것입니다.

전역 캐싱

CacheGlobal 에서와 같은 방법으로 글로벌 사전 기능을 지원 PXSelectorAttribute .

사용을위한 권장 사항

제한 조건 만 사용하십시오.

제한 자와 선택기를 함께 사용하면 후자에 IBqlWhere 절이 IBqlWhere 합니다. 이상적으로 모든 조건은 제한 장치로 옮겨야합니다. 이 접근 방식은보다 사용자 친화적 인 오류 메시지를 제공하고 불필요한 소급 오류를 제거합니다.

이상적인 예 :

[PXDBString(5, IsFixed = true, IsUnicode = false)]
[PXUIField(DisplayName = "Type", Required = true)]
[PXSelector(typeof(EPActivityType.type), DescriptionField = typeof(EPActivityType.description))]
[PXRestrictor(typeof(Where<EPActivityType.active, Equal<True>>), Messages.InactiveActivityType, typeof(EPActivityType.type))]
[PXRestrictor(typeof(Where<EPActivityType.isInternal, Equal<True>>), Messages.ExternalActivityType, typeof(EPActivityType.type))]
public virtual string Type { get; set; }

가능한 소급 오류 :

[PXDBInt]
[PXUIField(DisplayName = "Contract")]
[PXSelector(typeof(Search2<Contract.contractID,
    LeftJoin<ContractBillingSchedule, On<Contract.contractID, Equal<ContractBillingSchedule.contractID>>>,
    Where<Contract.isTemplate, NotEqual<True>,
        And<Contract.baseType, Equal<Contract.ContractBaseType>,
        And<Where<Current<CRCase.customerID>, IsNull,
            Or2<Where<Contract.customerID, Equal<Current<CRCase.customerID>>,
                And<Current<CRCase.locationID>, IsNull>>,
            Or2<Where<ContractBillingSchedule.accountID, Equal<Current<CRCase.customerID>>,
                And<Current<CRCase.locationID>, IsNull>>,
            Or2<Where<Contract.customerID, Equal<Current<CRCase.customerID>>,
                And<Contract.locationID, Equal<Current<CRCase.locationID>>>>,
            Or<Where<ContractBillingSchedule.accountID, Equal<Current<CRCase.customerID>>,
                And<ContractBillingSchedule.locationID, Equal<Current<CRCase.locationID>>>>>>>>>>>>,
    OrderBy<Desc<Contract.contractCD>>>),
    DescriptionField = typeof(Contract.description),
    SubstituteKey = typeof(Contract.contractCD), Filterable = true)]
[PXRestrictor(typeof(Where<Contract.status, Equal<Contract.status.active>>), Messages.ContractIsNotActive)]
[PXRestrictor(typeof(Where<Current<AccessInfo.businessDate>, LessEqual<Contract.graceDate>, Or<Contract.expireDate, IsNull>>), Messages.ContractExpired)]
[PXRestrictor(typeof(Where<Current<AccessInfo.businessDate>, GreaterEqual<Contract.startDate>>), Messages.ContractActivationDateInFuture, typeof(Contract.startDate))]       
[PXFormula(typeof(Default<CRCase.customerID>))]
[PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]
public virtual int? ContractID { get; set; }


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow