0
votes

We are trying to have contracts generated and activated when invoice released like in the T300 training class. It works if the contract template has no contract items defined. However, if the contract template has any contract items, then it fails with error:

CT Error: SAAS001 has no Setup Price in this Currency

It doesn't matter if multi currency enabled or not. The SAAS001 contract item has a setup price of 0 and a renew price of $5000. The non-stock item SAAS001 has a default price...and we have setup base price for the USD currency that is on the template.

1
We added code to the ARReleaseProcess - David Eichner

1 Answers

1
votes

If there are one or more details in the Contract Template, in order for CTBillEngine to set up and activate a contract, it must be first committed to the database (read, the Complete method must be invoked on PXTransactionScope).

To address this business case, you must move contracts setup and activation from Persist to the overriden ReleaseDocProc method:

using PX.Data;
using PX.Objects.CS;
using PX.Objects.CT;
using PX.Objects.GL;
using System;
using System.Collections.Generic;

namespace PX.Objects.AR
{
    public class ARReleaseProcess_Extension : PXGraphExtension<ARReleaseProcess>
    {
        public bool SetupContract = false;
        private List<Contract> setupContracts = new List<Contract>();

        public delegate List<ARRegister> ReleaseDocProcDel(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList,
            ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete);

        [PXOverride]
        public List<ARRegister> ReleaseDocProc(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList,
            ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete, ReleaseDocProcDel del)
        {
            var result = del(je, ardoc, pmBatchList, onreleasecomplete);

            CTBillEngine engine = PXGraph.CreateInstance<CTBillEngine>();
            if (SetupContract)
            {
                foreach (var contract in setupContracts)
                {
                    engine.SetupAndActivate(contract.ContractID, contract.ActivationDate);
                }
            }

            return result;
        }

        public delegate void PersistDelegate();
        [PXOverride]
        public void Persist(PersistDelegate baseMethod)
        {
            ARRegister invoice = Base.ARDocument.Current;
            if (SetupContract)
            {
                ContractMaint contractMaint = PXGraph.CreateInstance<ContractMaint>();
                foreach (ARTran tran in PXSelect<ARTran,
                    Where<ARTran.tranType, Equal<Required<ARInvoice.docType>>,
                        And<ARTran.refNbr, Equal<Required<ARInvoice.refNbr>>>>,
                    OrderBy<Asc<ARTran.tranType, Asc<ARTran.refNbr,
                            Asc<ARTran.lineNbr>>>>>
                    .Select(Base, invoice.DocType, invoice.RefNbr))
                {
                    Contract contract = CreateActivateContract(contractMaint,
                        invoice.DocDate, invoice.CustomerID, invoice.CustomerLocationID);
                    setupContracts.Add(contract);
                }
            }
            baseMethod();
        }

        private Contract CreateActivateContract(ContractMaint contractMaint,
            DateTime? invoiceDate, int? customerID, int? customerLocationID)
        {
            contractMaint.Clear();

            Contract contract = (Contract)contractMaint.Contracts.Cache.CreateInstance();
            contract = contractMaint.Contracts.Insert(contract);

            Contract template = PXSelect<Contract,
                Where<Contract.isTemplate, Equal<boolTrue>,
                    And<Contract.contractCD, Equal<Required<Contract.contractCD>>>>>
                .Select(Base, "SIMCARD");
            if (template == null)
            {
                throw new PXException("The SIMCARD contract template was not found.");
            }

            contract.TemplateID = template.ContractID;
            contract.CustomerID = customerID;
            contract = contractMaint.Contracts.Update(contract);
            contract.LocationID = customerLocationID;
            contract.StartDate = invoiceDate;
            contract.ActivationDate = invoiceDate;
            contract = contractMaint.Contracts.Update(contract);

            contractMaint.Save.Press();
            return contract;
        }
    }
}

Make sure to keep the original customization created for the SOInvoiceEntry BLC:

    using PX.Data;
    using PX.Objects.AR;
    using System.Collections;

    namespace PX.Objects.SO
    {
        public class SOInvoiceEntry_Extension : PXGraphExtension<SOInvoiceEntry>
        {
            public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
            [PXOverride]
            public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
            {
                PXGraph.InstanceCreated.AddHandler<ARReleaseProcess>((graph) =>
                {
                    // Setting the SetupContract flag to create, set up, and activate
                    // the contracts at the SOInvoice release
                    graph.GetExtension<ARReleaseProcess_Extension>().SetupContract = true;
                });

                return baseMethod(adapter);
            }
        }
    }