Lesson 4 of 5
Building a custom migration object
11 min
A custom, or user-defined, migration object is one you design end to end: its source structures, its target API and every mapping in between. In the modeler you create it within a project, choose the migration approach, and choose a function module as its target. That function module, often a BAPI or a thin wrapper around one, is what actually creates the data. The modeler and the cockpit provide the template, staging tables, mapping tasks, simulation, message log and run control around it.
The function module contract
The cockpit calls your function module once per instance of the object (for example once per core return agreement with its items) and expects it to behave like a well-mannered BAPI. SAP's guidance and community experience agree on a few rules:
- No COMMIT WORK inside. The cockpit controls commits. A function module that commits on its own breaks simulation and makes errors hard to roll back.
- Return messages in BAPIRET2. Errors, warnings and successes come back in a table of the standard BAPI return structure, so they appear in the cockpit's message log per record.
- Support a test run. A test-run parameter lets the cockpit simulate: the module runs all checks and then rolls back instead of saving. Without it, simulation cannot tell you anything useful.
- Run SAP's checks. Use released BAPIs or application function modules that validate data, rather than writing directly to tables. Direct table inserts skip checks and can create inconsistent data.
- Process one instance at a time and be safe to call many times in parallel processing.
| Function module behavior | Good | Bad |
|---|---|---|
| Saving | Leaves the commit to the caller | Calls COMMIT WORK itself |
| Messages | BAPIRET2 table with clear text per problem | Raises an exception or writes to a log nobody reads |
| Simulation | Test-run flag: checks, then rollback | No test mode; simulation posts data or skips checks |
| Validation | Released API with application checks | INSERT into database tables |
Designing the object
- SpecifyMapping specification for the new object, approved by the owner
- Build the function moduleWrapper around a released API; BAPIRET2 messages; test-run flag; no commit
- Create the objectIn LTMOM: user-defined object, staging table approach, function module as target
- Source structuresHeader and item levels with linking keys; mandatory fields marked
- MapStructure and field mapping; translation objects for code fields
- GenerateRuntime generated; staging tables created; template downloaded
Placing it in the load sequence
A custom object depends on other objects just like a predefined one. The Alternadores core return agreements reference business partners and products, so they load after both, and before any open sales orders that might refer to an agreement. Add the custom object to the object list, the load sequence and the cutover plan with its dependencies, its expected volume and its owner. Luis needs its run time from Mock 2 to place it on the critical path.
- Load step 2Business partnersFlotillas Monterrey and other Alternadores customers in company code 1910
- Load step 3ProductsAlternadores products for plant 1910, with the core part flag
- Load step 5Core return agreements (custom)Headers per customer, items per product; deposit amounts in MXN
- Load step 6Open sales ordersOrders that may reference an agreement
What would you do?
In the first Wave 2 simulation of the core return object, every record reports success. The next morning, the custom table in the quality system CMQ already contains all the agreements, although nobody ran the migration step. What is the most likely cause?
- A custom object uses a function module, often a BAPI or wrapper, as its target.
- The module must not commit, must return BAPIRET2 messages, must support a test run and must run application checks.
- Specify, build the module, create the object, define structures, map, generate.
- Add the custom object to the object list, load sequence and cutover plan with its dependencies.
Check your understanding · not graded
Lesson check
1. What does a user-defined migration object use as its target?
2. Why must the function module not call COMMIT WORK?
3. Which structure should return messages use?
4. The Alternadores core return agreements reference business partners and products. Where do they load?