Skip to main content
BlogERP

Landed Cost in ERP: True Import Cost for Indonesian Trade

The invoice price on a purchase order is never the real cost of imported goods. Here is how to build a landed cost engine that apportions freight, insurance, bea masuk import duty, and PPN across purchase lines for accurate inventory valuation.

Matthews Wong

Software Engineer

July 202610 min read
Landed Cost in ERP: True Import Cost for Indonesian Trade

Photo by dok1 on flickr

Key Takeaway

Landed cost in ERP means capturing freight, insurance, bea masuk import duty, and PPN impor as first-class shipment data, then apportioning them across every purchase line by FOB value, weight, or volume so each imported item carries its true unit cost, while PPN impor stays out of inventory as a recoverable input tax credit.

Every importer eventually learns the hard way that the price on a supplier invoice is not what the goods actually cost once they land on a warehouse shelf. Freight, marine insurance, bea masuk import duty, and PPN impor stack on top of the purchase price, and none of it shows up automatically on a purchase order. If your ERP only records the invoice amount, your inventory valuation, cost of goods sold, and gross margin are all quietly wrong from the moment goods are received.

This post walks through building a landed cost calculation into a custom ERP for Indonesian trade: how to move from FOB price to a dutiable CIF value, how bea masuk and PPN impor are layered on top, how to apportion shipment-level charges across many purchase lines fairly, and why one of those charges should never touch your inventory value at all. The examples use a worked shipment in rupiah so every formula has a concrete number behind it.

Why Landed Cost Matters for Indonesian Importers

A purchase order captures a supplier's selling price, but an import shipment carries several more cost layers before the goods are usable inventory. If those layers are expensed separately instead of being capitalized into the item cost, unit margins on imported SKUs look better than they actually are, and management ends up pricing products against a cost that was never real. The four layers that most commonly need to be captured are:

  • Freight to the Indonesian port of entry, whether by sea or air
  • Marine or cargo insurance covering the shipment in transit
  • Bea masuk, the import duty assessed on the customs value at the rate set for the item's HS code
  • PPN impor, PPh Article 22 withholding, and incidental fees such as terminal handling and customs brokerage

Capture landed cost at the goods receipt step, not when the freight forwarder's invoice finally arrives weeks later. Post a provisional estimate against the shipment as soon as the bill of lading and customs declaration are available, then true it up once the actual bills land. Waiting for every invoice before touching inventory value means your margin reports are wrong for the entire lag period.

From FOB Price to Dutiable CIF Value

Bea masuk and PPN impor are not calculated on the supplier's invoice price. Indonesian customs assesses both against the customs value, which in practice is almost always the CIF value: the free-on-board price of the goods plus the freight and insurance needed to get them to the Indonesian port. Getting this base value right is the first step, because every downstream tax and duty figure is a percentage of it.

Building the CIF Value

Under the CIF Incoterm, the seller pays for carriage and insurance up to the named port of destination, while the buyer takes on unloading costs, import duty, and tax from that point forward. Even when a shipment is bought on a different Incoterm such as FOB, an ERP still needs to reconstruct a CIF-equivalent value for customs purposes by adding the actual freight and insurance the importer paid to get the goods to port. That reconstructed CIF value, not the invoice total, is the number every subsequent calculation is built on.

ComponentFormulaAmount (IDR)
CIF valueFOB price + freight + insuranceRp 555,000,000
Bea masuk (import duty)CIF value times duty rate (7.5% in this example)Rp 41,625,000
Import valueCIF value + bea masuk + any other customs or excise levies (none here)Rp 596,625,000
PPN impor (recoverable)12% of 11/12 of the import value (non-luxury goods, PMK 131/2024)Rp 65,628,750
Landed cost for inventoryCIF value + bea masuk, excluding recoverable PPNRp 596,625,000

Bea Masuk and PPN Impor on the Import Declaration

Bea masuk rates are set per HS code in the official tariff book maintained by the Directorate General of Customs and Excise, and they range widely depending on the goods and whether a preferential trade agreement applies. PPN impor is then charged on the import value, which is the CIF value plus the duty just calculated and any other customs or excise levies. Under PMK 131/2024 the rate is 12%: for non-luxury goods it applies to 11/12 of the import value, an effective 11%, and for goods subject to PPnBM it applies to the full import value. Separately, PPh Article 22 withholding tax is collected at import, at a lower rate for holders of an importer identification number and a higher rate for those without one. None of this happens on the purchase order; it happens on the customs declaration, so an ERP needs a place to record it against the shipment rather than the individual item.

Bea masuk rates depend entirely on correct HS code classification, and a wrong code can mean a wrong duty rate, a wrong landed cost, and a compliance problem with customs. Do not hard-code a duty rate into item master data and assume it will stay correct. Validate every HS code and rate against the current official tariff schedule before it drives a landed cost calculation, and flag shipments where the classification is uncertain for manual review rather than letting the system silently apply a default rate.

Apportioning Shipment-Level Costs Across Purchase Lines

A single import shipment almost always carries several SKUs on one bill of lading, but freight, insurance, and duty are assessed against the whole shipment, not against each line item individually. The ERP has to take those shipment-level totals and split them fairly across every purchase line so each item ends up with its own true unit cost. That apportionment logic is the actual engineering problem behind landed cost, and it typically works in four steps.

  1. Capture every shipment-level charge, meaning freight, insurance, bea masuk, and any other fees, on the import shipment header before it ever touches a line item.
  2. Choose an apportionment key for the shipment, such as each line's share of total FOB value, its share of total weight, or its share of total volume, depending on which key best reflects how that cost was actually incurred.
  3. Multiply each line's apportionment share by every shipment-level charge, then add the result to the line's own FOB cost to get a landed unit cost per item.
  4. Post the landed cost adjustment into the inventory valuation for that item, or into a goods-received-not-invoiced holding account if the final bills have not arrived yet, rather than expensing it directly.
-- purchase_lines: goods received on a single import shipment
CREATE TABLE purchase_lines (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  shipment_id   UUID NOT NULL REFERENCES import_shipments(id),
  item_id       UUID NOT NULL REFERENCES items(id),
  quantity      NUMERIC(15,4) NOT NULL,
  unit_cost_fob NUMERIC(15,2) NOT NULL,     -- FOB price per unit, origin currency
  weight_kg     NUMERIC(15,4) NOT NULL,
  line_fob_idr  NUMERIC(15,2) NOT NULL       -- quantity * unit_cost_fob, converted to IDR
);

-- import_shipments: freight, insurance, duty and PPN captured once per shipment
CREATE TABLE import_shipments (
  id               UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  freight_idr      NUMERIC(15,2) NOT NULL,
  insurance_idr    NUMERIC(15,2) NOT NULL,
  duty_rate        NUMERIC(6,4) NOT NULL,   -- e.g. 0.075 for 7.5% bea masuk
  ppn_rate         NUMERIC(6,4) NOT NULL DEFAULT 0.11,  -- 12% x 11/12 (PMK 131/2024); 0.12 for PPnBM goods
  other_fees_idr   NUMERIC(15,2) NOT NULL DEFAULT 0
);

// NestJS: apportion shipment-level costs across lines by FOB value share
async function apportionLandedCost(shipmentId: string): Promise<LandedCostLine[]> {
  const shipment = await this.shipmentRepo.findOneOrFail({ where: { id: shipmentId } });
  const lines = await this.lineRepo.find({ where: { shipmentId } });

  const totalFob = lines.reduce((sum, l) => sum + l.lineFobIdr, 0);
  const cifBase = totalFob + shipment.freightIdr + shipment.insuranceIdr;
  const dutyTotal = cifBase * shipment.dutyRate;
  const ppnBase = cifBase + dutyTotal; // import value: add any other customs or excise levies
  const ppnTotal = ppnBase * shipment.ppnRate;

  return lines.map((line) => {
    const share = line.lineFobIdr / totalFob;           // apportionment key
    const freightShare = shipment.freightIdr * share;
    const insuranceShare = shipment.insuranceIdr * share;
    const dutyShare = dutyTotal * share;
    const otherShare = shipment.otherFeesIdr * share;
    // PPN import is a recoverable input credit, not part of inventory value
    const landedUnitCost =
      (line.lineFobIdr + freightShare + insuranceShare + dutyShare + otherShare) /
      line.quantity;

    return { itemId: line.itemId, landedUnitCost };
  });
}

Why PPN Impor Should Not Be Capitalized Into Inventory

PPN impor is a value-added tax paid at the border, but it is not a permanent cost of the goods the way freight or duty is. It becomes a Pajak Masukan, an input tax credit, that the importer offsets against output VAT collected on sales in the monthly VAT return. Folding it into landed cost and therefore into inventory value overstates what the goods actually cost the business and understates a tax asset that is genuinely recoverable within the same accounting period in most cases.

Keep bea masuk, freight, and insurance inside the landed cost calculation because they are irrecoverable costs of acquiring the goods, and keep PPN impor entirely outside it, posted instead to a VAT input account. Getting this separation right is what keeps inventory valuation and cost of goods sold defensible when an auditor or the tax office asks how a unit cost was derived.

Choosing the Right Apportionment Key

Not every shipment-level cost should be split the same way, because different costs are driven by different physical realities of the shipment.

  • By value: fair for insurance, since the premium is priced against the declared value of the goods being covered, so higher-value lines should absorb a larger share.
  • By weight: usually the better key for ocean or air freight, since carriers price by weight or chargeable weight, so a heavy low-value item should absorb more freight than a light high-value one.
  • By volume: useful when a shipment mixes bulky low-density items with dense high-value ones, so cubic space consumed, not just weight, is the fairer driver of freight cost.

Modeling Import Shipments in a Custom ERP Schema

The schema and apportionment function above keep the shipment-level charges on one header row and let every purchase line reference that shipment, so the calculation only needs to run once per shipment and fan out to every line proportionally. The key design decision is to keep the apportionment function idempotent: it should be safe to re-run against the same shipment after an input changes, recomputing every line's landed unit cost from scratch rather than incrementally adjusting a running total, which is where double-posting bugs usually creep in.

Design the recalculation as a full re-derivation keyed by shipment ID, not an incremental patch. When the freight forwarder's actual invoice replaces the provisional freight estimate, or customs issues a correction to the duty assessment, re-running the same function against the updated shipment header should produce a clean new landed unit cost for every line, and the difference against the previous cost becomes a single traceable inventory or cost-of-goods-sold adjustment.

Reconciling Provisional Estimates Against the Final Customs Assessment

Bea masuk on the import declaration is often provisional in practice. Under UU 17/2006, a customs officer can set the tariff or customs value before the declaration is lodged or within 30 days of it, recorded in an SPTNP, and the Director General can re-determine both for up to two years after the declaration date. Most ERPs handle this by posting an estimated landed cost at goods receipt using the declared PIB figures, then booking a true-up adjustment once the final assessment or the freight forwarder's actual invoice arrives. Whether that adjustment lands on inventory or on cost of goods sold depends on whether the stock is still on hand or has already been sold, so the ERP needs to check current quantity on hand for the item before deciding where the correction posts.

None of this is complicated math on its own, but it only works if the ERP treats freight, insurance, duty, and tax as first-class data attached to the shipment rather than afterthoughts bolted onto a purchase order. Get the apportionment key right, keep PPN impor out of inventory value, and build the recalculation to be idempotent, and the landed cost your system reports will hold up whether the audience is a margin dashboard, an auditor, or the tax office.

FAQ

Frequently Asked Questions

Short answers to what readers ask most about this topic.

What is landed cost in ERP inventory valuation?

Landed cost is the true total cost of an imported item once it reaches the warehouse, including its purchase price plus freight, insurance, import duty, and other acquisition charges. Recording only the supplier invoice price without these layers understates inventory value and overstates gross margin on every imported SKU.

How is bea masuk import duty calculated in Indonesia?

Bea masuk is calculated as the CIF value, meaning the FOB price plus freight and insurance, multiplied by the duty rate assigned to the item's HS code in the official tariff schedule. Rates vary widely by product category and can be reduced or eliminated under preferential trade agreements, so the HS code classification must be verified before the rate is applied.

Why should PPN impor not be included in landed cost?

PPN impor is a value-added tax that becomes a recoverable input tax credit offset against output VAT in the monthly VAT return, unlike freight or duty, which are permanent, irrecoverable costs of acquiring the goods. Including PPN impor in landed cost overstates inventory value and understates a tax asset the business can actually reclaim.

How do I apportion shipment costs across multiple purchase lines?

Pick an apportionment key such as each line's share of total FOB value, weight, or volume, then multiply that share by every shipment-level charge (freight, insurance, duty) and add the result to the line's own FOB cost. The right key depends on what actually drives the cost: weight usually fits ocean or air freight, while value often fits insurance premiums.

Can bea masuk change after goods are already received?

Yes. Under UU 17/2006, a customs officer can set a different tariff or customs value within 30 days of the import declaration, recorded in an SPTNP, and the Director General can re-determine both for up to two years after the declaration date. Most ERPs post a provisional landed cost at goods receipt using the declared PIB figures and then book a true-up adjustment against inventory or cost of goods sold once the final assessment arrives.