BOM Builder - Nioron07/Easy-Acumatica GitHub Wiki

This guide covers the BOMBuilder, which is your primary tool for creating the JSON payload needed to create Bill of Material (BOM) records with the BomsService.

1. Importing the BOMBuilder

To get started, import the BOMBuilder from the models directory.

from easy_acumatica.models.bom_builder import BOMBuilder

2. Understanding the Builder's Purpose

When you send data to Acumatica's contract-based API, each field must be wrapped in a specific JSON structure, such as {"value": ...}. The BOMBuilder handles this formatting for you automatically, allowing you to construct a valid payload for a new Bill of Material using a fluent, chainable interface. It is designed to build BOMs with one or more operations, where each operation can contain multiple material lines.

3. BOMBuilder Methods

The following table summarizes the primary methods available in the BOMBuilder.

Method Description Key Parameters
.set() Sets any top-level field on the BOM. field (str), value (Any)
.bom_id() (Required) Sets the BOMID. value (str)
.inventory_id() (Required) Sets the InventoryID of the finished good. value (str)
.revision() Sets the Revision of the BOM. value (str)
.description() Sets the Description. value (str)
.add_operation() Adds an operation, which can contain materials and other settings. operation_nbr, work_center, materials, **kwargs
.to_body() Constructs the final JSON payload for the request. (None)

4. Building a BOM Payload

You can set top-level fields using the generic .set() method or one of the convenient shortcut methods. The core of building a BOM is adding operations and their associated materials.

Adding Operations with Materials

The .add_operation() method is used to define a step in the manufacturing process. You must provide a list of dictionaries for the materials parameter, where each dictionary represents a component required for that operation.

Example: Creating a BOM with multiple operations

# 1. Define materials for the first operation
op_10_materials = [
    {"InventoryID": "RAW-PART-A", "QtyRequired": 2.0, "UOM": "EA"},
    {"InventoryID": "RAW-PART-B", "QtyRequired": 5.0, "UOM": "EA"}
]

# 2. Create a builder instance and add operations
bom_payload = (
    BOMBuilder()
    .bom_id("FINISHED-ASSEMBLY")
    .inventory_id("FINISHED-ASSEMBLY")
    .revision("A")
    .description("Multi-step Assembly BOM")
    .add_operation(
        operation_nbr="10",
        work_center="CUTTING",
        materials=op_10_materials
    )
    .add_operation(
        operation_nbr="20",
        work_center="WELDING",
        materials=[{"InventoryID": "SUB-ASSEMBLY-X", "QtyRequired": 1.0}]
    )
)

5. Generating the Final JSON Body

Once you have set all the required fields, call the .to_body() method to generate the final dictionary.

# 1. Build the BOM
bom_payload = (
    BOMBuilder()
    .bom_id("SIMPLE-BOM")
    .inventory_id("SIMPLE-BOM")
    .revision("A")
    .add_operation(
        operation_nbr="10",
        work_center="ASSEMBLY",
        materials=[{"InventoryID": "COMPONENT-Z", "QtyRequired": 1.0}]
    )
)

# 2. Get the final dictionary
json_body = bom_payload.to_body()

# The json_body will look like this:
# {
#     "BOMID": {"value": "SIMPLE-BOM"},
#     "InventoryID": {"value": "SIMPLE-BOM"},
#     "Revision": {"value": "A"},
#     "Operations": [
#         {
#             "OperationNbr": {"value": "10"},
#             "WorkCenter": {"value": "ASSEMBLY"},
#             "Material": [
#                 {
#                     "InventoryID": {"value": "COMPONENT-Z"},
#                     "QtyRequired": {"value": 1.0}
#                 }
#             ]
#         }
#     ]
# }

6. Complete Example with BomsService

Here is a complete example of how to use the BOMBuilder to create a new Bill of Material.

from easy_acumatica.models.bom_builder import BOMBuilder

# 1. Build the BOM payload
bom_to_create = (
    BOMBuilder()
    .bom_id("FINAL-PRODUCT")
    .inventory_id("FINAL-PRODUCT")
    .revision("C")
    .description("BOM for the final product assembly")
    .add_operation(
        operation_nbr="10",
        work_center="PREP",
        materials=[
            {"InventoryID": "PART-X", "QtyRequired": 4.0},
            {"InventoryID": "PART-Y", "QtyRequired": 8.0},
        ]
    )
)

# 2. Use the payload with the BomsService to create the record
try:
    new_bom = client.boms.create_bom(
        "24.200.001",
        builder=bom_to_create
    )
    print(f"Successfully created BOM: {new_bom['BOMID']['value']} Rev: {new_bom['Revision']['value']}")
except Exception as e:
    print(f"Failed to create BOM: {e}")