Skip to main content
Solved

REST API: how can I UPDATE an existing payment?


Forum|alt.badge.img+2

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"}

}

Best answer by Django

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

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

View original
Did this topic help you find an answer to your question?

19 replies

Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024
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"}
        }
    ]
}

Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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:

 


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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.

 


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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

            }

        }

    ]        

}


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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.

 


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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()"

    }


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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"}
        }
    ]
}

Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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.


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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.

 


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024
Django wrote:

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.


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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!


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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"}

}


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

Use a PUT and try:

{

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

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

        “delete”:true

}


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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

Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • Answer
  • May 3, 2024

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

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


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024

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


Forum|alt.badge.img+2
  • Author
  • Semi-Pro I
  • 66 replies
  • May 3, 2024
Django wrote:

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!!  😀


Forum|alt.badge.img+6
  • Captain II
  • 556 replies
  • May 3, 2024

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


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings