Skip to main content

Manufacturing Module API

The Manufacturing module provides APIs for production planning, bill of materials (BOM) management, work orders, and job cards.

Work Order APIs

make_stock_entry

Create stock entries for work orders to record material consumption or finished goods.
import frappe

# Create material transfer for work order
stock_entry = frappe.call(
    "erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry",
    work_order_id="MFG-WO-2024-00001",
    purpose="Material Transfer for Manufacture",
    qty=10
)
work_order_id
string
required
Work Order ID/name
purpose
string
required
Purpose: “Material Transfer for Manufacture”, “Material Consumption for Manufacture”, or “Manufacture”
qty
float
default:"null"
Quantity for the stock entry (defaults to work order quantity)
stock_entry
Document
Stock Entry document with pre-filled items from work order
  • stock_entry_type: Type of entry
  • purpose: Entry purpose
  • work_order: Reference to work order
  • from_bom: Whether items are from BOM
  • bom_no: BOM reference
  • fg_completed_qty: Finished goods quantity
  • items: List of items with quantities and warehouses

Bill of Materials (BOM) APIs

get_bom_items

Retrieve all items from a BOM including sub-assemblies.
items = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_bom_items",
    bom="BOM-LAPTOP-001",
    company="Company A",
    qty=1,
    fetch_exploded=1
)
bom
string
required
BOM name/ID
company
string
required
Company name
qty
float
default:"1"
Quantity multiplier for calculating required materials
fetch_exploded
int
default:"1"
Whether to explode sub-assemblies (1) or show as-is (0)
items
list
List of BOM items
  • item_code: Item code
  • item_name: Item name
  • qty: Required quantity
  • rate: Item rate
  • amount: Total amount
  • stock_uom: Stock UOM
  • source_warehouse: Default source warehouse
  • description: Item description

get_children

Get child items in BOM tree structure for hierarchical display.
children = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_children",
    parent="BOM-LAPTOP-001",
    is_root=False
)
parent
string
default:"null"
Parent BOM name (null for root level)
is_root
bool
default:"false"
Whether fetching root level items
children
list
List of child items with tree structure information

get_bom_diff

Compare two BOMs and get differences.
diff = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_bom_diff",
    bom1="BOM-LAPTOP-001",
    bom2="BOM-LAPTOP-002"
)
bom1
string
required
First BOM name
bom2
string
required
Second BOM name
diff
dict
Dictionary containing added, removed, and changed items

Job Card APIs

make_stock_entry (Job Card)

Create stock entry from job card for semi-finished or finished goods.
stock_entry = frappe.call(
    "erpnext.manufacturing.doctype.job_card.job_card.make_stock_entry",
    source_name="JOB-CARD-00001"
)
source_name
string
required
Job Card ID
target_doc
Document
default:"null"
Existing stock entry document to update
stock_entry
Document
Stock Entry document mapped from job card

BOM Operations

update_cost

Update BOM costs based on current rates.
bom = frappe.get_doc("BOM", "BOM-LAPTOP-001")
bom.update_cost(
    update_parent=True,
    from_child_bom=False,
    update_hour_rate=True,
    save=True
)
update_parent
bool
default:"true"
Update parent BOM costs
from_child_bom
bool
default:"false"
Whether update is triggered from child BOM
update_hour_rate
bool
default:"false"
Update operation hour rates
save
bool
default:"true"
Save the document after updating
result
null
Updates BOM costs in place

get_bom_material_detail

Get material details for adding items to BOM.
bom = frappe.get_doc("BOM", "BOM-LAPTOP-001")
details = bom.get_bom_material_detail(
    args={
        "item_code": "CPU-INTEL-I7",
        "bom_no": "BOM-LAPTOP-001",
        "qty": 1
    }
)
args
dict
required
Dictionary with item_code, bom_no, and qty
details
dict
Material details including rate, UOM, and description

Blanket Order APIs

make_order

Create sales or purchase order from blanket order.
order = frappe.call(
    "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",
    source_name="BLK-ORD-00001"
)
source_name
string
required
Blanket Order ID
order
Document
Sales Order or Purchase Order document

Usage Examples

Creating Work Order and Material Transfer

import frappe

# Create work order
work_order = frappe.get_doc({
    "doctype": "Work Order",
    "production_item": "LAPTOP-001",
    "bom_no": "BOM-LAPTOP-001",
    "qty": 10,
    "company": "Manufacturing Inc",
    "wip_warehouse": "Work In Progress - MI",
    "fg_warehouse": "Finished Goods - MI",
    "source_warehouse": "Stores - MI"
})
work_order.insert()
work_order.submit()

# Create material transfer
stock_entry = frappe.call(
    "erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry",
    work_order_id=work_order.name,
    purpose="Material Transfer for Manufacture"
)

# Save and submit
se_doc = frappe.get_doc(stock_entry)
se_doc.insert()
se_doc.submit()

print(f"Material transferred: {se_doc.name}")

Getting BOM Details and Costs

import frappe

# Get BOM items
items = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_bom_items",
    bom="BOM-LAPTOP-001",
    company="Manufacturing Inc",
    qty=100,  # For 100 laptops
    fetch_exploded=1  # Get all sub-assembly items
)

total_cost = 0
for item in items:
    print(f"Item: {item['item_code']}, Qty: {item['qty']}, Amount: {item['amount']}")
    total_cost += item['amount']

print(f"Total Material Cost for 100 units: {total_cost}")

Managing BOM Hierarchy

import frappe

# Get root level items
root_items = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_children",
    parent=None,
    is_root=True
)

# Get children of specific BOM
children = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_children",
    parent="BOM-LAPTOP-001",
    is_root=False
)

for child in children:
    print(f"Child Item: {child.get('value')} (Expandable: {child.get('expandable')})")

Comparing BOMs

import frappe

# Compare two BOM versions
diff = frappe.call(
    "erpnext.manufacturing.doctype.bom.bom.get_bom_diff",
    bom1="BOM-LAPTOP-001",
    bom2="BOM-LAPTOP-002"
)

print("Added Items:", diff.get('added', []))
print("Removed Items:", diff.get('removed', []))
print("Changed Items:", diff.get('changed', []))

Recording Production with Stock Entry

import frappe

# Create manufacture entry (finish production)
stock_entry = frappe.call(
    "erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry",
    work_order_id="MFG-WO-2024-00001",
    purpose="Manufacture",
    qty=10  # Finished 10 units
)

se_doc = frappe.get_doc(stock_entry)

# Modify if needed
se_doc.posting_date = "2024-03-15"

# Submit
se_doc.insert()
se_doc.submit()

print(f"Production recorded: {se_doc.name}")
print(f"Finished Goods: {se_doc.fg_completed_qty} units")

Updating BOM Costs

import frappe

# Get BOM and update costs
bom = frappe.get_doc("BOM", "BOM-LAPTOP-001")

# Update based on latest item rates
bom.update_cost(
    update_parent=True,
    from_child_bom=False,
    update_hour_rate=True,
    save=True
)

print(f"Updated BOM Cost: {bom.total_cost}")
print(f"Operating Cost: {bom.operating_cost}")
print(f"Raw Material Cost: {bom.raw_material_cost}")

Advanced Operations

Creating Multi-level BOM

import frappe

# Create sub-assembly BOM
sub_bom = frappe.get_doc({
    "doctype": "BOM",
    "item": "MOTHERBOARD-001",
    "quantity": 1,
    "company": "Manufacturing Inc",
    "items": [
        {
            "item_code": "CPU-INTEL-I7",
            "qty": 1,
            "rate": 300
        },
        {
            "item_code": "RAM-16GB",
            "qty": 2,
            "rate": 50
        }
    ]
})
sub_bom.insert()
sub_bom.submit()

# Create main BOM using sub-assembly
main_bom = frappe.get_doc({
    "doctype": "BOM",
    "item": "LAPTOP-001",
    "quantity": 1,
    "company": "Manufacturing Inc",
    "items": [
        {
            "item_code": "MOTHERBOARD-001",
            "qty": 1,
            "bom_no": sub_bom.name  # Link to sub-assembly BOM
        },
        {
            "item_code": "LCD-SCREEN-15",
            "qty": 1,
            "rate": 150
        }
    ]
})
main_bom.insert()
main_bom.submit()

print(f"Main BOM: {main_bom.name} with sub-assembly: {sub_bom.name}")

Build docs developers (and LLMs) love