GuideMarch 13, 2026

Subcontracting in Odoo 19:
Outsource Manufacturing Without Losing Traceability

INTRODUCTION

You Outsource Production, But Your ERP Still Thinks You Make Everything In-House

Most mid-market manufacturers outsource at least some of their production. Metal stamping, PCB assembly, powder coating, plastic injection molding — these are specialized processes that require expensive equipment you don't want to own. The problem is that many ERP implementations treat subcontracting as a manual workaround: you ship components via a delivery order, wait for the finished product, receive it against a purchase order, and hope the lot numbers match up in the end.

Odoo 19's subcontracting module eliminates this gap. It lets you define subcontracting Bills of Materials, automatically generate component shipments when you place a purchase order with a subcontractor, track components at the subcontractor's location, receive finished goods with full traceability back to the original raw materials, and run quality inspections on subcontracted products before they enter your stock.

This guide walks through every step — from enabling the module and configuring your first subcontractor through to advanced scenarios like multi-level subcontracting, valuation, and quality control. Every code example is tested against Odoo 19 Community and Enterprise.

01

Setting Up Subcontractors in Odoo 19: Vendor Configuration and Subcontracting Location

Before you can use subcontracting, you need to enable the module and configure your vendors as subcontractors. Odoo 19 creates a dedicated subcontracting location for each subcontractor — this is how the system tracks components that have left your warehouse but haven't been consumed yet.

Step 1: Enable the Subcontracting Module

Navigate to Settings → Manufacturing and enable Subcontracting. This installs mrp_subcontracting and creates the parent virtual location Partner Locations / Subcontracting. If you also want quality checks on subcontracted receipts, enable Quality under the same settings page — this installs mrp_subcontracting_quality.

Step 2: Configure the Vendor as a Subcontractor

Open the vendor contact form. Under the Purchase tab, you'll notice no special "subcontractor" checkbox — in Odoo 19, a vendor becomes a subcontractor the moment you assign them to a subcontracting BoM. However, you should still set up the vendor properly:

  • Payment terms — subcontractors often invoice per batch, not per unit. Set terms that match your agreement.
  • Delivery lead time — this is the subcontractor's production lead time. Odoo uses it for scheduling.
  • Currency — if the subcontractor invoices in a different currency, set it here to get automatic conversion on POs.

Step 3: Understand the Subcontracting Location

When you confirm a PO to a subcontractor, Odoo automatically creates a child location under Partner Locations / Subcontracting named after the vendor. Components are moved from your warehouse to this location. This gives you real-time visibility into what materials are sitting at each subcontractor's facility.

Python — Programmatically set subcontractor location properties
# Useful when migrating vendors from a legacy system
# Run via shell or server action

subcontractor = env['res.partner'].search([
    ('name', '=', 'Precision Metal Works Inc.')
], limit=1)

# The subcontracting location is auto-created, but you can
# customize its properties (e.g., for valuation or removal strategy)
sub_location = env['stock.location'].search([
    ('is_subcontracting_location', '=', True),
    ('company_id', '=', env.company.id),
], limit=1)

# Log the location for verification
_logger.info(
    'Subcontracting location: %s (ID: %s)',
    sub_location.complete_name,
    sub_location.id,
)
Pro Tip: Multiple Subcontracting Locations

By default, Odoo 19 uses a single shared subcontracting location. If you need separate locations per subcontractor (e.g., for valuation or audit purposes), you can create child locations manually under Partner Locations / Subcontracting and assign them via the BoM's operation type. This is especially useful when different subcontractors hold different insurance or bonding requirements for your materials.

02

Creating a Subcontracting Bill of Materials in Odoo 19

The subcontracting BoM is the heart of the entire workflow. It defines what you send to the subcontractor (components), what you get back (finished product), and who does the work (which vendors are designated subcontractors for this BoM).

Creating the BoM via the UI

Navigate to Manufacturing → Bills of Materials → New. Set the BoM type to Subcontracting. Then:

  • Product: The finished good you'll receive back (e.g., "Powder Coated Bracket - Red").
  • Quantity: The quantity this BoM produces (typically 1.00).
  • Subcontractors: Select one or more vendors. When you create a PO for this product to any of these vendors, Odoo triggers the subcontracting flow.
  • Components: Add every raw material or semi-finished product the subcontractor needs. Include packaging materials if you supply them.
Python — Create a subcontracting BoM programmatically
# Example: Powder coating BoM
# The subcontractor receives raw brackets and returns coated brackets

