How SAP goods movement automation works in PostNow.ai
SAP goods movement automation in PostNow.ai means a MIGO upload from Excel through SAP's standard BAPI_GOODSMVT_CREATE, under your own SAP login. Each row is one line of a material document. Validate checks the sheet offline, Simulate lets SAP check stock and periods without posting, and Run writes each material document number back to its rows.
- GM code once per document, movement type on every line. 01 for a PO receipt, 03 for an issue, 04 for a transfer, 05 for other receipts such as 561 initial stock. Each line carries its reference: PO item, cost center, order, reservation or receiving storage location.
- Use the BAPI, not a MIGO recording. MIGO is built on GUI controls that batch input does not handle well, so the BAPI is the practical route for volume.
This page is about the movements a warehouse or plant team keys in MIGO every day: receipts against purchase orders, issues to cost centers and orders, transfers between storage locations, scrapping, and the initial stock load at go-live. Inventory adjustments split in two. Initial stock is a goods movement with movement type 561, covered on this page. Count differences come from physical inventory: you create a physical inventory document (MI01), enter the count (MI04) and post the differences (MI07), and SAP books the gain or loss itself with movement type 701 or 702.

Which movement type, GM code and reference for each goods movement
In PostNow.ai the GM code is a header field. You map it once per document, usually as a fixed value. The movement type and its reference fields are line fields, mapped to columns. The combinations below are the ones most uploads need. Your configuration decides the final list, so check a new movement type in OMJJ before you build a template around it.
| Movement | Mvt type | GM code | MVT_IND | What the line must carry | Reversal |
|---|---|---|---|---|---|
| Goods receipt for a purchase order | 101 | 01 | B | PO_NUMBER, PO_ITEM, quantity, plant, storage location | 102 |
| Goods receipt for a production order | 101 | 02 | F | ORDERID, quantity, storage location | 102 |
| Goods issue to a cost center | 201 | 03 | blank | COSTCENTER, material, plant, storage location, quantity | 202 |
| Goods issue to an order | 261 | 03 | blank | ORDERID; against a reservation also RESERV_NO and RES_ITEM | 262 |
| Transfer, storage location to storage location | 311 | 04 | blank | Issuing PLANT/STGE_LOC, receiving MOVE_STLOC; batch material also MOVE_BATCH | 312 |
| Scrapping from unrestricted stock | 551 | 03 | blank | Quantity, and usually a cost center; MOVE_REAS if your configuration requires a reason | 552 |
| Initial entry of stock balances | 561 | 05 | blank | Material, plant, storage location, quantity; batch if batch-managed; optional value in AMOUNT_LC | 562 |
| Other goods receipt without a PO | 501 | 05 | blank | Material, plant, storage location, quantity | 502 |
The reversal column follows SAP's rule that the reversal movement type is the original plus one. The movement indicator (MVT_IND) is the field people forget. A PO receipt needs B and a production-order receipt needs F; leave it blank for everything else. In PostNow.ai, map it as a fixed value on the template so nobody has to type it on every row.
One posting, two records: material and accounting document
PostNow.ai writes the material document number back to the row, but a valuated movement also leaves a second, permanent record in finance. The same posting creates both:
| Movement | Material document | Accounting document |
|---|---|---|
101 against a purchase order | Yes | Stock account debited at the PO price, GR/IR clearing credited. The GR/IR line stays open until the invoice for that order clears it. |
501 receipt without a PO | Yes | Stock account debited, offset to a stock-change account set by account determination. No GR/IR line. |
311 between storage locations in one plant | Yes | None. Stock is valuated at plant level, so moving it inside the plant changes no value. |
This is why a wrong receipt is quiet. A 101 against the wrong PO item posts cleanly, and the mistake only surfaces later as a GR/IR balance the invoice does not clear. Compare each receipt run against the PO history in ME23N the same day, not at month-end.
BAPI_GOODSMVT_CREATE: GM codes, header and item fields
PostNow.ai reads the BAPI's interface from your own system, so the Mapping Designer lists exactly the fields your release has, including the ones added after the original release. What you see there is SAP's structure, unchanged:
PSTNG_DATE (posting date; decides the period), DOC_DATE, REF_DOC_NO (often the delivery note), BILL_OF_LADING, GR_GI_SLIP_NO, HEADER_TXT.GM_CODE. It is a separate parameter, not part of the header.MATERIAL, PLANT, STGE_LOC, BATCH, MOVE_TYPE, STCK_TYPE, ENTRY_QNT, ENTRY_UOM, PO_NUMBER/PO_ITEM, ORDERID, COSTCENTER, RESERV_NO/RES_ITEM, MOVE_PLANT/MOVE_STLOC/MOVE_BATCH, MVT_IND, MOVE_REAS, NO_MORE_GR, ITEM_TEXT. The table has no item-number field: lines are numbered in the order you send them.MATDOC_ITM).BAPIRET2).GOODSMVT_HEADRET.The GM code tells the BAPI which classic transaction to behave like. SAP keeps the assignment in table T158G:
| GM code | Behaves like | Used for |
|---|---|---|
01 | MB01 | Goods receipt for a purchase order |
02 | MB31 | Goods receipt for a production order |
03 | MB1A | Goods issue (cost center, order, scrapping and so on) |
04 | MB1B | Transfer posting |
05 | MB1C | Other goods receipts, including initial stock entry |
06 | MB11 | Reversal of goods movements |
07 | MB04 | Subsequent adjustment for a subcontract order |
Two things about that table catch people out. First, there is no GM code for MIGO; SAP's own knowledge base article 2304535 says so. Second, S/4HANA no longer lets you run MB01, MB1A, MB1B, MB1C or MB11 as transactions. The BAPI still accepts the codes, and SAP's S/4HANA simplification guidance points custom code that called those transactions to this BAPI. The codes are internal switches, not screens you need.
The BAPI does not commit on its own. PostNow.ai calls BAPI_TRANSACTION_COMMIT with wait only when SAP returns no error or abort message for the document, and rolls back otherwise. A material document is all or nothing: if line 3 of 5 fails, none of the five lines post, and the next document in the sheet is processed separately.
MIGO upload from Excel: BAPI, recording or keying
PostNow.ai offers two ways to post: a BAPI, or a transaction you record once and replay. For goods movements the choice is easy, and the table shows why.
| Route | Works for | Where it breaks | Verdict |
|---|---|---|---|
PostNow.ai with BAPI_GOODSMVT_CREATE | Receipts, issues, transfers, scrapping and initial stock, on ECC and S/4HANA; many lines per document | Movement types your configuration does not allow for the GM code (M7 096); serial-heavy materials need care | The default for any volume |
| PostNow.ai with a recording | On ECC, the classic MB1A/MB1B/MB1C screens can be recorded like any other transaction | MIGO's controls do not replay through batch input; the MB transactions are gone in S/4HANA | Only if a movement has no BAPI route in your system, which is rare |
| Keying in MIGO | A few lines, exceptions, anything that needs a person to look at the stock first | Hundreds of lines a day; no row-by-row trail back to the source file | Keep for exceptions |
The SAP mass upload guide compares BAPI and recording for other objects, the SAP MM mass upload guide sets goods movements in load order with materials, purchase orders and invoices, and the BDC recording guide covers recordings in general.
SAP goods movement automation with PostNow.ai, step by step
PostNow.ai is an Excel add-in. Everything below happens in the workbook, against your SAP system, under your own SAP user. BAPI mode installs nothing in SAP; it needs RFC access and the same goods movement authorizations you would need in MIGO. If you have never uploaded anything from Excel before, the first-upload walkthrough covers the basics in more detail.
Pick the BAPI
Search the function library by name, or type "MIGO" or "post goods issue" into Find with AI; both lead to BAPI_GOODSMVT_CREATE. PostNow.ai loads the header, code and item structures from your system.

Map columns, fixed values and documents
Map the line fields to columns: material, plant, storage location, batch, quantity, unit and the reference fields from the table above. Give GM_CODE and MVT_IND fixed values. Posting date can come from a column, or from the dynamic value SAP_DATE if every movement posts today.
Then tell PostNow.ai where one material document ends and the next begins. You have two options. You can use an H/D marker column, where an H row carries the header and the D rows below it are lines. Or you can use flat rows: every row is a line, and a new document starts when a column such as "GR Ref" or "Delivery note" changes value. Flat rows suit scanner exports, which rarely have header rows.


Set field rules
Use a per-field date format if the posting date arrives as DD.MM.YYYY. Set leading zeros, with a target length, on numeric keys such as order numbers and reservation numbers. Leading zeros apply to numeric values only, so alphanumeric materials like TG-1001 pass through untouched. Mark the fields operators must fill, and give storage location or reason for movement a restricted list where only a few values are valid.
Validate, then Simulate
Validate checks the file offline: required fields, types, lengths, dates, decimals, allowed values. With Pre-Validation switched on, it also looks up single values in SAP's check tables, so a plant or material that does not exist is caught before posting. Stock, the PO item's open quantity and the open period are SAP's checks, and Simulate covers those. It calls the BAPI for each document and then issues BAPI_TRANSACTION_ROLLBACK, so SAP runs its real checks and returns its real messages without posting anything.
Post a pilot, then the rest
Use Run Scope to post the first document or two, check them in SAP, then run the remainder. Documents post in sheet order, top to bottom. That matters when a transfer in row 40 depends on a receipt in row 10. Each row gets a Run Log entry. For this BAPI the default success message reads "Material Document $DOC_NO posted successfully", and the number can also be written to a column of its own.
Fix and retry the failures
Retry Failed re-posts only rows whose Run Log starts with ERROR, and it rebuilds the whole document they belong to. It scans from the current Start Row downwards, so after a pilot set Start Row back to the first data row. If SAP's answer for a document was lost after it was sent, its rows are marked UNKNOWN instead of ERROR, and Retry Failed leaves them alone: look the document up in MB51 before you post it again. AI Review can explain a failed row in plain English; by default it sends only SAP's messages and the field layout, not your cell values.
Once the template works, publish it. A published workbook is run-only: operators paste the day's movements, validate and run, but cannot change the mapping. If your portal has an approval policy on the template, Run waits until someone other than the submitter approves that exact data. How templates, roles and approvals fit together is on the Excel to SAP automation page.
Worked example: a shift's goods issues
A production supervisor collects the shift's material withdrawals in a sheet. PostNow.ai posts them through a flat-row template: GM code 03 fixed, posting date from the sheet, a new document whenever the "Slip" column changes.
| Row | Slip | Posting date | Mvt | Material | Plant | SLoc | Qty | Unit | Order | Reservation / item | Cost center |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2 | GI-1020-01 | 20.10.2026 | 261 | TG-1001 | 1010 | 101A | 40 | EA | 1000452 | 0000123456 / 0001 | |
| 3 | GI-1020-01 | 20.10.2026 | 261 | TG-1002 | 1010 | 101A | 12 | EA | 1000452 | 0000123456 / 0002 | |
| 4 | GI-1020-02 | 20.10.2026 | 201 | TG-1105 | 1010 | 101A | 5 | L | 101500 | ||
| 5 | GI-1020-03 | 20.10.2026 | 551 | TG-1001 | 1010 | 101A | 2 | EA | 101500 |
- Validate passes. The date format rule turns 20.10.2026 into 20261020, and order 1000452 is padded to twelve digits.
- Simulate returns two clean documents and one failure. Slip GI-1020-01 fails with M7 021, a deficit of unrestricted stock for TG-1002 in 1010/101A. The shift withdrew from a bin that had not been received into SAP yet. Because the document is all or nothing, row 2 shows the error too.
- The supervisor posts the open receipt for TG-1002 first, then runs the sheet. Rows 4 and 5 get material documents of their own (for example 4900012345 and 4900012346). Rows 2 and 3 share one document, because they are one slip.
- The withdrawal is posted with reference to the reservation items, so nobody keyed the reservation in MIGO; the BAPI took it from
RESERV_NO/RES_ITEM.
Batches, serial numbers and stock types
PostNow.ai treats batch, stock type and serial data as ordinary BAPI fields. The rules come from SAP:
- Batch-managed materials need
BATCHon every line that moves them. Without it SAP answers M7 018 "Enter batch". On a 311 transfer, put the receiving batch inMOVE_BATCH; SAP does not assume it is the same as the issuing batch. - Stock type (
STCK_TYPE) decides where a receipt lands: blank for unrestricted use, or quality inspection or blocked stock. A receipt into quality inspection is invisible to an issue that expects unrestricted stock, which is a common cause of M7 021 later in the same file. - Serial numbers go in a second table, linked to a line by its position. One serial per line maps cleanly. Several serials on one line do not fit a one-row-per-line sheet. Prove the serial-number layout in Simulate on a test client before you rely on it.
PO receipts: partial deliveries, tolerances and delivery completed
PostNow.ai sends the quantity on the row, and SAP compares it with the open quantity and tolerances on the PO item. A delivery file rarely matches the order exactly, so it helps to know which way SAP leans:
- Under-delivery is accepted by default as a partial delivery, and the item stays open for the rest. If the PO item has an under-delivery tolerance and the receipt falls below it, SAP issues a warning. A warning does not stop the document posting.
- Over-delivery is rejected with an error by default. An over-delivery tolerance on the PO item allows receipts up to the order quantity plus that percentage; beyond it you get M7 022 from the error table below. Tolerances usually default from the material master or the purchasing info record. Raising one just to get a run through switches off the check that catches suppliers over-shipping.
- Delivery completed is
NO_MORE_GRin the BAPI (ELIKZon the PO item). Customizing can set it automatically when the received quantity is within tolerance. For a final delivery that falls short of tolerance, mapNO_MORE_GRto a column and putXon that row. The open PO quantity then drops to zero, so planning stops expecting the rest; later receipts are still possible. If a return or reversal takes the received quantity back below tolerance, SAP resets the flag itself.
Posting period errors: M7 053 and the open MM period
PostNow.ai sends the posting date you map, and SAP decides whether that period is open. Materials Management allows postings in the current period and the previous one. When the posting date falls outside them, every document fails with M7 053 "Posting only possible in periods &1 and &2 in company code &3". If you Simulate first, this shows on the first document and a wrong date never reaches a real run.
Look at the two periods in the message. If they are behind the calendar, the MM period has not been moved forward yet. MMRV shows the current setting, and closing the period with MMPV is a job for whoever owns period-end, not for the upload. If the periods are right and the date is wrong, the usual cause is a date read as month-first; fix it with the field's date format rather than in the cells. Finance can close the FI period separately in OB52, so a date can pass the MM check and still fail.
BAPI_GOODSMVT_CREATE error messages and fixes
PostNow.ai writes SAP's message to the row exactly as SAP returns it. These are the ones a goods movement upload meets most:
| Message | What it means | Fix |
|---|---|---|
| M7 053 Posting only possible in periods &1 and &2 | Posting date outside the open MM periods | Correct the date, or ask period-end owners to move the period (MMRV/MMPV) |
| M7 021 Deficit of … | Not enough stock of that type, location or batch on the posting date | Check MMBE; post the receipt first or correct the storage location or batch |
| M7 022 … exceeded by … | Quantity exceeds what the reference allows, for example the PO quantity plus tolerance | Check open quantity in the PO history; split or reduce the line |
| M7 018 Enter … | A field SAP needs for this movement is empty; most often the batch | Add the column, or a default if it is the same for every row |
| M7 096 Goods movement not possible with mvmt type … | The movement type is not allowed for the transaction behind the GM code, for example 261 sent with code 05 | Use the GM code from the table above; if it is right, check the movement type's allowed transactions in OMJJ |
| M7 127 Material … flagged for deletion | The material is flagged for deletion at that level | Remove the line, or have master data lift the flag |
| M7 001 Check table …: entry … does not exist | A key value is not in its check table; the message names the table | Turn on Pre-Validation for that field so the next file is caught offline |
| M7 162 Order … cannot be processed | The order's status does not allow the movement | Check the order status with production or controlling before re-running |
Reversing a goods movement: 102, 262 and BAPI_GOODSMVT_CANCEL
Documents that already posted stay in SAP when you press Stop, and a reversal is an SAP posting like any other. You can do it by hand or from a second template.
- By hand: cancel the material document in MIGO (on ECC, MBST also exists; S/4HANA removed it in favour of MIGO).
- In volume: build a PostNow.ai template on
BAPI_GOODSMVT_CANCEL. It takes the material document, the year and an optional posting date, plus a table if you only reverse some lines. SAP derives the reversal movement type (102 for 101, 262 for 261) from the original. Run it on a test client first and check that the Run Log shows the reversal document's number. If it does not, build a Custom Message from SAP's message variables. - Posting the reversal type yourself (a 262 return to stock, a 102 against the PO) also works through
BAPI_GOODSMVT_CREATE. It is a new movement with its own references, not a link to the original document. Use it when the return is a business event, and use the cancel BAPI when the original was simply wrong.
Subcontracting: components out, finished goods in
PostNow.ai posts a subcontracting receipt as a 101 against the subcontract PO item. What makes it different is what SAP does inside that one document:
- Components go first. They are provided to the vendor with movement type
541, a transfer posting from unrestricted-use stock to the stock of material provided to vendor. Check in OMJJ which transaction, and so which GM code, your configuration allows for 541 before you build a template for it. - The receipt consumes them. When the finished item is received, SAP posts the consumption of the components from the vendor's stock in the same material document, as
543lines copied from the PO's component list. Your file states the finished quantity and SAP works out the components, so a wrong finished quantity consumes the wrong amount of every component. - Only unrestricted provided stock counts. The components consumed at receipt must be in the vendor's unrestricted-use stock. If they are not there yet, post the 541 first.
- Different actual usage can be corrected at goods receipt. If the vendor reports it later, post a subsequent adjustment, which is GM code
07in the table above.
Keep subcontracting receipts in their own template and file rather than mixed in with standard receipts. Run Simulate on a test client first and check that the 543 lines come back the way you expect.
Checking the result: MB51, MIGO display and MATDOC
PostNow.ai gives you the document number per row; SAP gives you the proof. Use these:
- MB51, the material document list. Select by posting date, movement type, plant and your user to see everything the run posted, line by line.
- MIGO, Display for one document. On ECC, MB03 shows it too; S/4HANA removed MB03.
- MMBE for the stock that moved, and the PO history in ME23N for receipts against purchase orders.
- Tables: on ECC the documents are in
MKPF(header) andMSEG(items). In S/4HANA they are stored inMATDOC;MKPFandMSEGstill answer reads, as compatibility views, so existing queries keep working.
If you have the Reports permission, the Report Library's MM-07 Goods Movements 360 pulls material documents into Excel by document, posting date or material. It shows movement-type text, quantity and local-currency value, so you can reconcile a run against its source file in the same workbook. Operators run it; designers author new queries. Its columns are shown on the goods movements report in Excel page: the same material documents, with movement-type text and material data, in one sheet.
Checklist before a goods movement upload
PostNow.ai enforces some of these, and SAP enforces the rest at posting time. Checking them first saves a re-run:
- GM code, movement type,
MVT_INDand reference fields match the first table on this page, document by document. - Posting dates fall in the open MM period, and FI has not closed it either.
- Batch is filled for batch-managed materials, and receiving batch on transfers.
- Rows are in the order the stock really moved: receipts before the issues that consume them.
- Validate is clean and Simulate has run on at least the first documents.
- Movements already posted from another file are removed from this one, and any UNKNOWN row has been checked in MB51.
- For 561: values agreed with finance, and the user is authorized for it.
What to plan for in a goods movement upload
PostNow.ai uses SAP's own goods movement logic, so SAP's checks come with it. Plan for these points:
- Check MB51 before re-posting a new file or an UNKNOWN row. A second Run on the same sheet offers to skip posted documents from its Run Log; for a new file with the same movements, or a row marked UNKNOWN, confirm in MB51 what already posted.
- Prove stock and open quantities with Simulate. Stock levels and PO open quantities are SAP's checks: Simulate and Run see them, and stock can change between the two.
- Warehouse and EWM follow-on steps (transfer requirements, putaway tasks) are created by SAP according to your configuration. Test one document in a warehouse-managed storage location before running a full file.
Free goods movement Excel templates
PostNow.ai publishes free upload templates, each mapped to BAPI_GOODSMVT_CREATE with H/D rows, sample lines and a field guide. They are a quick way to see the layout before you build your own:
- MIGO goods receipt against purchase order (GM code 01, movement type 101). Add
MVT_IND=Bas a fixed value when you map it. - Goods issue (GM code 03; 201, 261, 551)
- Stock transfer posting (GM code 04; 311)
- Goods receipt without purchase order (GM code 05; 561, 501)
SAP goods movement upload: frequently asked questions
How do I upload goods movements from Excel into SAP?
BAPI_GOODSMVT_CREATE. Map the line columns (material, plant, storage location, quantity, movement type and its reference), set the GM code and movement indicator as fixed values, and tell it where each material document starts, either with H/D rows or with a document-reference column. Validate checks the file offline, and Simulate calls the BAPI and rolls back so SAP's own stock and period checks run. Run then posts each document and writes the material document number back to its rows.Which BAPI is used for MIGO goods movements?
BAPI_GOODSMVT_CREATE. It takes a header (GOODSMVT_HEADER), a GM code (GOODSMVT_CODE) and one entry per line in GOODSMVT_ITEM, and returns MATERIALDOCUMENT and MATDOCUMENTYEAR. It does not commit by itself, so the caller has to commit after a clean return. To reverse a document, use BAPI_GOODSMVT_CANCEL. In PostNow.ai, typing "MIGO" into Find with AI leads to BAPI_GOODSMVT_CREATE.What are the GOODSMVT_CODE values in BAPI_GOODSMVT_CREATE?
Can MIGO be recorded with BDC or SHDB?
BAPI_GOODSMVT_CREATE instead, which PostNow.ai calls in BAPI mode; it covers receipts, issues, transfers, scrapping and initial stock entry on both ECC and S/4HANA.How do I post initial stock with movement type 561 from Excel?
AMOUNT_LC. Agree the values with finance before you post, because 561 posts stock value with no purchase order behind it. Many systems restrict it to the migration team, so check the user's authorization first.How are inventory adjustments posted in SAP: 561, 701 and 702?
BAPI_GOODSMVT_CREATE. Count differences are not keyed as goods movements: you create a physical inventory document in MI01, enter the counted quantities in MI04 and post the differences in MI07. SAP then generates movement type 701 for a surplus and 702 for a shortage in unrestricted stock.How do I reverse a material document posted from Excel?
BAPI_GOODSMVT_CANCEL, which takes the material document, its year and an optional posting date. SAP posts the reversal movement type, which is the original plus one: 102 for 101, 262 for 261. Posting a 102 or 262 yourself through BAPI_GOODSMVT_CREATE is a new movement, which suits a real return rather than a correction.Why does BAPI_GOODSMVT_CREATE return "Posting only possible in periods"?
Where do I see material documents in S/4HANA?
MATDOC, and MKPF and MSEG remain as compatibility views for reads. In PostNow.ai, the Report Library's MM-07 Goods Movements 360 pulls material documents into Excel by document, posting date or material.