Solved

REST API: how can I UPDATE an existing payment?


Userlevel 2
Badge

I have an open payment for a Sales Order in Acumatica.  Currently, Applied To Order is set to 0.00 for the payment attached to the order.  I would like to change this value to the unpaid balance.  I can easily do this in SOAP.  For REST, I am using the following URL in Postman:

https://sandbox.com/AcumaticaERP/entity/Default/22.200.001/Payment

 

However, I am constantly getting the following error:

"Inserting  'AR Payment' record raised at least one error. Please review the errors.; ARAccountID: 'AR Account' cannot be empty.; ARSubID: 'AR Subaccount' cannot be empty."

 

Here’s is the body I’m passing:

{

        "ReferenceNbr": { "value": "598089" },

        "PaymentRef": {"value": "5006956/4/23/2024 8:18:10 AM" },

        "AppliedToOrder": {"value": 200.00},

        "CashAccount": {"value": "01010"},

        "PaymentAmount": {"value": 200.00},

        "PaymentMethod": {"value": "CASH"}

}

icon

Best answer by Django 3 May 2024, 23:44

View original

19 replies

Userlevel 7
Badge +5
I thought that I had more information/documentation but I found this in my Postman workspace. It’s not an update but I would imagine that if you’re including the key fields to access the payment record then the application should happen as desired.
 
You might change your DocType to Order (Or Sales Order- not sure of the exact string and I don’t have my ACM system up and running).
 
Hopefully that pushes you in the right direction.
 
{
    "Type":{"value":"Payment"},
    "CustomerID":{"value":"1200"},
    "LocationID":{"value":"MAIN"},
    "ApplicationDate":{"value":"2024-03-08"},
    "PaymentMethod":{"value":"CCAMEX"},
    "CashAccount":{"value":"CLR00101"},
    "PaymentRef":{"value":"John"},
    "Description":{"value":"Payment made"},
    "PaymentAmount":{"value":"149"},
    
    "DocumentsToApply":[
        {
            "DocType":{"value":"Invoice"},
            "ReferenceNbr":{"value":"000047"},
            "AmountPaid":{"value":"149"}
        }
    ]
}
Userlevel 2
Badge

I stopped getting the error once I added the “Type”.  However, I just get the Payment object back in my result and the Applied To Order remains unchanged.  I’m not sure why you added an Invoice document to your request.  I don’t have an invoice.  I can update the Applied to Order using the UI or SOAP but not REST.   Here’s how I change it in the UI:

 

Userlevel 7
Badge +5

So, looking at my Web Service Endpoints, I see that Payment has an OrdersToApply entity.

I suspect that will be what you need for orders.

 

Userlevel 2
Badge

After I added that entity, a completely new Payment is created which is not what I want.  Here’s the body I sent:

{

        "Type":{"value":"Payment"},

        "CustomerID": { "value": "10409538" },

        "LocationID": { "value": "MAIN" },

        "RefernceNbr": {"value": "598047"},

        "PaymentMethod": {"value": "EBAY"},

        "CashAccount": {"value": "01016"},

        "PaymentAmount": {"value": 90.97},

        "OrdersToApply": [

            {

                "OrderType": {"value": "EB"},

                "OrderNbr": { "value": "EB00103052" },

                "AppliedToOrder": {"value": 10.00}

            }

        ]

}

I was FINALLY able to apply my payment to the sales order by using a totally different URL:

https://sandbox.com/AcumaticaERP/entity/Default/22.200.001/SalesOrder?$expand=Payments&$select=Payments/AppliedToOrder

{

    "CustomerID": {"value": "10409538"},

    "OrderType": {"value": "EB"},

    "OrderNbr": {"value": "EB00103052"},

    "Payments": [

        {

            "ReferenceNbr": {

                "value": "598047"

            },

            "AppliedToOrder": {

                "value": 10.0000

            }

        }

    ]        

}

Userlevel 7
Badge +5

Great news!

Out of curiosity, did you type your JSon above because I noticed this field is not correct:

  "RefernceNbr": {"value": "598047"},

Which means that ACM won’t be able to find an existing batch and will thus create a new one.

 

Userlevel 2
Badge

Yes, I mistyped in the actual JSON but the reason I changed to use ReferenceNbr is because it was creating a new payment when I used PaymentRef (with that correct number).

Just now, I changed “RefernceNbr” to “ReferenceNbr” and received this message:

    "innerException": {

        "message": "An error has occurred.",

        "exceptionMessage": "Another process has added the 'SOAdjust' record. Your changes will be lost.",

        "exceptionType": "PX.Data.PXLockViolationException",

        "stackTrace": "   at PX.Data.PXCache`1.PersistInserted(Object row, Boolean bypassInterceptor)\r\n   at PX.Data.PXCache`1.Persist(PXDBOperation operation)\r\n   at PX.Data.PXGraph.Persist()\r\n   at PX.Objects.AR.ARPaymentEntry.Persist()\r\n   at KN.ChaparralMotors.KCHARPaymentEntryExt.Persist(PersistDelegate del)\r\n   at PX.Objects.Extensions.ProcessAffectedEntitiesInPrimaryGraphBase`4.Persist(Action basePersist)\r\n   at PX.Data.PXSave`1.<HandlerInternal>g__Persist|3_2()\r\n   at PX.Data.PXSave`1.<HandlerInternal>d__3.MoveNext()\r\n   at PX.Data.PXAction`1.<Press>d__38.MoveNext()\r\n   at PX.Data.PXAction`1.<Press>d__38.MoveNext()\r\n   at PX.Api.SyImportProcessor.SyStep.PressButton(PXAction button, PXAdapter adapter, SyView view, String actionName, Object[] currents)\r\n   at PX.Api.SyImportProcessor.SyStep.CommitChangesInt(Object itemToBypass, PXFilterRow[] targetConditions, PXFilterRow[] filtersForAction, SyImportRowResult importResult)\r\n   at PX.Api.SyImportProcessor.SyStep.CommitChanges(Object& itemToBypass, PXFilterRow[] targetConditions, PXFilterRow[] filtersForAction)\r\n   at PX.Api.SyImportProcessor.ExportTableHelper.ExportTable()"

    }