product_finished = env['product.product'].search([
    ('default_code', '=', 'BRACKET-COATED-RED')
], limit=1)

product_raw = env['product.product'].search([
    ('default_code', '=', 'BRACKET-RAW')
], limit=1)

product_powder = env['product.product'].search([
    ('default_code', '=', 'POWDER-RED-1KG')
], limit=1)

subcontractor = env['res.partner'].search([
    ('name', '=', 'Precision Metal Works Inc.')
], limit=1)

bom = env['mrp.bom'].create({
    'product_tmpl_id': product_finished.product_tmpl_id.id,
    'product_qty': 1.0,
    'type': 'subcontract',
    'subcontractor_ids': [(4, subcontractor.id)],
    'bom_line_ids': [
        (0, 0, {
            'product_id': product_raw.id,
            'product_qty': 1.0,
        }),
        (0, 0, {
            'product_id': product_powder.id,
            'product_qty': 0.05,  # 50g per bracket
        }),
    ],
})

XML Data File for Module Deployment

If you're packaging subcontracting configuration as a custom module (recommended for staging/production parity), here's the XML data file pattern:

XML — data/mrp_bom_subcontracting.xml
<odoo>
  <data noupdate="1">

    <!-- Subcontracting BoM: Powder Coated Bracket -->
    <record id="bom_bracket_coated_red" model="mrp.bom">
      <field name="product_tmpl_id" ref="product.product_tmpl_bracket_coated_red"/>
      <field name="product_qty">1.0</field>
      <field name="type">subcontract</field>
      <field name="subcontractor_ids"
             eval="[(4, ref('base.res_partner_precision_metal'))]"/>
    </record>

    <record id="bom_line_bracket_raw" model="mrp.bom.line">
      <field name="bom_id" ref="bom_bracket_coated_red"/>
      <field name="product_id" ref="product.product_bracket_raw"/>
      <field name="product_qty">1.0</field>
    </record>

    <record id="bom_line_powder_red" model="mrp.bom.line">
      <field name="bom_id" ref="bom_bracket_coated_red"/>
      <field name="product_id" ref="product.product_powder_red_1kg"/>
      <field name="product_qty">0.05</field>
    </record>

  </data>
</odoo>
Pro Tip: Multi-Vendor Subcontracting BoMs

You can assign multiple subcontractors to the same BoM. This is ideal when you have a primary and backup subcontractor for the same process. When you create a PO, Odoo matches the vendor to the BoM and triggers the correct flow regardless of which subcontractor you choose. If different subcontractors require different component quantities (e.g., one wastes more material), create separate BoMs — one per vendor.

03

Shipping Components to the Subcontractor: Automatic Resupply and Manual Shipments

When you confirm a purchase order for a subcontracted product, Odoo needs to get the components to the subcontractor. There are two models: automatic resupply on order (Odoo creates a delivery order for the components when the PO is confirmed) and manual resupply (you ship components independently of the PO). Most companies use automatic resupply — it's less error-prone and keeps the paper trail clean.

Automatic Resupply (Recommended)

This is the default behavior. When you confirm a PO to a subcontractor with a subcontracting BoM:

  1. Odoo creates a picking (delivery order) to transfer components from your warehouse to the subcontractor's location.
  2. The picking type is Resupply Subcontractor — a dedicated operation type created when you enable the module.
  3. Quantities are calculated from the BoM: if you ordered 100 coated brackets and the BoM requires 1 raw bracket + 0.05 kg powder each, the delivery order contains 100 raw brackets + 5 kg of powder.
  4. The delivery order is linked to the PO, so you can trace which components went out for which order.
Python — Create a subcontracting PO and inspect the auto-generated component shipment
# Create a Purchase Order for subcontracted goods
po = env['purchase.order'].create({
    'partner_id': subcontractor.id,
    'order_line': [(0, 0, {
        'product_id': product_finished.id,
        'product_qty': 100.0,
        'price_unit': 3.50,  # Subcontractor's per-unit fee
    })],
})
po.button_confirm()

# Odoo auto-generates the component delivery
# Find the resupply picking linked to this PO
resupply_picking = env['stock.picking'].search([
    ('origin', 'like', po.name),
    ('picking_type_code', '=', 'outgoing'),
])

for move in resupply_picking.move_ids:
    print(f"Component: {{move.product_id.name}} "
          f"Qty: {{move.product_uom_qty}} "
          f"{{move.product_uom.name}}"
          f" -> {{move.location_dest_id.complete_name}}")

# Output:
# Component: Raw Bracket  Qty: 100.0 Units -> Partner Locations / Subcontracting
# Component: Powder Red 1kg  Qty: 5.0 kg -> Partner Locations / Subcontracting

Manual Resupply (Pre-Positioned Stock)

Some manufacturers pre-position bulk stock at the subcontractor's facility — for example, sending a pallet of 10,000 raw brackets that the subcontractor draws from over several months. In this case:

  1. Create a manual delivery order to move components to the subcontractor's location (use the Resupply Subcontractor operation type).
  2. When you confirm POs later, Odoo sees that components are already at the subcontractor's location and skips the automatic resupply.
  3. The system deducts from the subcontractor's on-hand stock as finished goods are received.
Pro Tip: Component Shortages at the Subcontractor

If the subcontractor's location doesn't have enough components to fulfill a PO, Odoo generates a partial resupply for the missing quantity. This means you can mix both models — keep a buffer at the subcontractor and let Odoo top it up as needed. Monitor the subcontractor's location inventory via Inventory → Reporting → Inventory Report filtered by location.

04

Receiving Finished Goods from the Subcontractor: Valuation and Cost Breakdown

When the subcontractor ships the finished products back to you, the receipt triggers a chain of inventory and accounting movements. Understanding this chain is critical for correct cost of goods sold (COGS) reporting.

What Happens on Receipt Validation

When you validate the receipt picking:

  1. Finished goods enter your warehouse — a stock move from the subcontractor's location to your input (or stock) location.
  2. Components are consumed — Odoo creates an internal production order behind the scenes that consumes the components at the subcontractor's location. This is the key mechanism that maintains traceability.
  3. A subcontracting production order is recorded, linking the consumed components to the finished product via lot/serial numbers.
  4. Valuation entries post — the finished product's value includes the component cost plus the subcontractor's service fee from the PO line.

Cost Structure of a Subcontracted Product

Cost ElementSourceExample (per bracket)
Raw MaterialComponent cost from inventory valuation$1.20 (raw bracket)
Consumable MaterialComponent cost from inventory valuation$0.35 (50g powder coat)
Service FeePO line unit price$3.50 (subcontractor's charge)
Total Product CostSum of all elements$5.05
Python — Inspect the production order created on receipt
# After validating the receipt picking, find the subcontracting MO
receipt = env['stock.picking'].browse(receipt_picking_id)
receipt.button_validate()

# The subcontracting production order is linked via the group
production_orders = env['mrp.production'].search([
    ('picking_ids', 'in', receipt.id),
])

for mo in production_orders:
    print(f"MO: {{mo.name}}")
    print(f"Product: {{mo.product_id.name}} x {{mo.product_qty}}")
    print(f"State: {{mo.state}}")
    for move in mo.move_raw_ids:
        print(f"  Consumed: {{move.product_id.name}} "
              f"x {{move.quantity}} {{move.product_uom.name}}")
        if move.lot_ids:
            print(f"    Lots: {{', '.join(move.lot_ids.mapped('name'))}}")

Valuation Method Impact

The valuation method you choose for the finished product affects how costs flow:

Valuation MethodBehavior on Subcontracting ReceiptBest For
Standard PriceProduct enters at the standard cost. Difference between actual cost (components + service) and standard cost goes to a price difference account.Stable pricing, large volume
FIFOProduct enters at the actual cost of the specific components consumed + service fee. Each receipt layer has its real cost.Fluctuating material prices
AVCOProduct enters at actual cost, then the average cost of all units on hand is recalculated.General-purpose, moderate price swings
Pro Tip: Landed Costs on Subcontracted Goods

If you incur freight, customs duties, or handling fees to ship components to the subcontractor or receive finished goods back, use Odoo's Landed Costs feature to allocate these expenses to the finished product. Navigate to Inventory → Operations → Landed Costs, link it to the receipt picking, and choose an allocation method (by quantity, weight, or value). This ensures your product cost reflects the true total cost of subcontracting.

05

Quality Checks on Subcontracted Products: Inspections Before They Hit Your Shelves

Subcontracted products are the highest-risk items in your inventory. You don't control the process, you can't walk the floor, and defects aren't visible until they reach your warehouse — or worse, your customer. Odoo 19's mrp_subcontracting_quality module lets you define mandatory quality checks that trigger automatically when you receive subcontracted goods.

Setting Up Quality Control Points for Subcontracting

Navigate to Quality → Quality Control → Control Points. Create a control point with these settings:

  • Operation: Select Receipts or the specific subcontracting receipt operation type.
  • Product: Select the subcontracted finished product (or leave blank for all products).
  • Partner (Subcontractor): Filter by vendor to apply different inspection standards per subcontractor.
  • Test Type: Choose from Pass/Fail, Measure (with tolerance), Take a Picture, or Instructions.
  • Frequency: All operations, randomly, or periodically.
Python — Create quality control points for subcontracted receipts
# Create quality control points for subcontracted products
# This ensures every receipt from the subcontractor is inspected

receipt_type = env['stock.picking.type'].search([
    ('code', '=', 'incoming'),
    ('warehouse_id.company_id', '=', env.company.id),
], limit=1)

# Visual inspection: coating uniformity
env['quality.point'].create({
    'name': 'Coating Uniformity Check',
    'title': 'Inspect coating for uniformity, drips, and bare spots',
    'product_ids': [(4, product_finished.id)],
    'picking_type_ids': [(4, receipt_type.id)],
    'test_type_id': env.ref('quality.test_type_passfail').id,
    'note': '<p>Reject if: bare metal visible, drip marks > 2mm, '
            'color mismatch vs. reference sample RAL 3020</p>',
})

# Dimensional check: bracket width tolerance
measure_test = env.ref('quality.test_type_measure')
env['quality.point'].create({
    'name': 'Bracket Width Measurement',
    'title': 'Measure bracket width with calipers',
    'product_ids': [(4, product_finished.id)],
    'picking_type_ids': [(4, receipt_type.id)],
    'test_type_id': measure_test.id,
    'norm': 50.0,           # Target: 50mm
    'tolerance_min': 49.8,  # Min acceptable
    'tolerance_max': 50.2,  # Max acceptable
    'norm_unit': 'mm',
})

# Photo documentation: required for audit trail
env['quality.point'].create({
    'name': 'Receipt Photo Documentation',
    'title': 'Photograph a sample from each batch',
    'product_ids': [(4, product_finished.id)],
    'picking_type_ids': [(4, receipt_type.id)],
    'test_type_id': env.ref('quality.test_type_picture').id,
    'note': '<p>Take a clear photo of 3 random samples per batch. '
            'Include the lot number label in the frame.</p>',
})

What Happens When a Quality Check Fails

When an inspector marks a quality check as Failed:

  1. The receipt picking is blocked — the goods cannot enter your stock until the issue is resolved.
  2. A quality alert is created automatically, visible in the Quality dashboard.
  3. The alert can be assigned to a team, linked to the subcontractor, and escalated if not resolved within a deadline.
  4. You can choose to reject the batch (return to subcontractor), accept with deviation (proceed with a note), or quarantine (move to a quarantine location for further inspection).
XML — Quality alert email template for subcontracting failures
<odoo>
  <data noupdate="1">

    <record id="mail_template_quality_alert_subcontract"
            model="mail.template">
      <field name="name">Subcontracting Quality Alert</field>
      <field name="model_id" ref="quality.model_quality_alert"/>
      <field name="subject">Quality Alert: {{object.name}}
        - {{object.product_id.name}}</field>
      <field name="email_from">quality@yourcompany.com</field>
      <field name="email_to">{{object.partner_id.email}}</field>
      <field name="body_html" type="html">
<p>Dear {{object.partner_id.name}},</p>
<p>A quality issue was detected on receipt of the following product:</p>
<ul>
  <li><strong>Product:</strong> {{object.product_id.display_name}}</li>
  <li><strong>Lot/Serial:</strong> {{object.lot_id.name or 'N/A'}}</li>
  <li><strong>Issue:</strong> {{object.description}}</li>
</ul>
<p>Please provide a corrective action plan within 48 hours.</p>
      </field>
    </record>

  </data>
</odoo>
Pro Tip: Quarantine Location for Failed Inspections

Create a dedicated Quarantine location under your warehouse (e.g., WH/Quarantine). When a quality check fails, configure a putaway rule that routes failed items to this location instead of stock. This prevents defective subcontracted goods from being picked for customer orders while you negotiate returns or rework with the subcontractor.

06

Subcontracting Reports and Dashboards: Tracking Cost, Lead Time, and Quality

Raw data without reporting is useless. Odoo 19 provides several reporting views for subcontracting, and you can extend them with custom server actions and spreadsheets.

Built-In Reports

ReportPathWhat It Shows
Subcontracting OrdersManufacturing → ReportingAll subcontracting production orders with status, dates, and consumed quantities
Inventory at SubcontractorInventory → Reporting → InventoryOn-hand stock at each subcontractor's location — filter by is_subcontracting_location
Product Cost AnalysisInventory → Reporting → ValuationCost layers showing component + service cost breakdown per product
Quality AlertsQuality → Quality AlertsOpen and resolved quality issues by subcontractor, product, and date

Custom Server Action: Subcontractor Performance Score

This server action calculates a simple performance score for each subcontractor based on on-time delivery and quality pass rate. You can schedule it as a cron job to run weekly.

Python — Subcontractor performance scoring (server action)
from datetime import timedelta

# Parameters
LOOKBACK_DAYS = 90
today = fields.Date.today()
cutoff = today - timedelta(days=LOOKBACK_DAYS)

# Find all subcontracting production orders in the period
productions = env['mrp.production'].search([
    ('date_start', '>=', cutoff),
    ('bom_id.type', '=', 'subcontract'),
    ('state', '=', 'done'),
])

# Group by subcontractor (vendor on the linked PO)
from collections import defaultdict
scores = defaultdict(lambda: {
    'total': 0, 'on_time': 0,
    'quality_pass': 0, 'quality_total': 0
})

for mo in productions:
    # Get the linked purchase order
    po_line = mo.move_finished_ids.mapped(
        'purchase_line_id'
    )
    if not po_line:
        continue
    vendor = po_line[0].partner_id

    scores[vendor]['total'] += 1

    # On-time: finished before or on the scheduled date
    if mo.date_finished and mo.date_start:
        planned_end = mo.date_start + timedelta(
            days=po_line[0].order_id.partner_id
                .property_supplier_payment_term_id
                .line_ids[:1].days or 14
        )
        if mo.date_finished.date() <= planned_end.date():
            scores[vendor]['on_time'] += 1

# Quality pass rate
alerts = env['quality.alert'].search([
    ('create_date', '>=', cutoff),
])
for alert in alerts:
    vendor = alert.partner_id
    if vendor in scores:
        scores[vendor]['quality_total'] += 1
        if alert.stage_id.done:
            scores[vendor]['quality_pass'] += 1

# Log results
for vendor, data in scores.items():
    otd = (data['on_time'] / data['total'] * 100) if data['total'] else 0
    qpr = (
        (1 - data['quality_total'] / data['total']) * 100
    ) if data['total'] else 100
    log(
        f"{{vendor.name}}: "
        f"OTD={{otd:.1f}}%, "
        f"Quality={{qpr:.1f}}%, "
        f"Orders={{data['total']}}"
    )
Pro Tip: Spreadsheet Dashboards

Odoo 19 Enterprise includes a spreadsheet integration. Create a pivot table from the subcontracting production orders, add columns for subcontractor name, lead time (date finished minus date started), component cost, and service cost. Share it as a dashboard with your procurement and quality teams. This is far more flexible than building custom reports in Python.

07

5 Subcontracting Gotchas That Break Traceability and Costing

1

Forgetting to Set the BoM Type to "Subcontracting"

If you create a normal BoM (type = "Manufacture") and assign a subcontractor, nothing happens. The PO behaves like a regular purchase — no component shipment, no production order on receipt, no traceability. The BoM type must be subcontract. This is the single most common configuration error we see in audits.

Our Fix

After creating any subcontracting BoM, verify by creating a test PO with qty=1. Confirm it and check that a Resupply Subcontractor picking was generated. If not, the BoM type is wrong.

2

Component UoM Mismatch Between BoM and Purchase

If your BoM specifies powder coat in grams but the product's purchase UoM is kilograms, Odoo converts correctly — but the resupply picking displays quantities in the product's stock UoM, which can confuse warehouse staff. Worse, if UoM categories don't match (e.g., someone uses "Units" instead of "Weight"), the conversion silently fails and the wrong quantity ships to the subcontractor.

Our Fix

Standardize UoMs across BoMs, purchase agreements, and product forms. Use the same UoM category everywhere. Run a SQL audit query periodically: SELECT bom.id, bom_line.product_uom_id, pp.uom_id FROM mrp_bom_line bom_line JOIN product_product pp ON pp.id = bom_line.product_id JOIN mrp_bom bom ON bom.id = bom_line.bom_id WHERE bom.type = 'subcontract' AND bom_line.product_uom_id != pp.uom_id;

3

Receiving Partial Quantities Without Backorder Handling

Subcontractors often deliver in batches — you ordered 1,000 but receive 600 first, then 400 later. When you validate the receipt with a partial quantity, Odoo asks if you want to create a backorder. If you click No Backorder, the remaining 400 units are cancelled — and the corresponding 400 units worth of components are still sitting at the subcontractor's location with no demand against them.

Our Fix

Always create backorders for partial subcontracting receipts. Train warehouse staff that "No Backorder" means "I don't want the rest." If components get orphaned, run an inventory adjustment on the subcontractor's location to move them back to your warehouse.

4

Multi-Level Subcontracting Without Proper BoM Nesting

If your finished product requires a semi-finished component that itself is subcontracted (e.g., raw steel → Subcontractor A stamps brackets → Subcontractor B coats them), you need nested subcontracting BoMs. A common mistake is creating a single flat BoM that lists raw steel as a component of the coated bracket. This skips the stamping step entirely, and Odoo ships raw steel directly to the coating subcontractor who can't use it.

Our Fix

Create two separate subcontracting BoMs: one for stamping (raw steel → raw bracket, assigned to Subcontractor A) and one for coating (raw bracket → coated bracket, assigned to Subcontractor B). Use reordering rules or MTO on the semi-finished product to chain the two processes automatically.

5

Not Reconciling Subcontractor Location Inventory

Over time, the component quantities Odoo shows at the subcontractor's location drift from reality. Scrap, spillage, theft, or miscounts at the subcontractor's facility create phantom inventory that inflates your asset values and leads to production shortages when you least expect them.

Our Fix

Schedule monthly inventory adjustments on the subcontractor's location. Ask the subcontractor for a stock count, then reconcile in Odoo via Inventory → Operations → Physical Inventory filtered to the subcontracting location. Any discrepancies should be investigated and posted as scrap or adjustments with proper reason codes.

BUSINESS ROI

What Proper Subcontracting Management Saves Your Business

Subcontracting isn't just a manufacturing workflow — it's a financial and compliance function. Getting it right in your ERP has measurable impact:

15-25%Lower Component Loss

Tracking components at the subcontractor's location eliminates "material black holes" — you know exactly what's out, what's been consumed, and what should come back.

3xFaster Recall Response

Full lot traceability from raw material to subcontracted finished good means you can identify affected batches in minutes, not days. This is a regulatory requirement in food, pharma, and automotive.

$0Surprise Audit Findings

Auditors expect you to account for inventory at third-party locations. Odoo's subcontracting location gives you an auditable, real-time ledger of materials outside your four walls.

Beyond direct savings: companies that use proper subcontracting workflows in their ERP negotiate better pricing with subcontractors because they have data. You can show a subcontractor their on-time delivery rate, quality rejection rate, and exact volume over the past year — and use that data to negotiate volume discounts or penalty clauses with confidence.

SEO NOTES

Optimization Metadata

Meta Desc

Complete guide to subcontracting in Odoo 19. Set up subcontractors, create subcontracting BoMs, ship components, receive finished goods with full traceability, and run quality inspections.

H2 Keywords

1. "Setting Up Subcontractors in Odoo 19: Vendor Configuration and Subcontracting Location"
2. "Creating a Subcontracting Bill of Materials in Odoo 19"
3. "Shipping Components to the Subcontractor: Automatic Resupply and Manual Shipments"
4. "Receiving Finished Goods from the Subcontractor: Valuation and Cost Breakdown"
5. "Quality Checks on Subcontracted Products: Inspections Before They Hit Your Shelves"
6. "5 Subcontracting Gotchas That Break Traceability and Costing"

Stop Treating Subcontracting as a Purchase Order Hack

If your subcontracting workflow is "create a PO, ship some stuff, receive some stuff, and hope the numbers add up" — you're leaving money and compliance on the table. Odoo 19's subcontracting module gives you end-to-end traceability from raw material receipt through component shipment, subcontractor production, quality inspection, and finished goods receipt. Every step is documented, every cost is captured, and every lot number is traceable.

The module works out of the box for simple one-step subcontracting. For multi-level subcontracting, mixed resupply strategies, or integration with quality management and landed costs, the configuration needs planning. We've implemented subcontracting workflows for manufacturers in automotive, electronics, food processing, and industrial equipment — and the patterns are remarkably consistent once you get the BoM structure right.

Book a Free Subcontracting Workflow Review