Goods Stock Maintain (T131)
Manage inventory levels by increasing or decreasing stock for registered goods. This endpoint supports stock-in (purchases, imports, manufacturing) and stock-out (adjustments, reductions) operations. Requires encrypted request and response.
Endpoint Overview
| Property | Value |
|---|---|
| Interface Code | T131 |
| Request Encrypted | ✅ Yes |
| Response Encrypted | ✅ Yes |
| Request Body | { goodsStockIn, goodsStockInItem } |
| Response Format | Array of items with status |
Flow Description
- Client constructs stock maintenance payload (
goodsStockInheader +goodsStockInItemlines). - Client specifies
operationType(101=Increase,102=Reduce). - Client sends encrypted request to server.
- Server validates goods codes, quantities, stock types, and branch permissions.
- Server updates inventory ledger.
- Server returns an array of results. Successful items may return empty messages; failed items return
returnCodeandreturnMessage.
⚠️ Critical:
- For
operationType=102(Reduction),adjustTypeandsupplierName/supplierTinmust be empty.- For
stockInType=103(Manufacturing),productionBatchNoandproductionDateare required.- Ensure goods are registered (T130) before maintaining stock.
- PHP
- JavaScript / TypeScript
- Python
try {
// Construct stock maintenance payload
$stockData = [
'goodsStockIn' => [
'operationType' => '101', // 101=Increase, 102=Reduce
'supplierTin' => $config['tin'],
'supplierName' => 'Test Supplier',
'remarks' => 'Integration test stock in',
'stockInDate' => date('Y-m-d'),
'stockInType' => '102', // 102=Local Purchase
'isCheckBatchNo' => '0',
'rollBackIfError' => '0',
'goodsTypeCode' => '101' // 101=Goods, 102=Fuel
],
'goodsStockInItem' => [
[
'commodityGoodsId' => $context['goods_id'],
'goodsCode' => $context['goods_code'],
'measureUnit' => '101',
'quantity' => '10',
'unitPrice' => '100.00',
'remarks' => 'Test stock entry'
]
]
];
// Call T131: Maintain Stock
$response = $client->maintainStock($stockData);
$results = $response['data']['content'] ?? $response;
if (is_array($results)) {
foreach ($results as $index => $result) {
$code = $result['returnCode'] ?? '00';
$msg = $result['returnMessage'] ?? 'SUCCESS';
if ($code === '00' || empty($code)) {
echo "✅ Stock Item #{$index} updated successfully\n";
} else {
echo "❌ Stock Item #{$index} failed: {$code} - {$msg}\n";
}
}
}
} catch (\UraEfrisSdk\Exceptions\APIException $e) {
echo "❌ Stock maintain failed: " . $e->getMessage() . "\n";
echo " Return Code: " . $e->getReturnCode() . "\n";
}
try {
// Construct stock maintenance payload
const stockData = {
goodsStockIn: {
operationType: '101', // 101=Increase, 102=Reduce
supplierTin: config.tin,
supplierName: 'Test Supplier',
remarks: 'Integration test stock in',
stockInDate: new Date().toISOString().slice(0, 10),
stockInType: '102', // 102=Local Purchase
isCheckBatchNo: '0',
rollBackIfError: '0',
goodsTypeCode: '101'
},
goodsStockInItem: [
{
commodityGoodsId: context.goods_id,
goodsCode: context.goods_code,
measureUnit: '101',
quantity: '10',
unitPrice: '100.00',
remarks: 'Test stock entry'
}
]
};
// Call T131: Maintain Stock
const response = await client.maintainStock(stockData);
const results = response?.data?.content ?? response;
if (Array.isArray(results)) {
results.forEach((result: any, index: number) => {
const code = result.returnCode ?? '00';
const msg = result.returnMessage ?? 'SUCCESS';
if (code === '00' || !code) {
console.log(`✅ Stock Item #${index} updated successfully`);
} else {
console.error(`❌ Stock Item #${index} failed: ${code} - ${msg}`);
}
});
}
} catch (error: any) {
console.error(`❌ Stock maintain failed: ${error.message}`);
if (error.returnCode) {
console.error(` Return Code: ${error.returnCode}`);
}
throw error;
}
try:
# Construct stock maintenance payload
stock_data = {
"goodsStockIn": {
"operationType": "101", # 101=Increase, 102=Reduce
"supplierTin": config["tin"],
"supplierName": "Test Supplier",
"remarks": "Integration test stock in",
"stockInDate": datetime.now().strftime('%Y-%m-%d'),
"stockInType": "102", # 102=Local Purchase
"isCheckBatchNo": "0",
"rollBackIfError": "0",
"goodsTypeCode": "101"
},
"goodsStockInItem": [
{
"commodityGoodsId": context["goods_id"],
"goodsCode": context["goods_code"],
"measureUnit": "101",
"quantity": "10",
"unitPrice": "100.00",
"remarks": "Test stock entry"
}
]
}
# Call T131: Maintain Stock
response = client.maintain_stock(stock_data)
results = response.get("data", {}).get("content", response)
if isinstance(results, list):
for index, result in enumerate(results):
code = result.get("returnCode", "00")
msg = result.get("returnMessage", "SUCCESS")
if code == "00" or not code:
print(f"✅ Stock Item #{index} updated successfully")
else:
print(f"❌ Stock Item #{index} failed: {code} - {msg}")
except Exception as e:
print(f"❌ Stock maintain failed: {e}")
if hasattr(e, "return_code"):
print(f" Return Code: {e.return_code}")
raise
Request Structure
{
"goodsStockIn": {
"operationType": "101",
"supplierTin": "1000029771",
"supplierName": "Supplier Name",
"adjustType": "",
"remarks": "Stock increase",
"stockInDate": "2025-02-19",
"stockInType": "102",
"productionBatchNo": "",
"productionDate": "",
"branchId": "2020090132456",
"invoiceNo": "",
"isCheckBatchNo": "0",
"rollBackIfError": "0",
"goodsTypeCode": "101"
},
"goodsStockInItem": [
{
"commodityGoodsId": "287700992426868373",
"goodsCode": "ITEM001",
"measureUnit": "101",
"quantity": "100",
"unitPrice": "6999.00",
"remarks": "Item remarks",
"fuelTankId": "",
"lossQuantity": "",
"originalQuantity": ""
}
]
}
Response Structure
[
{
"commodityGoodsId": "287700992426868373",
"goodsCode": "ITEM001",
"measureUnit": "101",
"quantity": "100",
"unitPrice": "6999.00",
"remarks": "Item remarks",
"returnCode": "00",
"returnMessage": "SUCCESS"
},
{
"commodityGoodsId": "287700992426868374",
"goodsCode": "ITEM002",
"measureUnit": "101",
"quantity": "50",
"unitPrice": "5000.00",
"remarks": "Item remarks",
"returnCode": "601",
"returnMessage": "MeasureUnit:Invalid field value!"
}
]
Field Descriptions
Goods Stock In (Header)
| Field | Required | Type | Description |
|---|---|---|---|
operationType | ✅ Yes | String (3) | 101=Increase inventory, 102=Inventory reduction |
supplierTin | ⚠️ Conditional | String (50) | Required if operationType=101. Must be empty if operationType=102 or stockInType=103. |
supplierName | ⚠️ Conditional | String (100) | Required if operationType=101. Must be empty if operationType=102 or stockInType=103. |
adjustType | ⚠️ Conditional | String (20) | Required if operationType=102. Values: 101=Expired, 102=Damaged, 103=Personal, 104=Others, 105=Raw Material. Multiple separated by commas. |
remarks | ⚠️ Conditional | String (1024) | Required if operationType=102 AND adjustType=104. |
stockInDate | ❌ No | Date | Format: yyyy-MM-dd. |
stockInType | ⚠️ Conditional | String (3) | Required if operationType=101. Must be empty if operationType=102. Values: 101=Import, 102=Local Purchase, 103=Manufacture, 104=Opening Stock. |
productionBatchNo | ⚠️ Conditional | String (50) | Required if stockInType=103. Must be empty otherwise. |
productionDate | ⚠️ Conditional | Date | Required if stockInType=103. Format: yyyy-MM-dd. Must be empty otherwise. |
branchId | ❌ No | String (18) | Target branch ID. |
invoiceNo | ❌ No | String (20) | Related invoice number (optional). |
isCheckBatchNo | ❌ No | String (1) | 0=No (default), 1=Yes. |
rollBackIfError | ❌ No | String (1) | 0=No (default), 1=Yes. |
goodsTypeCode | ❌ No | String (3) | 101=Goods (default), 102=Fuel. |
Goods Stock In Item (Line Items)
| Field | Required | Type | Description |
|---|---|---|---|
commodityGoodsId | ⚠️ Conditional | String (18) | Required if goodsCode is empty. Cannot be empty at same time as goodsCode. |
goodsCode | ⚠️ Conditional | String (50) | Required if commodityGoodsId is empty. Cannot be empty at same time as commodityGoodsId. |
measureUnit | ❌ No | String (3) | From T115 rateUnit. Must match maintained commodity unit. |
quantity | ✅ Yes | Number | Integer ≤12 digits, Decimal ≤8 digits. |
unitPrice | ✅ Yes | Number | Purchase price. Can be 0. Integer ≤12, Decimal ≤8. |
remarks | ❌ No | String (1024) | Item-specific remarks. |
fuelTankId | ❌ No | String (18) | Required for fuel products. |
lossQuantity | ❌ No | Number | For stock adjustments/losses. |
originalQuantity | ❌ No | Number | For stock adjustments/losses. |
Return Codes (T131 Specific)
| Code | Message | Description |
|---|---|---|
00 | SUCCESS | Stock updated successfully |
99 | Unknown error | Generic server error |
601 | MeasureUnit:Invalid field value! | Unit not found in dictionary |
656 | commodityGoodsId cannot be empty! | Missing goods ID |
658 | commodityGoodsId or goodsCode does not exist! | Invalid goods reference |
659 | quantity cannot be empty! | Missing quantity |
664 | unitPrice cannot be empty! | Missing price |
2076 | operationType:cannot be empty! | Missing operation type |
2078 | operationType: invalid field value! | Invalid operation type |
2079 | supplierTin:cannot be empty! | Missing supplier TIN (for stock-in) |
2081 | If 'operationType' is '101', supplierName cannot be empty! | Missing supplier name |
2083 | If 'operationType' is '102', supplierName must be empty! | Supplier name present for reduction |
2085 | If 'adjustType' is '104', remarks cannot be empty! | Missing remarks for 'Others' adjustment |
2088 | If 'operationType' is '102', adjustType cannot be empty! | Missing adjustment type for reduction |
2091 | Item is not in stock! | Cannot reduce non-existent stock |
2092 | Original inventory quantity cannot be less than the reduced quantity! | Insufficient stock |
2114 | StockInDate:The time format must be yyyy-MM-dd! | Invalid date format |
2126 | stockInType:cannot be empty! | Missing stock-in type |
2129 | If 'stockInType' not equals to '103', productionBatchNo must be empty! | Batch no present for non-manufacturing |
2176 | This product has been stored, it cannot stock in using opening stock | Cannot use opening stock on existing items |
2193 | branchId: branch does not belong to current taxpayer! | Invalid branch |
2243 | measureUnit: inconsistent with the maintained commodity unit! | Unit mismatch |
2810 | Invoice number does not exist! | Referenced invoice not found |
2841 | Same FDN or productionBatchNo cannot be stocked in more than once! | Duplicate batch/invoice |
3016 | lossQuantity cannot be empty! | Missing loss quantity for adjustments |
💡 Tip: For
operationType=102(Reduction), ensureadjustTypeis set andsupplierTin/supplierNameare explicitly empty to avoid validation errors.
Common Use Cases
-
Stock-In (Purchase)
UseoperationType=101,stockInType=102(Local Purchase). ProvidesupplierTin,supplierName,quantity,unitPrice. -
Stock-In (Import)
UseoperationType=101,stockInType=101(Import). Link to import invoice if applicable. -
Stock-In (Manufacturing)
UseoperationType=101,stockInType=103(Manufacture). ProvideproductionBatchNo,productionDate.supplierTinmust be empty. -
Opening Stock
UseoperationType=101,stockInType=104(Opening Stock). Only for new goods not previously stocked. -
Stock Reduction (Adjustment)
UseoperationType=102. ProvideadjustType(e.g.,101=Expired).supplierTin/supplierNamemust be empty.quantityrepresents reduction amount. -
Fuel Stock Management
UsegoodsTypeCode=102. ProvidefuelTankIdfor each item. TracklossQuantityfor evaporation/leakage.