3neti/cash

A package to enable assigning cash to Eloquent Models

Maintainers

Package info

github.com/3neti/cash

pkg:composer/3neti/cash

Transparency log

Statistics

Installs: 98

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

v1.3.0 2026-07-31 03:18 UTC

This package is auto-updated.

Last update: 2026-07-31 03:21:49 UTC


README

A lightweight Laravel package for representing monetary value as a first-class model, with support for:

  • precise money handling (via Brick\Money)
  • wallet integration (via Bavix Wallet)
  • status lifecycle (via Spatie Model Status)
  • tagging (via Spatie Tags)
  • metadata and expiration handling

This package is designed as a supporting domain layer for the x-change ecosystem, particularly for voucher issuance, redemption, and disbursement workflows.

Supported platforms

  • PHP 8.3 and 8.4
  • Laravel 12 and 13
  • 3neti/wallet 1.x and 2.x

Laravel 12 and Laravel 13 are tested as separate compatibility lanes.

✨ Core Concept

Cash is a value container:

  • it represents an amount of money
  • it can be tagged, status-tracked, and expired
  • it can be linked to any model via reference
  • it integrates with wallet systems for transfer and settlement

It is not a ledger
It is not a wallet

It is a portable monetary unit used across workflows.

📦 Installation

composer require 3neti/cash:^1.3

⚙️ Configuration

Publish config (optional):

php artisan vendor:publish --tag=config

🧱 Database Migrations

This package uses:

loadMigrationsFrom()

So migrations are auto-loaded.

Run:

php artisan migrate

⚠️ Migration Prerequisites

This package depends on the following schema:

  • spatie/laravel-model-statusstatuses table
  • spatie/laravel-tagstags tables
  • 3neti/wallet / bavix/laravel-wallet → wallet tables

👉 These must be installed and migrated by the host application.

This package does NOT publish or manage those migrations.

🧠 Usage

Creating Cash

use LBHurtado\Cash\Models\Cash;

$cash = Cash::create([
    'amount' => 1500.00,
    'currency' => 'PHP',
    'meta' => ['note' => 'Transport support'],
]);

Using Money Object

use Brick\Money\Money;

$cash = Cash::create([
    'amount' => Money::of(1500, 'PHP'),
    'currency' => 'PHP',
]);

Stored internally as minor units.

Accessing Amount

$cash->amount; // Brick\Money\Money instance
$cash->amount->getAmount()->toFloat(); // 1500.00
$cash->amount->getMinorAmount()->toInt(); // 150000

Metadata

$cash->meta->note;
$cash->meta['note'];

Expiration

$cash->expired = true;
$cash->save();

$cash->expired; // true

Status Management

use LBHurtado\Cash\Enums\CashStatus;

$cash->setStatus(CashStatus::DISBURSED);

$cash->hasStatus(CashStatus::DISBURSED);
$cash->getCurrentStatus();

Secret Protection

$cash->secret = '1234';
$cash->save();

$cash->verifySecret('1234'); // true

Redemption Check

$cash->canRedeem('1234');

Tags

$cash->attachTag('transport');
$cash->tags;

Wallet Integration

$cash->depositFloat(1000);
$cash->withdrawFloat(500);

🧾 Data Transformation

Use CashData for API responses:

use LBHurtado\Cash\Data\CashData;

CashData::fromModel($cash);

🧱 Schema

cash
- id
- amount (minor units)
- currency
- reference_type
- reference_id
- meta (json)
- secret (hashed)
- expires_on
- timestamps

🧩 Relationships

  • morphTo: reference
  • morphOne: withdrawTransaction
  • statuses (Spatie)
  • tags (Spatie)
  • wallet (Bavix)

🧪 Testing

This package uses:

  • Testbench
  • in-memory SQLite
  • test-only migrations under tests/database/migrations

No vendor migrations are required for tests.

🧭 Architecture Role

In the x-change ecosystem:

  • cash = monetary payload
  • voucher = contract/instruction
  • wallet = balance + ledger
  • x-change = orchestration

🔒 Design Principles

  • Money is always stored in minor units
  • Currency is explicit
  • Status is first-class
  • Expiration is built-in
  • Metadata is flexible
  • Secrets are hashed

Withdrawal authorization

Cash withdrawal policy is exposed through container-resolved contracts for:

  • amount bounds;
  • withdrawal intervals;
  • claimant authorization;
  • vendor mandates;
  • approval policy; and
  • typed authorization decisions.

The default decision service reports whether a withdrawal is allowed or requires an independent approval. It does not dispatch a provider transfer or manufacture approval evidence. The integrating settlement system remains responsible for authenticating the officer, persisting authorization evidence, and invoking execution.

Resolve these services through Laravel's container so applications may replace policy implementations without changing Cash models.

🚀 Future Enhancements

  • reconciliation support
  • audit integration
  • stricter immutability enforcement
  • event hooks

🧾 License

Proprietary