Purchase Module

SKYBIZ API — Purchase Module

Purchase

The Purchase module allows you to retrieve and create purchase invoice records in your SKYBIZ account. Supports both read and create operations.

Endpoint: /apiv2/modules/purchase.php

Required Permissions: Purchase — Read, Purchase — Create

Allowed DocTypes: SupInv (Invoice), SupCN (Credit Note), SupDN (Debit Note)


Read Purchase

Retrieves purchase invoices created within the given date range. Returns all fields — no field filtering or custom filters are supported for this module.

Base Request Structure

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "read",
  "date_from": "YYYY-MM-DD",
  "date_to": "YYYY-MM-DD"
}

Request Parameters

Parameter Description Required
api_key Your API key Yes
api_secret Your API secret Yes
action Must be "read" Yes
date_from Start date (YYYY-MM-DD) Yes
date_to End date (YYYY-MM-DD). Max 31 days range. Yes

Date Rules

  • Format must be YYYY-MM-DD — e.g. "2026-04-01"
  • Maximum range is 31 days
  • date_from cannot be after date_to

Available Fields (Read Only)

The Purchase module returns all fields. Field filtering is not supported for this module.

CurCodestringCurrency code

Field Type Description
Doc1No string Primary document number
Doc2No / Doc3No string Reference document numbers
D_ate string Document date
CusCode string Supplier code
CurRate1 float Exchange rate
TermCode integer Payment term code
HCNetAmt float Home currency net amount
HCDtTax float Home currency detail tax total
DocType string Document type — SupInv, SupCN, SupDN
DueDate string Payment due date
PostedYN string Flag — whether document is posted
ApprovedYN string Flag — whether document is approved
ItemCode string Item, other charge, or GL account code
Description string Line item description
Description2 string Secondary line description
Qty float Quantity
FactorQty float UOM conversion factor
UOM string Unit of measure

(Additional fields continue below)

OCRatefloatOther charge rate
FinCatCodestringFinancial category code
LineNointegerLine number

Field Type Description
UOMSingular string Singular form of the UOM
HCUnitCost float Home currency unit cost
HCLineAmt float Home currency line total
HCDiscount float Home currency discount amount
DisRate1 float Discount rate
HCTax float Home currency tax amount
TaxRate1 float Tax rate
DetailTaxCode string Tax code for the line
BlankLine string Line type — "0" Stock Item, "4" Other Charge, "6" GL Account
BranchCode string Branch code
DepartmentCode string Department code
ProjectCode string Project code
LocationCode string Stock location code
WarrantyDate string Warranty date
GRNNo string GRN reference number
PORunNo integer PO run number
PONO string PO number
LandingCost float Landing cost
OCCode string Other charge code
OCAmt float Other charge amount
GLCode string GL account code
ItemBatch string Item batch number

Example 1 — Get All Purchase (All Fields)

This request returns all purchase invoice fields for invoices created between April 1, 2026 and April 30, 2026.

Request

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "read",
  "date_from": "2026-04-01",
  "date_to": "2026-04-30"
}

Sample Code for making an API READ request using php

<?php
header('Content-Type: application/json');

// ============================================================
// STEP 1: CONFIGURATION
// ============================================================

$API_KEY = "your-api-key";
$API_SECRET = "your-api-secret";
$ACTION = "read";

// Date range (required for all endpoints, max 31 days)
$DATE_FROM = "2026-04-01";
$DATE_TO = "2026-04-30";

// ============================================================
// STEP 2: ENDPOINT
// ============================================================

$BASE_URL = "https://domain-name/01/clientportal/apiv2/modules"; //(replace it with your skybiz domain name url)
$ENDPOINT = "purchase.php";

// ============================================================
// STEP 3: REQUEST PARAMETERS
// ============================================================

$requestParams = [
    "date_from" => $DATE_FROM,
    "date_to" => $DATE_TO
];

// ============================================================
// STEP 4: BUILD PAYLOAD
// ============================================================

$payload = array_merge(
    [
        "api_key" => $API_KEY,
        "api_secret" => $API_SECRET,
        "action" => $ACTION
    ],
    $requestParams
);

// ============================================================
// STEP 5: SEND REQUEST
// ============================================================

$url = rtrim($BASE_URL, '/') . '/' . ltrim($ENDPOINT, '/');

$ch = curl_init($url);

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($payload),
    CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);

