cancel
Showing results for 
Search instead for 
Did you mean: 

Inventory Stock Reversal in SAP: Best Practices for Order Cancellation via API

kenjon
Explorer
0 Kudos

I use SAP Business One daily.
I am working on an application built in Nextjs that connects to a backend built in Nestjs to fetch data.
Data like: Sales orders, A/R Invoices, Incoming Payments, Items, Warehouses, etc.

The API requests are made to SAP using oData queries in Nestjs. Via the URL: https://200.7.150.206:50000/b1s/v2

The issue I am facing right now is correctly canceling orders, invoices, and payments (the full order flow). When I cancel an order(sales order + a/r invoice + incoming payment) I want the items to go back into the warehouse as well. But that is not happening. I'll give an example:

1. I send a POST request to create a Sales Order with the following request body:

 

{
 "CardCode": "TKI_MEE",
 "DocDate": "2024-02-13",
 "DocDueDate": "2024-02-15",
 "DocumentLines": [
  {
   "ItemCode": "6055",
   "Quantity": "10",
   "UnitPrice": 55.0,
   "WarehouseCode": "TKI_MEEN"
  }
 ]
}

 

2. Then, I send a POST request to create an A/R Invoices with the following request Body:

 

{
 "CardCode": "TKI_MEE",
 "DocTotal": 550.0,
 "DocDueDate": "2024-02-15",
 "DocumentLines": [
  {
   "ItemCode": "6055",
   "BaseEntry": 26414, // the id(DocEntry) of the Sales Order I just created in step 1
   "BaseType": 17,
   "BaseLine": 0
  }
 ]
}

 

This creates an A/R Invoice based on the Sales Order in step 1.

3. Next, I send a POST request to create an Incoming Payment that is based on the Invoice. The request body is...

 

{
 "CardCode": "TKI_MEE",
 "CashAccount": "1060.11",
 "PaymentInvoices": [
  {
   "LineNum": 0,
   "SumApplied": 55,
   "DocEntry": 26098, // id(DocEntry) of the A/R Invoice created in step 2
   "InvoiceType": "it_Invoice"
  }
 ],
 "CashSum": 55
}

 

This will create a Payment that's based on the A/R Invoice in step 2.

What happens next is, the Item with code '6055' will get subtracted from the warehouse with code 'TKI_MEEN' with a quantity of 10. So after this complete transaction, I will have 10 less of that item inside of warehouse TKI_MEEN.

What do I do when I want to cancel this order and revert the inventory as well?
How I am currently doing it is wrong.

First I cancel the Incoming Payment. Then I cancel the A/R Invoice. Then I cancel the Sales Order.
It has to be in that order because they are dependent on each other. But this approach does not reverse the item (6055) of quantity 10 that is subtracted from the warehouse.

When I cancel this full order flow, the inventory should be restocked with all the items that were specified inside of the DocumentLines. How do I efficiently do this using API requests to SAP bs1?

I should also add that I used the following two links to help me with how to make SAP queries and to which endpoints I should make those:

https://sap.highwaytwo.com/Working_with_SAP_Business_One_Service_Layer.pdf

https://sap.highwaytwo.com/Service%20Layer%20API%20Reference.html

Accepted Solutions (0)

Answers (3)

Answers (3)

ANKIT_CHAUHAN
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi kenjon,

How do you perform Inventory Stock Reversal manually using SAP Business One client?

You need to perform the same action using Service Layer or API.

Kind regards,

ANKIT CHAUHAN

SAP Business One Support

 

kenjon
Explorer
0 Kudos

This is an example of a batch request in SAP oData:

--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary GET serviceRoot/Airlines HTTP/1.1
Accept: application/json;odata.metadata=minimal --batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
Content-ID: 1 POST serviceRoot/Airlines HTTP/1.1
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json;odata.metadata=minimal {
"@odata.type" : "Microsoft.OData.SampleService.Models.TripPin.Airline",
"AirlineCode" : "EK",
"Name" : "Emirates Airline"
} --batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary GET serviceRoot/Airlines HTTP/1.1
Accept: application/json;odata.metadata=minimal --batch_36522ad7-fc75-4b56-8c71-56071383e77b--

Source:oData Docs 

What this does:
Batch requests allow grouping multiple operations into a single HTTP request payload. The Batch request below contains the following operations in order listed:
1. A query request, returns all Airlines.
2. Create an entity, a new Airline.
3. A second query request Airlines.

Here is another batch request example:

--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET /b1s/v1/Items('i001')
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed;boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
POST /b1s/v1/Items('i002')
Content-Type: application/json
<Json format item(i002) body>
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2
PATCH /b1s/v1/$1
Content-Type: application/json
<Json format item(i002) update body>
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd--
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

Source: Working with SAP bs1 PDF 

This batch request does the following:
1. Gets Item with code i001
2. It then creates a new item and assigns Content-ID of 1
3. It then updates taht new item (with content id of 1) and assigns Content-ID of 2

What am I want to achieve now with batch requests is the following:
1. Cancel an Incoming Payment
2. Create a Creditnote on the specified invoice
3. Cancel a Sales Order based of the Invoice

This is the endpoint to cancel an Invoice: /IncomingPayments(id)/Cancel (POST request)
The incoming payment's Id I will specify dynamically.

This is the endpoint to create a Creditnote: /CreditNotes (POST request)
and here is an EXAMPLE request body:

{
 "CardCode":"TKI_ELLN",
 "JournalMemo": "Invoice Cancelled",
 "DocumentLines":[
  {
   "ItemCode":"6002",
   "UnitPrice": 55.0,
   "Quantity": 1.0,
   "WarehouseCode":"TKI_ELL",
   "BaseEntry": 26443,
   "BaseType": 13,
   "BaseLine": 0
  }
 ]
}

The following properties should be dynamically specified:
CardCode, ItemCode, UnitPrice, Quantity, WarehouseCode, BaseEntry.

At the time of writing, I realize this won't be possible 🥲. Because I don't know if batch request support for loops.

I continue anyway...

This is the endpoint to cancel an Order: /Orders(id)/Cancel (POST request)
The order Id I will specify dynamically as well.

Shalini_Singhal
Associate
Associate
0 Kudos

Hi kenjon,

In this case, you can create an incident for SAP Business One Support Team to get it investigated.

Kind regards,

Shalini Singhal

SAP Business One Support

kenjon
Explorer
0 Kudos
Incident?
Shalini_Singhal
Associate
Associate
Yes, you can create a ticket for SAP Business One Support Team under the component SBO-SDK-SVL to get it investigated. Mention the link of this discussion while creating the ticket.
kenjon
Explorer
0 Kudos
@Shalini_Singhal. The link to create a ticket is not easy to find at all. Where do I do that?
Shalini_Singhal
Associate
Associate
0 Kudos
@kenjon You can refer SAP Note 722980 for Creating Customer Incidents in SAP Business One.
kenjon
Explorer
0 Kudos
@Shalini_Singhal Can you provide me with the link please where do I find SAP note 722980 ??
Shalini_Singhal
Associate
Associate
0 Kudos
@kenjon Please find the following link https://me.sap.com/notes/722980
kenjon
Explorer
0 Kudos
@Shalini_Singhal The page to the link you sent keeps loading. That page is really buggy as well.