Instruction Pricing Engine for Laravel
3neti/instruction is a standalone Laravel package that evaluates the
cost of instruction-based workflows.
It extracts the pricing and charge computation logic from the x-change platform into a reusable domain package.
- Calculates charges for instruction payloads
- Supports dynamic instruction structures
- Applies tariff-based pricing per component
- Handles validation-based pricing rules
- Computes slice-based fees for divisible vouchers
- Supports wallet-based purchases via Bavix Laravel Wallet
- Uses Brick Money for safe and precise monetary handling
This package uses a dual representation of money:
| Type | Example | Meaning |
|---|---|---|
| Decimal (human) | '5.00' |
₱5.00 |
| Minor units (system) | 500 |
₱5.00 |
-
Use decimal strings when defining prices:
'price' => '5.00'
-
Internally, all values are stored and computed as integer minor units:
500 -
API responses return human-readable decimal values, while also exposing minor units.
This ensures:
- no floating point errors
- consistent financial calculations
- compatibility with wallet systems
composer require 3neti/instructionPublish config and migrations:
php artisan vendor:publish --tag=instruction-config
php artisan vendor:publish --tag=instruction-migrationsRun migrations:
php artisan migrateSeed canonical instruction items:
php artisan db:seed --class="LBHurtado\Instruction\Database\Seeders\InstructionItemSeeder"use LBHurtado\Instruction\Actions\EvaluateInstructionCharges;
use LBHurtado\Instruction\Support\ArrayChargeableCustomer;
use LBHurtado\Instruction\Support\ArrayInstructionSource;
$customer = new ArrayChargeableCustomer([
'email' => 'user@example.com',
]);
$instructions = new ArrayInstructionSource([
'count' => 2,
'inputs' => [
'fields' => ['email'],
],
]);
$result = app(EvaluateInstructionCharges::class)
->handle($customer, $instructions);Instruction items are wallet-capable products.
- Each
InstructionItemhas its own wallet - Charges can be:
- estimated (no wallet interaction)
- executed (via wallet purchase flow)
Example:
$customer->deposit(10000); // ₱100.00
$customer->pay($instructionItem);Revenue is credited to the instruction item's wallet.
POST /api/instruction/v1/estimate
{
"customer": {
"email": "user@example.com"
},
"instructions": {
"count": 2,
"inputs": {
"fields": ["email"]
}
}
}{
"success": true,
"data": {
"charges": [
{
"index": "inputs.fields.email",
"unit_price": 5,
"unit_price_minor": 500,
"quantity": 2,
"price": 10,
"price_minor": 1000,
"currency": "PHP",
"label": "Email",
"pay_count": 1
}
],
"total_amount": 10,
"total_amount_minor": 1000,
"total_items_charged": 1,
"currency": "PHP"
},
"meta": {}
}Instruction items support price history tracking.
Each change can be recorded with:
- old price
- new price
- effective date
- optional reason and actor
This enables:
- auditability
- pricing analytics
- future dashboards
All monetary values are stored and computed in minor units (e.g., centavos) to ensure precision and eliminate floating-point errors.
The package is structured into clear layers:
- Models -> persistence and wallet integration
- Services -> pricing and evaluation logic
- DTOs -> serialization and API output
This keeps the system maintainable and testable.
-
Human-facing inputs use decimal strings:
'price' => '5.00'
-
System computations use integers (minor units):
500
This removes ambiguity and ensures consistent behavior.
Instruction items are treated as products with wallets:
- Each item can accumulate revenue
- Enables per-instruction accounting
- Supports future dashboards and reconciliation
All pricing decisions are:
- explicit
- rule-based
- data-driven
This guarantees consistent results across environments and executions.
The system is designed to evolve:
- new instruction types
- additional validation rules
- pricing modifiers
- reporting and analytics
without breaking existing behavior.
Client / API / Host App
|
v
+-------------------------------+
| EvaluateInstructionCharges |
| Action |
+-------------------------------+
|
v
+-------------------------------+
| InstructionCostEvaluator |
| Service |
+-------------------------------+
|
+--------------------+
| |
v v
+-------------------+ +----------------------+
| InstructionItem | | InstructionSource |
| Repository | | / Customer Adapters |
+-------------------+ +----------------------+
|
v
+-------------------------------+
| InstructionItem Model |
| - Brick Money |
| - Minor-unit price storage |
| - Bavix ProductInterface |
| - Wallet-enabled |
+-------------------------------+
|
+--------------------+
| |
v v
+-------------------+ +----------------------+
| instruction_items | | instruction_item_ |
| table | | price_histories |
+-------------------+ +----------------------+
|
v
+-------------------------------+
| API / DTO Layer |
| - ChargeBreakdownData |
| - ChargeEstimateData |
| - decimal display output |
| - minor-unit metadata |
+-------------------------------+
- A client, controller, or host app calls the action.
- The action delegates pricing logic to
InstructionCostEvaluator. - The evaluator loads instruction items from the repository.
- The evaluator inspects the instruction payload and customer context.
InstructionItemsupplies wallet/product pricing behavior and money normalization.- Charges are computed in minor units.
- DTOs serialize the result into API-friendly decimal values, while preserving minor-unit fields.
composer testMIT