// ============================================================
// STEP 6: HANDLE CURL ERROR
// ============================================================

if ($response === false) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => curl_error($ch)
    ], JSON_PRETTY_PRINT);
    curl_close($ch);
    exit;
}

$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// ============================================================
// STEP 7: DECODE RESPONSE
// ============================================================

$result = json_decode($response, true);

if (!$result) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => "Invalid JSON from API",
        "raw_response" => $response
    ], JSON_PRETTY_PRINT);
    exit;
}

// ============================================================
// STEP 8: RETURN CLEAN JSON FORMAT
// ============================================================

echo json_encode([
    "status" => $result['status'] ?? "error",
    "timestamp" => date("c"),
    "request_id" => $result['request_id'] ?? uniqid("req_"),
    "data" => $result['data'] ?? null,
    "message" => $result['message'] ?? null
], JSON_PRETTY_PRINT);

Response (Success)

{
  "status": "response",
  "timestamp": "2026-04-30T04:07:04+00:00",
  "request_id": "req_69f2d56891e57",
  "data": {
    "requested_by": "your-api-key",
    "mode": "2",
    "date_range": {
      "from": "2026-04-01",
      "to": "2026-04-30",
      "days": 30
    },
    "total_returned": 2,
    "data": [
      {
        "Doc1No": "PINV-001",
        "CusCode": "SUPP001",
        "DocType": "SupInv",
        "HCNetAmt": 1500.00,
        "HCDtTax": 120.00,
        "D_ate": "2026-04-15"
      },
      {
        "Doc1No": "PINV-002",
        "CusCode": "SUPP002",
        "DocType": "SupInv",
        "HCNetAmt": 2500.00,
        "HCDtTax": 200.00,
        "D_ate": "2026-04-20"
      }
    ]
  }
}

Postman Steps — READ Request

  1. Set method to POST

2. Enter URL: https://your-domain/01/clientportal/apiv2/modules/purchase.php

3. Set header: Content-Type: application/json

4. Under Body, select raw and format JSON

5. Paste your request payload and click Send


Create Purchase Invoice

Creates one or more purchase invoice records. All documents are validated before any are saved. If any document fails, the entire batch is rejected.

Compulsory Fields — Header

Field Type Description
Doc1No string Unique document number. Must not already exist.
CusCode string Supplier code. Must exist in SKYBIZ (FinCatCode = ‘B70’).
DocType string Document type — SupInv, SupCN, SupDN, or PurRet
HCNetAmt float Net amount before tax. Must equal sum of all item HCLineAmt.
HCDtTax float Total tax amount. Must equal sum of all item HCTax.

Compulsory Fields — Items

FactorQtyfloatUOM conversion factor. Usually same as Qty. Must be greater than 0.

Field Type Description
ItemCode string Item code. Must exist in SKYBIZ (stock item, other charge, or GL account based on BlankLine).
Description string Item description (max 255 characters)
Qty float Quantity. Must be greater than 0 for stock items and other charges.
UOM string Unit of measure. Must exist in SKYBIZ UOM table.
HCUnitCost float Unit price. Must be greater than 0 for stock items.
HCLineAmt float Line total. Must equal Qty × HCUnitCost.
BlankLine string Line type — "0" Stock Item, "4" Other Charge, "6" GL Account

Optional Fields — Header

Field Type Description
Doc2No / Doc3No string Reference document numbers
D_ate string Document date in YYYY-MM-DD format. Defaults to today.
CurCode string Currency code. Default: MYR. Must exist in SKYBIZ if provided.
CurRate1 float Exchange rate. Default: 1. Must be greater than 0 if provided.

Optional Fields — Items

TaxRate1floatTax rate in percent — e.g. 8. If provided, HCTax is validated.
PONOstringPO number
OCAmtfloatOther charge amount

Field Type Description
Description2 string Second description line (max 255 characters)
UOMSingular string Singular form of UOM (auto-populated from UOM if empty)
HCDiscount / DisRate1 float Discount amount and discount rate (%)
HCTax float Tax amount for this line. Must equal HCLineAmt × (TaxRate1 / 100) if TaxRate1 > 0.
DetailTaxCode string Tax code. If provided, must exist in SKYBIZ with TaxType ‘2’ or ‘3’.
BranchCode string Branch code. If provided, must exist in SKYBIZ branch table.
DepartmentCode string Department code. If provided, must exist in SKYBIZ department table.
ProjectCode string Project code. If provided, must exist in SKYBIZ project table.
LocationCode string Stock location code. If provided, must exist in SKYBIZ location table.
WarrantyDate string Warranty date in YYYY-MM-DD format
GRNNo string GRN reference number
PORunNo integer PO run number
LandingCost float Landing cost
OCCode string Other charge code. If provided, must exist in SKYBIZ.
OCRate float Other charge rate
GLCode string GL account code. If provided, must exist in SKYBIZ.
FinCatCode string Financial category code
DUD1 to DUD6 string User-defined detail fields 1 through 6 (max 40 characters each)
LineNo integer Line sequence number. Auto-assigned if omitted.

BlankLine Values

Value Type Description
"0" Stock Item Item code must exist. HCUnitCost must be > 0.
"4" Other Charge Item code must exist.
"6" GL Account Item code must exist (GL account table).

⚠️ Amount Validation Rules: SKYBIZ validates that HCLineAmt = Qty × HCUnitCost and that the sum of all item HCLineAmt values matches the document header HCNetAmt. Mismatches will cause the entire document to fail.

Base Create Request Structure

{
  "api_key": "your-api-key",
  "api_secret": "your-api-secret",
  "action": "create",
  "purchase_data": {
    "documents": [
      {
        "Doc1No": "PINV-001",
        "CusCode": "SUPP001",
        "DocType": "SupInv",
        "D_ate": "2026-05-20",
        "HCNetAmt": 550.00,
        "HCDtTax": 44.00,
        "CurCode": "RM",
        "CurRate1": 1,
        "items": [
          {
            "ItemCode": "ITEM001",
            "Description": "Raw Material A",
            "Qty": 10,
            "FactorQty": 1,
            "UOM": "Piece",
            "HCUnitCost": 50.00,
            "HCLineAmt": 500.00,
            "BlankLine": "0",
            "HCTax": 40.00,
            "TaxRate1": 8,
            "LineNo": 1
          }
        ]
      }
    ]
  }
}

Sample Code for making an API CREATE request using php

<?php
header('Content-Type: application/json');

// ============================================================
// STEP 1: CONFIGURATION
// ============================================================

$API_KEY = "your-api-key";
$API_SECRET = "your-api-secret";
$ACTION = "create";

// ============================================================
// STEP 2: ENDPOINT
// ============================================================

$BASE_URL = "https://domain-name/01/clientportal/apiv2/modules"; //(replace it with your skybiz domain name url)
$ENDPOINT = "purchase.php";

// ============================================================
// STEP 3: DATA KEY
// ============================================================

$DATA_KEY = "purchase_data";

// ============================================================
// STEP 4: BUILD YOUR DOCUMENTS ARRAY
// ============================================================

$DOCUMENTS = [];

// --- Purchase example ---
$DOCUMENTS[] = [
    "Doc1No" => "PINV-001",
    "CusCode" => "SUPP001",
    "DocType" => "SupInv",
    "D_ate" => "2026-05-20",
    "HCNetAmt" => 550.00,
    "HCDtTax" => 44.00,
    "CurCode" => "RM",
    "CurRate1" => 1,
    "items" => [
        [
            "ItemCode" => "ITEM001",
            "Description" => "Raw Material A",
            "Qty" => 10,
            "FactorQty" => 1,
            "UOM" => "Piece",
            "HCUnitCost" => 50.00,
            "HCLineAmt" => 500.00,
            "BlankLine" => "0",
            "HCTax" => 40.00,
            "TaxRate1" => 8,
            "LineNo" => 1
        ]
    ]
];

// ============================================================
// STEP 5: CLIENT-SIDE COUNT CHECK (Please do not modify this)
// ============================================================

$totalDocuments = 0;

foreach ($DOCUMENTS as $document) {
    $totalDocuments++;

    if (empty($document['Doc1No'])) {
        echo json_encode([
            "status" => "REJECTED_BY_CLIENT",
            "timestamp" => date("c"),
            "request_id" => uniqid("req_"),
            "message" => "CLIENT-SIDE REJECTION: Document at position {$totalDocuments} has empty Doc1No",
            "action_required" => "Fix the document before sending to server"
        ], JSON_PRETTY_PRINT);
        exit;
    }
}

if ($totalDocuments > 500) {
    echo json_encode([
        "status" => "REJECTED_BY_CLIENT",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => "CLIENT-SIDE REJECTION: You have {$totalDocuments} documents. Maximum is 500.",
        "your_document_count" => $totalDocuments,
        "max_allowed" => 500,
        "action_required" => "Reduce your documents to 500 or less BEFORE sending to server"
    ], JSON_PRETTY_PRINT);
    exit;
}

echo "=== CLIENT-SIDE VALIDATION ===\n";
echo "Looped through all {$totalDocuments} documents one by one\n";
echo "All documents passed client validation\n";
echo "Document count: {$totalDocuments} (max 500)\n";
echo "Sending to server...\n\n";

// ============================================================
// STEP 6: SEND REQUEST
// ============================================================

$url = rtrim($BASE_URL, '/') . '/' . ltrim($ENDPOINT, '/');

$payload = [
    "api_key" => $API_KEY,
    "api_secret" => $API_SECRET,
    "action" => $ACTION,
    $DATA_KEY => ["documents" => $DOCUMENTS]
];

$ch = curl_init($url);

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_TIMEOUT => 120,
]);

$response = curl_exec($ch);

// ============================================================
// STEP 7: HANDLE CURL ERROR
// ============================================================

if ($response === false) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => curl_error($ch)
    ], JSON_PRETTY_PRINT);
    curl_close($ch);
    exit;
}

$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// ============================================================
// STEP 8: DECODE RESPONSE
// ============================================================

$result = json_decode($response, true);

if (!$result) {
    echo json_encode([
        "status" => "error",
        "timestamp" => date("c"),
        "request_id" => uniqid("req_"),
        "message" => "Invalid JSON from API",
        "raw_response" => $response
    ], JSON_PRETTY_PRINT);
    exit;
}

// ============================================================
// STEP 9: RETURN CLEAN JSON FORMAT
// ============================================================

echo "=== SERVER RESPONSE ===\n";
echo json_encode([
    "status" => $result['status'] ?? "error",
    "timestamp" => date("c"),
    "request_id" => $result['request_id'] ?? uniqid("req_"),
    "data" => $result['data'] ?? null,
    "message" => $result['message'] ?? null
], JSON_PRETTY_PRINT);

Response (Success)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_69fc0070d83cf",
  "data": {
    "requested_by": "your-api-key",
    "mode": "2",
    "summary": {
      "total_documents": 1,
      "inserted": 1,
      "failed": 0
    },
    "successful_documents": ["PINV-001"],
    "failed_documents": [],
    "fail_details": {
      "compulsory_fields_missing": [],
      "duplicate_documents": [],
      "invalid_suppliers": [],
      "invalid_items": [],
      "invalid_tax_codes": [],
      "invalid_locations": [],
      "invalid_departments": [],
      "invalid_projects": [],
      "invalid_branches": [],
      "invalid_currencies": [],
      "invalid_uoms": [],
      "amount_mismatch": [],
      "validation_errors": []
    }
  }
}

Response (Error — Duplicate Document)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_69fc03e446a20",
  "data": {
    "requested_by": "your-api-key",
    "mode": "2",
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "successful_documents": [],
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "duplicate_documents": ["PINV-001"],
      "invalid_currencies": [],
      "invalid_uoms": [],
      "amount_mismatch": [],
      "validation_errors": {}
    }
  }
}

Error Responses

Missing Date Range (READ)

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "date_from and date_to are required"
}

Invalid Date Format

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Invalid date format. Use YYYY-MM-DD format."
}

Date Range Exceeds 31 Days

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Date range cannot exceed 31 days."
}

Invalid DocType (CREATE)

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Invalid DocType 'XXX'. Allowed: SupInv, SupCN, SupDN, PurRet"
}

Missing Compulsory Fields (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "compulsory_fields_missing": [
        "Document 1 (Doc1No: PINV-001): Missing header fields - CusCode, HCNetAmt, HCDtTax, DocType"
      ]
    }
  }
}

Invalid Supplier Code (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "invalid_suppliers": [
        {
          "supplier_code": "INVALID",
          "document_no": "PINV-001",
          "error": "Supplier Code 'INVALID' does not exist"
        }
      ]
    }
  }
}

