StateSet One Guides
StateSet ReSponse Guides
StateSet Commerce Network Guides
StateSet One Guides
COGS Quickstart
Comprehensive guide to implementing COGS calculation with Stateset API
Cost of Goods Sold (COGS) Calculation Guide
This guide provides a comprehensive approach to calculating Cost of Goods Sold (COGS) using the Stateset API. It covers purchase order integration, work order processing, inventory management, and various costing methods.
Table of Contents
- Setup
- Purchase Order Integration
- Work Order and BOM Processing
- Inventory Management
- COGS Calculation Methods
- Periodic COGS Calculation
- Reporting
1. Setup
First, install the Stateset Node.js SDK:
npm install stateset-node
Then, initialize the Stateset client:
import { stateset } from 'stateset-node';
const client = stateset('YOUR_API_KEY');
2. Purchase Order Integration
2.1 Create Purchase Order
async function createPurchaseOrder(poData) {
try {
const created = await client.purchaseorder.create({
purchase_order: {
id: poData.id,
number: poData.number,
supplier: poData.supplier,
order_date: poData.orderDate,
expected_delivery_date: poData.expectedDeliveryDate,
status: poData.status,
total_amount: poData.totalAmount,
currency: poData.currency,
line_items: poData.lineItems
}
});
return created;
} catch (error) {
console.error("Error creating purchase order:", error);
throw error;
}
}
2.2 Retrieve and Update Purchase Orders
async function getPurchaseOrder(poNumber) {
try {
return await client.purchaseorder.retrieve(poNumber);
} catch (error) {
console.error("Error retrieving purchase order:", error);
throw error;
}
}
async function updatePurchaseOrder(poNumber, updateData) {
try {
return await client.purchaseorder.update(poNumber, updateData);
} catch (error) {
console.error("Error updating purchase order:", error);
throw error;
}
}
2.3 Receive Purchase Order
async function receivePurchaseOrder(poNumber) {
const po = await getPurchaseOrder(poNumber);
for (const lineItem of po.line_items) {
await updateInventory(lineItem.part_number, lineItem.quantity, lineItem.unit_cost);
}
await updatePurchaseOrder(poNumber, { status: 'RECEIVED', received_date: new Date() });
}
3. Work Order and BOM Processing
3.1 Retrieve Work Orders and BOMs
async function getWorkOrdersForPeriod(startDate, endDate) {
return await client.workOrder.list({
created_at: { gte: startDate, lte: endDate },
status: 'COMPLETED'
});
}
async function getBOMForWorkOrder(bomNumber) {
return await client.billOfMaterials.retrieve(bomNumber);
}
3.2 Calculate COGS for Work Order
async function calculateCOGSForWorkOrder(workOrder) {
const bom = await getBOMForWorkOrder(workOrder.bill_of_materials_number);
let totalCost = 0;
for (const lineItem of bom.line_items) {
const componentCost = await getComponentCost(lineItem.part_number);
totalCost += componentCost * lineItem.quantity;
}
return {
workOrderNumber: workOrder.number,
totalCost: totalCost,
quantityProduced: workOrder.line_items.reduce((sum, item) => sum + item.total_quantity, 0)
};
}
async function getComponentCost(partNumber) {
try {
// Retrieve the latest inventory record for the part
const latestInventory = await client.inventory.list({
part_number: partNumber,
limit: 1,
sort: '-updated_at'
});
if (latestInventory.length === 0) {
throw new Error(`No inventory found for part number: ${partNumber}`);
}
// Return the unit cost from the latest inventory record
return latestInventory[0].unit_cost;
} catch (error) {
console.error(`Error getting component cost for part ${partNumber}:`, error);
throw error;
}
}
4. Inventory Management
4.1 Update Inventory
async function updateInventory(partNumber, quantity, unitCost) {
try {
// Create a new inventory record
const newInventory = await client.inventory.create({
part_number: partNumber,
quantity: quantity,
unit_cost: unitCost
});
console.log(`Inventory updated for part ${partNumber}:`, newInventory);
return newInventory;
} catch (error) {
console.error(`Error updating inventory for part ${partNumber}:`, error);
throw error;
}
}
4.2 Get Inventory Movements
async function getInventoryMovements(productId, startDate, endDate) {
return await client.inventory.listMovements({
product: productId,
date: { gte: startDate, lte: endDate }
});
}
5. COGS Calculation Methods
5.1 Average Cost Method
async function calculateAverageCost(productId, dateRange) {
const purchases = await client.purchaseorder.list({ product: productId, date: dateRange });
const inventory = await client.inventory.list({ product: productId, date: dateRange });
const manufacturingCosts = await client.manufacturingorder.list({ product: productId, date: dateRange });
const totalCost = purchases.reduce((sum, po) => sum + po.total_cost, 0) +
manufacturingCosts.reduce((sum, cost) => sum + cost.amount, 0);
const totalQuantity = inventory.reduce((sum, inv) => sum + inv.quantity, 0);
return totalCost / totalQuantity;
}
5.2 Weighted Average Cost Method
import Big from 'big.js';
function calculateWeightedAverageCost(previousInventory, purchases) {
let totalCost = Big(previousInventory.cost).times(previousInventory.quantity);
let totalQuantity = Big(previousInventory.quantity);
for (const purchase of purchases) {
totalCost = totalCost.plus(Big(purchase.cost).times(purchase.quantity));
totalQuantity = totalQuantity.plus(purchase.quantity);
}
return totalQuantity.eq(0) ? Big(0) : totalCost.div(totalQuantity);
}
async function calculateWeightedAverageCOGS(productId, startDate, endDate) {
const purchaseOrders = await getPurchaseOrders(productId, startDate, endDate);
const inventoryMovements = await getInventoryMovements(productId, startDate, endDate);
const manufacturingCosts = await getManufacturingCosts(productId, startDate, endDate);
let inventory = { quantity: Big(0), cost: Big(0) };
let cogs = Big(0);
let totalPurchases = [];
const allMovements = [
...purchaseOrders.map(po => ({ date: po.date, type: 'purchase', ...po })),
...inventoryMovements.map(mov => ({ date: mov.date, type: 'movement', ...mov })),
...manufacturingCosts.map(mc => ({ date: mc.date, type: 'manufacturing', ...mc }))
].sort((a, b) => new Date(a.date) - new Date(b.date));
for (const movement of allMovements) {
switch (movement.type) {
case 'purchase':
case 'manufacturing':
totalPurchases.push({
quantity: Big(movement.quantity),
cost: Big(movement.type === 'purchase' ? movement.unitCost : movement.totalCost / movement.quantity)
});
break;
case 'movement':
if (movement.quantityChange > 0) {
const newAverageCost = calculateWeightedAverageCost(inventory, totalPurchases);
inventory.quantity = inventory.quantity.plus(movement.quantityChange);
inventory.cost = newAverageCost;
totalPurchases = [];
} else {
const quantitySold = Big(Math.abs(movement.quantityChange));
cogs = cogs.plus(inventory.cost.times(quantitySold));
inventory.quantity = inventory.quantity.minus(quantitySold);
}
break;
}
}
return {
cogs: cogs.toNumber(),
endingInventory: {
quantity: inventory.quantity.toNumber(),
averageCost: inventory.cost.toNumber()
}
};
}
6. Periodic COGS Calculation
async function calculateMonthlyCOGS() {
const date = new Date();
const startDate = new Date(date.getFullYear(), date.getMonth(), 1);
const endDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
const workOrders = await getWorkOrdersForPeriod(startDate, endDate);
let totalCOGS = 0;
let totalQuantityProduced = 0;
for (const workOrder of workOrders) {
const workOrderCOGS = await calculateCOGSForWorkOrder(workOrder);
totalCOGS += workOrderCOGS.totalCost;
totalQuantityProduced += workOrderCOGS.quantityProduced;
}
const averageCOGS = totalCOGS / totalQuantityProduced;
const previousPeriod = `${new Date(date.getFullYear(), date.getMonth() - 1, 1).getFullYear()}-${String(date.getMonth()).padStart(2, '0')}`;
const previousCOGSData = await getPreviousCOGSData(previousPeriod);
const cogsTrend = previousCOGSData
? ((totalCOGS - previousCOGSData.totalCOGS) / previousCOGSData.totalCOGS) * 100
: 0;
await storeCOGSData({
period: `${startDate.getFullYear()}-${String(startDate.getMonth() + 1).padStart(2, '0')}`,
totalCOGS,
averageCOGS,
quantityProduced: totalQuantityProduced,
cogsTrend
});
}
7. Reporting
async function generateCOGSReport(startDate, endDate) {
const workOrders = await getWorkOrdersForPeriod(startDate, endDate);
let totalCOGS = 0;
let totalQuantityProduced = 0;
const workOrderDetails = [];
for (const workOrder of workOrders) {
const workOrderCOGS = await calculateCOGSForWorkOrder(workOrder);
totalCOGS += workOrderCOGS.totalCost;
totalQuantityProduced += workOrderCOGS.quantityProduced;
workOrderDetails.push({
workOrderNumber: workOrder.number,
part: workOrder.part,
quantityProduced: workOrderCOGS.quantityProduced,
totalCost: workOrderCOGS.totalCost,
averageCost: workOrderCOGS.totalCost / workOrderCOGS.quantityProduced
});
}
return {
period: `${startDate.toISOString().split('T')[0]} to ${endDate.toISOString().split('T')[0]}`,
totalCOGS,
averageCOGS: totalCOGS / totalQuantityProduced,
quantityProduced: totalQuantityProduced,
workOrders: workOrderDetails
};
}
For any questions or assistance, please contact our support team at support@stateset.io.
On this page
- Cost of Goods Sold (COGS) Calculation Guide
- Table of Contents
- 1. Setup
- 2. Purchase Order Integration
- 2.1 Create Purchase Order
- 2.2 Retrieve and Update Purchase Orders
- 2.3 Receive Purchase Order
- 3. Work Order and BOM Processing
- 3.1 Retrieve Work Orders and BOMs
- 3.2 Calculate COGS for Work Order
- 4. Inventory Management
- 4.1 Update Inventory
- 4.2 Get Inventory Movements
- 5. COGS Calculation Methods
- 5.1 Average Cost Method
- 5.2 Weighted Average Cost Method
- 6. Periodic COGS Calculation
- 7. Reporting