Userlevel 7
Badge +5

Since you’re updating an existing payment and you only want to update the records on the Sales Order tab, just include the fields you need to locate the payment batch. I suspect that the error you encountered is being caused by you trying to update a field that another process is trying to update to a different value. It looks like you have an override of the Persist method in the mix that may have caused a conflict in this case.

I tested this structure on a setup of 22R2 that I have installed and it did what I think you're aiming for.

{
    "Type":{"value":"Payment"},
    "ReferenceNbr":{"value":"598047"},
   
    "OrdersToApply":[
        {
            "OrderType":{"value":"EB"},
            "OrderNbr":{"value":"EB00103052"},
            "AppliedToOrder":{"value":"10"}
        }
    ]
}
Userlevel 2
Badge

No, I just tried that and it gives me the same error.  It looks like you removed all the attributes that are used to create a new payment.  I’ll just use the SalesOrder API call that I mentioned above since it works.  I was just disappointed that I couldn’t do the same thing using a Payment API call.  Thank you for your help anyway.

Userlevel 7
Badge +5

Just to be clear, you can do that with the existing API.

I think you have an issue in your KCHARPaymentEntryExt.Persist override code that’s causing the error that you’re seeing.

 

Userlevel 2
Badge

Just to be clear, you can do that with the existing API.

I think you have an issue in your KCHARPaymentEntryExt.Persist override code that’s causing the error that you’re seeing.

 

I’m not using code yet.  These are the results I got by using Postman.

Userlevel 7
Badge +5

When you use the REST API, you’re will be invoking the Acumatica graph (business) logic, no matter how you’re connecting to the endpoint, whether using Postman, an application, or from some external site. You have no choice in the matter.

The instance of Acumatica that you’re connecting to does have a customization in place that is adding additional logic to the Persist method within the ARPaymentEntry graph (see the clip I added to my message above with the customization highlighted). It’s possible that the code in that customization is causing you to not be able to use the Payment end point.

However, as you’ve found, going through the Sales Order endpoint doesn’t cause this error to arise. Those fields on the SO screen are built in a way that isn’t connected directly to the Payment batch so updating them works slightly differently than updating the Payment batch directly. The end result is the same but it’s not exactly the same Acumatica code paths being run when you update the Amt to Apply value on the SO screen.

But you do have a working solution, which is great!

Userlevel 2
Badge

Sorry, I thought you meant that I was using code to make the API calls.  I’m trying to delete the payment now using the REST API but I just get the following error using a DELETE method instead of a PUT method:

{

    "message": "An error has occurred.",

    "exceptionMessage": "Object reference not set to an instance of an object.",

    "exceptionType": "System.NullReferenceException",

    "stackTrace": "   at PX.Api.ContractBased.SystemContracts.V2.RestController.CreateEntityFromKeys(String objectName, String idsString)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_1.<GetExecutor>b__0(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"

}

Here’s the body that I’m passing:

{

        "Type":{"value":"Payment"},

        "ReferenceNbr": {"value": "598095"}

}

Userlevel 7
Badge +5

Use a PUT and try:

{

        "Type":{"value":"Payment"},

        "ReferenceNbr": {"value": "598095"},

        “delete”:true

}

Userlevel 2
Badge

I tried that too but Postman just returned the entire Payment object.

Userlevel 7
Badge +5

The other way to do it is to query the record and you’ll see an id value. This will be the NoteID field value:

{
    "id": "70745a61-ae52-ee11-9d72-645d867a1962",
    "rowNumber": 1,
    "note": {
        "value": ""
    },
    "ReferenceNbr": {
        "value": "014054"
 
Use that ID in the URL with a DELETE call:
https://myserver/company/entity/endpoint/20.200.001/Payment/70745a61-ae52-ee11-9d72-645d867a1962
Userlevel 7
Badge +5

You can also do it with the direct URL as well:

https://myserver/company/entity/endpoint /20.200.001/Payment/Payment/589095

Userlevel 2
Badge

That worked but I really need it to work like the SOAP API call where I pass in the ReferenceNbr.

Userlevel 2
Badge

You can also do it with the direct URL as well:

https://myserver/company/entity/endpoint /20.200.001/Payment/Payment/589095

Sorry, I didn’t see this when I was typing my response.  Awesome!  Thanks...it works!  I guess Payment is the ReferenceNbr parameter!!  😀

Userlevel 7
Badge +5

Because it’s a two part key, it looks odd.  If you were deleting a prepayment it would look a little more clear:

https://myserver/company/entity/endpoint /20.200.001/Payment/Prepayment/589095

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved