Skip to content

Product Costing Categories

This process describes the implemented catalogue classification and its operator-run backfill. Products.Costing_Category is separate from the commercial Product_Category. Classification does not change billing prices or identify which Product belongs on an invoice line.

Classification

Category Cost basis identified by the classification
Labour/service Internal delivery labour; no Product purchase price is required
Purchased product/licence Purchased goods, licences or externally supplied services
Mixed/bundle Both internal labour and identified purchased components
Unclassified Costing type requires review

A blank or zero cost price does not establish a category. Explicit supplier-cost or delivery-budget links remain relevant in every category. The classification alone does not establish complete costs or a historical margin.

Seat L1/L2/L3/SB, their annual/prorated variants and Extra Device are classified as Labour/service because their licences are billed separately. Those licence Products have their own purchased-cost basis. An externally purchased service is a purchased item even though its name contains “service”.

Prepare and apply the backfill

Preparation captures all existing Products, including inactive records, and produces one classification per Product. Clear hardware/goods/software/licence categories map to purchased items. Other classifications require an explicit Product-ID decision and reason; otherwise the migration writes Unclassified. It does not infer labour from a missing price or broad “Managed Services” or “service” categories.

Applying the saved migration creates the Costing Category picklist when absent and updates only Costing_Category. Established classifications are preserved. The writer checks captured source values before batches of up to 100, uses a server-time cutoff to reject concurrent edits, disables optional record triggers and verifies every saved record.

The private journal supports restarting a partially completed run. Changed records, conflicting metadata or failed readback stop the batch. The writer does not modify Product prices, invoice Product links, invoices or billing inputs. New Products with blank categories remain unclassified until populated.

Implementation: commercial_services/product_costing_migration.py. Classification logic: app/service_planning/product_costing.py. Validation: tests/commercial_services/test_product_costing_migration.py.