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);
}
}
}