Skip to main content

Hi, I’m struggling to insert a new Customer Contract record into Acumatica using code. 

The screen is CT301000
Here is the screen shot:

and here is the important part of the code I’m using with added comments

//create the graph
ContractMaint contractMaint = PXGraph.CreateInstance<ContractMaint>();
//create a new instance of the dac
Contract contract = (Contract)contractMaint.Contracts.Cache.CreateInstance();
//insert into the view
contract = contractMaint.Contracts.Insert(contract);
//set the contractCD, it's using a segmented key but I think this is the way to set the value
contract.ContractCD = "D -D -<NEW> ";
contract = contractMaint.Contracts.UpdateCurrent();
//set the template id, update the contract record with contract template info
//t has a value of course
contract.TemplateID = t;
contract = contractMaint.Contracts.UpdateCurrent();
//set the customer id and update the contract record with customer info
//c has a value of course
contract.CustomerID = c;
contract = contractMaint.Contracts.UpdateCurrent();

try
{
//persist the data to the database
contractMaint.Contracts.Cache.Persist(PXDBOperation.Insert);
//alternatively use PressSave
//contractMaint.Actions.PressSave();
}
catch (Exception ex)
{
string g = ex.Message;
}

When I run this code an error occurs on the Persists method.

The ex.message is “Error: Inserting  'Contract' record raised at least one error. Please review the errors.”
When I check the ex.InnerMessages in the watch window I see the following. 

I’ve set the Contract Template and Customer fields, and I expected the update commands to set the Description, Duration and Currency fields. (which is what happens when I enter a Customer Contract using the UI). 
Can anyone advise what I’m doing wrong?

Thanks

I meant to add that I get the same error when I replace

contractMaint.Contracts.Cache.Persist(PXDBOperation.Insert);

with 

contractMaint.Actions.PressSave();

 


The errors you see are required fields. You need to give them values in your code in the same way that you set the ContractCD, or by doing

contractMaint.Contracts.SetValueExt<fieldType>(contract, fieldValue);

 

I can see you’ve attempted Template and Customer. I suppose the comments mean you’ve tested for null? 

I can’t say for sure you methods are wrong, because there are a lot of different ways to accomplish the same thing in Acumatica. Here’s how I would write it.

//create the graph
ContractMaint contractMaint = PXGraph.CreateInstance<ContractMaint>();

//create a new instance of the dac
Contract contract = contractMaint.Contracts.Insert();

//set the contractCD, it's using a segmented key but I think this is the way to set the value
contractMaint.Contracts.SetValueExt<PMProject.contractCD>(contract, "D -D -<NEW> ");

//set the template id
contractMaint.Contracts.SetValueExt<PMProject.templateID>(contract, t);

//set the customer id and update the contract record with customer info
contractMaint.Contracts.SetValueExt<PMProject.customerID>(contract, c);

// additional required fields

contract = contractMaint.Contracts.Update(contract);

try
{
// save the data to the database
contractMaint.Actions.PressSave();
}
catch (Exception ex)
{
string g = ex.Message;
}

 

The contract CD looks unusual to me, but again, I can’t say for sure it’s wrong.


Hello, thanks for taking the time to look at this. 

I’ve had a go with the code you set over using SetValueExt but this didn’t seem to set the dependant fields and they remained set to null. e.g. after setting the contract template, the description was still null. When the PressSave action occurred the error said that description, currency and duration were missing.

You asked whether I had tested for null, the values I’ve used do exist and in the code I was using, the dependant fields are all populated in the cache. The screen shots below show the currency, description and duration all present and correct, along with customer id. 

 

The problem seems to occur at the point of PressSave. It’s like the values in the cache are lost and all the fields reset to null.

I’ve added the most recent version of the code below if you had any other ideas.

ContractMaint contractMaint = PXGraph.CreateInstance<ContractMaint>();
Contract contract = (Contract)contractMaint.Contracts.Cache.CreateInstance();
contract = contractMaint.Contracts.Insert(contract);

contract.ContractCD = "D -D -<NEW> ";
contract=contractMaint.Contracts.UpdateCurrent();
contract.TemplateID = i;
contract=contractMaint.Contracts.UpdateCurrent();
contract.CustomerID = c;
contract=contractMaint.Contracts.UpdateCurrent();

try
{
contractMaint.Actions.PressSave();
}
catch (Exception ex)
{
string g = ex.Message;
}

 Thanks


Are your ContractCD’s auto-numbered (<NEW>)? 

 

If so, you shouldn’t need to set the ContractCD. Have you tried not setting the ContractCD?


The Contract ID on this system has been configured to use a multi-part segmented key, see below.

Values are required for the first 2 sections and <NEW> is defined for the 3rd part.

I think there is a decent chance that this is the root of the problem. For testing purposes I’m just setting the value to "D -D -<NEW> "
If I copy this value into the UI things work fine, but perhaps it’s working differently in code. 

I’m going to test the code on another instance of Acumatica where the Contract ID is set to <NEW> and see what happens. 

Thanks


OK then, I’ve tested the code on a different instance of Acumatica where the Contract ID is the default set up of <NEW>. With the default key, the contract was created and everything is working fine. 

So the problem is now, how to provide a value for a multi-part segmented key.
The segmented key in this case looks like the following:
 

The screen shot above shows the format when entering a new customer contract.

CreateContractX("123456789-1234567-");
CreateContractX("123456789-1234567-<NEW>");
CreateContractX("123456789-1234567-<NEW> ");
CreateContractX("1234567891234567");
CreateContractX("1234567891234567<NEW>");
CreateContractX("1234567891234567<NEW> ");

I’ve adjusted the code so that I can pass a contract CD value to a CreateContractX method. I’ve tried all the values shown above. The attempts without the - character in get closest and the ContractCD value in the watch window looks OK but the contract isn’t created when the PressSave action is invoked. It returns the same message saying about fields being required. Odd because I can see in the Watch window that the values are present.  

 

Does anyone know how I should set the ContractCD value?


@Dmitrii Naumov 


Finally got to the bottom of this. I checked the Contracts cache and noticed that the Insert command was adding a new item to the cache, but also the first Update command was adding a second item to the cache. I guess I was checking the values of one of the items in the cache and the values were all correct but the errors were coming from the other, unexpected and unnoticed, item.

I’ve commented out the Insert command. The item is added to the cache after the first Update command and the following 2 updates are applied correctly. The contract is created as it should be. The code is below.

Disappointed this as all taken so long. 

@darylbowman thanks for assisting.   

ContractMaint contractMaint = PXGraph.CreateInstance<ContractMaint>();
Contract contract = (Contract)contractMaint.Contracts.Cache.CreateInstance();
//contract = contractMaint.Contracts.Insert(contract);

contract.ContractCD = "1234567891234567<NEW>";
contract = contractMaint.Contracts.Update(contract);
contract.TemplateID = i;
contract = contractMaint.Contracts.Update(contract);
contract.CustomerID = c;
contract = contractMaint.Contracts.Update(contract);

try
{
contractMaint.Actions.PressSave();
}
catch (Exception ex)
{
string g = ex.Message;
}

 


Thank you for sharing your solution with the community @stephenward03 !


Makes sense I think. I've never used this:

(Contract)contractMaint.Contracts.Cache.CreateInstance()


Reply