Invalid Item Code (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "invalid_items": [
        {
          "item_code": "INVALID",
          "document_no": "PINV-001",
          "line_no": 1,
          "blank_line_type": "0 (Stock Item)"
        }
      ]
    }
  }
}

Invalid UOM Code (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "invalid_uoms": [
        {
          "uom_code": "INVALID",
          "document_no": "PINV-001",
          "line_no": 1,
          "error": "UOM code 'INVALID' does not exist"
        }
      ]
    }
  }
}

Invalid Currency Code (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "invalid_currencies": [
        "Document 1 (Doc1No: PINV-001): Currency code 'INVALID' does not exist"
      ]
    }
  }
}

Amount Mismatch — Line Level (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "amount_mismatch": {
        "PINV-001": [
          {
            "line_no": 1,
            "item_code": "ITEM001",
            "provided_hclineamt": "100.00",
            "expected_hclineamt": "500.00",
            "error": "HCLineAmt does not match Qty × HCUnitCost"
          }
        ]
      }
    }
  }
}

Amount Mismatch — Header Level (CREATE)

{
  "status": "response",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "data": {
    "summary": {
      "total_documents": 1,
      "inserted": 0,
      "failed": 1
    },
    "failed_documents": ["PINV-001"],
    "fail_details": {
      "amount_mismatch": {
        "PINV-001": [
          "Header HCNetAmt (100.00) does not match sum of HCLineAmt (500.00)"
        ]
      }
    }
  }
}

No Read Permission

{
  "status": "error",
  "timestamp": "2026-04-07T10:46:15+08:00",
  "request_id": "req_6612f3b9c21a7",
  "message": "Purchase read permission denied"
}

No Create Permission

{
  "status": "error",
  "timestamp": "2026-05-20T10:30:00+08:00",
  "request_id": "req_123456",
  "message": "Purchase create permission denied"
}

Common Errors — Purchase Module

"Currency code 'X' does not exist"Invalid currency code (CREATE)Use a valid currency code (e.g., RM, SGD, USD)

Error Message Cause Fix
"date_from and date_to are required" Missing date range (READ only) Add both fields to your request
"Invalid date format. Use YYYY-MM-DD format." Wrong date format Use YYYY-MM-DD — e.g. "2026-04-01"
"Date range cannot exceed 31 days." Date range too wide Narrow range to 31 days or fewer
"Invalid DocType 'XXX'. Allowed: SupInv, SupCN, SupDN, PurRet" Wrong DocType in CREATE request Use one of the allowed DocTypes
"Missing fields - ItemCode, Description, Qty, FactorQty, UOM, HCUnitCost, HCLineAmt, BlankLine" Compulsory item fields not provided (CREATE) Include all required fields for each item
"UOM code 'X' does not exist" Invalid Unit of Measure (CREATE) Check the UOM exists in SKYBIZ (singular or plural form)
"Supplier Code 'X' does not exist" Invalid supplier code Check the supplier code exists in SKYBIZ (FinCatCode = ‘B70’)
"ItemCode 'X' does not exist" Invalid item code Check the item code exists in SKYBIZ (stock item, other charge, or GL account based on BlankLine)
"HCLineAmt does not match Qty × HCUnitCost" Amount calculation mismatch (CREATE) Ensure HCLineAmt = Qty × HCUnitCost (tolerance: ±0.01)
"Header HCNetAmt does not match sum of HCLineAmt" Header total doesn’t match item totals (CREATE) Set HCNetAmt to the sum of all item HCLineAmt (tolerance: ±0.01)
"HCTax does not match HCLineAmt × TaxRate1%" Tax calculation mismatch (CREATE) Ensure HCTax = HCLineAmt × (TaxRate1 / 100) (tolerance: ±0.01) when TaxRate1 > 0
"Document already exists" Duplicate Doc1No (CREATE) Use a unique Doc1No for each document
"Qty must be greater than 0 for Stock Item" Quantity is zero or negative for stock item (CREATE) Set Qty to a positive number greater than 0
"HCUnitCost must be greater than 0 for stock items" Unit cost is zero or negative for stock item (CREATE) Set HCUnitCost to a positive number greater than 0
"FactorQty must be greater than 0" Factor quantity is zero or negative (CREATE) Set FactorQty to a positive number (default is 1)
"Purchase read permission denied" No read permission for Purchase module Enable read permission in portal by contacting your SkyBiz Admin