Initial commit - WASL Digital Wallet

This commit is contained in:
Hamza-Ayed
2026-06-20 21:55:06 +03:00
commit 7306c47368
61 changed files with 4157 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Models\Traits;
/**
* Provides minor-unit (cents/halala) money helpers.
* All monetary amounts in WASL use BIGINT minor units.
* This trait provides conversion methods.
*
* Usage: $wallet->formatBalance('SYP') → "150,000.00 SYP"
*/
trait HasMinorUnits
{
/**
* Convert display amount (e.g., 1500.00) to minor units (150000).
* Uses string math to avoid float precision issues.
*/
public static function toMinor(string|int|float $amount, int $decimals = 2): int
{
return (int) round((float) $amount * (10 ** $decimals));
}
/**
* Convert minor units back to display amount string.
* Returns a string to preserve precision (e.g., "1500.00").
*/
public static function fromMinor(int $minor, int $decimals = 2): string
{
return number_format($minor / (10 ** $decimals), $decimals, '.', '');
}
/**
* Format a minor-unit value for user display.
* e.g., formatMoney(150000, 'SYP', 2) → "150,000.00 SYP"
*/
public static function formatMoney(
int $minor,
string $currency = 'SYP',
?int $decimals = null
): string {
$decimals = $decimals ?? config("wasl.wallet.minor_unit_decimals.{$currency}", 2);
$amount = self::fromMinor($minor, $decimals);
return number_format((float) $amount, $decimals, '.', ',') . ' ' . $currency;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Models\Traits;
/**
* Auto-generates a UUID on creation and provides uuid-based route binding.
* Every WASL model exposed to the API MUST use this trait.
*/
trait HasUuid
{
protected static function booted(): void
{
static::creating(function ($model) {
if (empty($model->getAttribute('uuid'))) {
$model->setAttribute('uuid', str()->uuid()->toString());
}
});
}
public function getRouteKeyName(): string
{
return 'uuid';
}
/**
* Resolve by UUID instead of BIGINT primary key.
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->where('uuid', $value)->firstOrFail();
}
/**
* Scope: filter by UUID.
*/
public function scopeWhereUuid($query, string $uuid)
{
return $query->where('uuid', $uuid);
}
}