Skip to content

Petty Cash

Petty cash management allows companies to maintain small cash funds for day-to-day minor expenses. Each petty cash fund is assigned a custodian (a user responsible for the fund), linked to a GL account, and has a maximum allowed amount. Transactions (receipts and payments) adjust the fund balance and can optionally generate journal entries.

Purpose

  • Create and manage petty cash funds with assigned custodians
  • Track receipt (replenishment) and payment (expense) transactions
  • Maintain a running balance with automatic adjustment on each transaction
  • Enforce fund limits to prevent overspending
  • Link each fund to a GL account for ledger integration
  • Provide a clear audit trail of all petty cash activity

Entity Attributes

Petty Cash (Fund)

FieldTypeDescription
idbigintPrimary key
company_idbigintFK to companies
namestringEnglish name (e.g., "Main Office Petty Cash")
name_arstring?Arabic name (e.g., "صندوق المصروفات النثرية - المكتب الرئيسي")
account_idbigintFK to accounts (linked GL account)
custodian_idbigint?FK to users (responsible person)
max_amountdecimal(12,3)Maximum fund limit
current_balancedecimal(12,3)Current available balance — derived from posted GL activity, never written directly
is_activebooleanWhether the fund is active
created_attimestampCreation timestamp
updated_attimestampLast update timestamp
deleted_attimestamp?Soft-delete timestamp

Petty Cash Transaction

FieldTypeDescription
idbigintPrimary key
company_idbigintFK to companies
petty_cash_idbigintFK to petty_cash
typeenumreceipt (replenishment) or payment (expense)
amountdecimal(12,3)Transaction amount
datedateTransaction date
descriptionstringEnglish description
description_arstring?Arabic description
referencestring?External reference (receipt number, voucher, etc.)
journal_entry_idbigint?FK to journal_entries (auto-generated)
created_bybigint?FK to users
created_attimestampCreation timestamp
updated_attimestampLast update timestamp

INFO

Petty cash transactions do not use soft deletes. When a transaction is deleted, its journal entry is reversed.

Single source of truth

current_balance is derived from the petty cash GL account's posted activity by PettyCashBalanceService::syncBalance() — it is re-synced after every transaction and never mutated directly. Payment sufficiency is checked against this GL-derived balance, so a stale current_balance can never authorise an overspend.

:::

Relationships

Transaction Types

TypeValueEffect on BalanceDescription
ReceiptreceiptIncreases balanceFund replenishment from main cash/bank
PaymentpaymentDecreases balanceExpense payment from the fund

API Endpoints

Petty Cash Funds

MethodPathDescription
GET/api/accounting/petty-cashList petty cash funds (paginated)
POST/api/accounting/petty-cashCreate a new petty cash fund
GET/api/accounting/petty-cash/{id}Get a single fund
PUT/api/accounting/petty-cash/{id}Update a fund
DELETE/api/accounting/petty-cash/{id}Soft-delete a fund

Petty Cash Transactions

MethodPathDescription
GET/api/accounting/petty-cash/{id}/transactionsList transactions for a fund
POST/api/accounting/petty-cash/{id}/transactionsCreate a transaction
GET/api/accounting/petty-cash/{id}/transactions/{txId}Get a transaction
DELETE/api/accounting/petty-cash/{id}/transactions/{txId}Delete and reverse a transaction

Request/Response Examples

Create Petty Cash Fund

Request POST /api/accounting/petty-cash

bash
curl -X POST https://moon-erp.test/api/accounting/petty-cash \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Main Office Petty Cash",
    "name_ar": "صندوق المصروفات النثرية - المكتب الرئيسي",
    "account_id": 3,
    "custodian_id": 2,
    "max_amount": "500.000",
    "is_active": true
  }'
dart
final response = await http.post(
  Uri.parse('https://moon-erp.test/api/accounting/petty-cash'),
  headers: {
    'Authorization': 'Bearer $token',
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  },
  body: jsonEncode({
    'name': 'Main Office Petty Cash',
    'name_ar': 'صندوق المصروفات النثرية - المكتب الرئيسي',
    'account_id': 3,
    'custodian_id': 2,
    'max_amount': '500.000',
    'is_active': true,
  }),
);

Response 201 Created

json
{
  "data": {
    "id": 1,
    "company_id": 1,
    "name": "Main Office Petty Cash",
    "name_en": "Main Office Petty Cash",
    "name_ar": "صندوق المصروفات النثرية - المكتب الرئيسي",
    "account_id": 3,
    "account": {
      "id": 3,
      "code": "1101",
      "name": "Cash on Hand",
      "name_ar": "النقدية بالصندوق"
    },
    "custodian_id": 2,
    "custodian": {
      "id": 2,
      "name": "Mohammed Ali",
      "name_ar": "محمد علي"
    },
    "max_amount": "500.000",
    "current_balance": "0.000",
    "is_active": true,
    "created_at": "2026-02-16T12:00:00.000000Z",
    "updated_at": "2026-02-16T12:00:00.000000Z"
  }
}

Create Receipt (Replenish Fund)

Request POST /api/accounting/petty-cash/1/transactions

json
{
  "type": "receipt",
  "amount": "500.000",
  "date": "2026-02-16",
  "description": "Initial fund replenishment",
  "description_ar": "تجديد الصندوق الأولي",
  "reference": "REP-001"
}

Response 201 Created

json
{
  "data": {
    "id": 1,
    "petty_cash_id": 1,
    "type": "receipt",
    "type_label": "Receipt",
    "amount": "500.000",
    "date": "2026-02-16",
    "description": "Initial fund replenishment",
    "description_ar": "تجديد الصندوق الأولي",
    "reference": "REP-001",
    "journal_entry_id": null,
    "created_by": 1,
    "created_at": "2026-02-16T12:00:00.000000Z"
  }
}

After this transaction, the fund's current_balance becomes 500.000.

Create Payment (Record Expense)

Request POST /api/accounting/petty-cash/1/transactions

json
{
  "type": "payment",
  "amount": "25.500",
  "date": "2026-02-17",
  "description": "Office supplies - printer paper",
  "description_ar": "مستلزمات مكتبية - ورق طابعة",
  "reference": "PC-EXP-001"
}

Response 201 Created

json
{
  "data": {
    "id": 2,
    "petty_cash_id": 1,
    "type": "payment",
    "type_label": "Payment",
    "amount": "25.500",
    "date": "2026-02-17",
    "description": "Office supplies - printer paper",
    "description_ar": "مستلزمات مكتبية - ورق طابعة",
    "reference": "PC-EXP-001",
    "journal_entry_id": null,
    "created_by": 1,
    "created_at": "2026-02-17T09:00:00.000000Z"
  }
}

After this transaction, the fund's current_balance becomes 474.500.

List Fund Transactions

Request GET /api/accounting/petty-cash/1/transactions

Response 200 OK

json
{
  "data": [
    {
      "id": 2,
      "type": "payment",
      "amount": "25.500",
      "date": "2026-02-17",
      "description": "مستلزمات مكتبية - ورق طابعة",
      "reference": "PC-EXP-001"
    },
    {
      "id": 1,
      "type": "receipt",
      "amount": "500.000",
      "date": "2026-02-16",
      "description": "تجديد الصندوق الأولي",
      "reference": "REP-001"
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 2 }
}

Delete Transaction (Reversal)

Request DELETE /api/accounting/petty-cash/1/transactions/2

Response 200 OK

json
{
  "message": "Deleted"
}

After deletion, the balance impact of the deleted transaction is reversed. If a payment of 25.500 is deleted, the fund's current_balance increases by 25.500 back to 500.000.

Business Rules

  1. GL account required -- Every petty cash fund must be linked to a detail-level GL account (typically "Cash on Hand" or a sub-account).
  2. Max amount limit -- The max_amount defines the ceiling for the fund. A receipt transaction cannot bring the balance above this limit.
  3. Insufficient balance -- A payment transaction is rejected if the amount exceeds the current_balance. The API returns a 422 error with the message "Insufficient petty cash balance."
  4. Automatic balance update -- receipt transactions increase current_balance; payment transactions decrease it. This is handled in a database transaction for consistency.
  5. Deletion reverses balance -- Deleting a transaction reverses its balance impact: deleting a receipt decreases the balance, deleting a payment increases it.
  6. Custodian assignment -- The custodian_id links to a user who is responsible for the fund. This is for tracking purposes.
  7. Created by tracking -- Each transaction records the created_by user for audit trails.
  8. Active funds only -- Transactions can only be created on active petty cash funds.

Workflow

Typical Monthly Cycle

  1. Month start -- Custodian receives a receipt (replenishment) to bring the fund to its maximum.
  2. During the month -- Custodian records payment transactions for minor expenses (office supplies, courier fees, small repairs).
  3. Month end -- Finance reviews all transactions, verifies receipts, and replenishes the fund for the next month.
  4. Journal entries -- If journal entry generation is enabled, each transaction creates a corresponding entry (debit expense account, credit petty cash account for payments; or debit petty cash account, credit bank account for receipts).

Moon ERP API Documentation