feat: add CurrencyStripping trait for consistent currency handling across requests

This commit is contained in:
Yoga Pangestu 2026-08-04 22:11:50 +07:00
parent d90d2261ac
commit 318afca796
16 changed files with 127 additions and 105 deletions

View File

@ -0,0 +1,57 @@
<?php
namespace App\Concerns;
trait CurrencyStripping
{
protected function stripCurrencyDot(array $data, string ...$fields): array
{
foreach ($fields as $field) {
$data = $this->stripField($data, $field);
}
return $data;
}
private function stripField(array $data, string $field): array
{
if (str_contains($field, '*')) {
return $this->stripNestedField($data, $field);
}
if (isset($data[$field]) && is_string($data[$field])) {
$data[$field] = (int) str_replace('.', '', $data[$field]);
}
return $data;
}
private function stripNestedField(array $data, string $pattern): array
{
$parts = explode('.', $pattern);
$this->stripNestedRecursive($data, $parts);
return $data;
}
private function stripNestedRecursive(array &$data, array $parts): void
{
$current = array_shift($parts);
if ($current === '*') {
if (is_array($data)) {
foreach ($data as &$item) {
$this->stripNestedRecursive($item, $parts);
}
}
} elseif (empty($parts)) {
if (isset($data[$current]) && is_string($data[$current])) {
$data[$current] = (int) str_replace('.', '', $data[$current]);
}
} else {
if (isset($data[$current]) && is_array($data[$current])) {
$this->stripNestedRecursive($data[$current], $parts);
}
}
}
}

View File

@ -2,24 +2,23 @@
namespace App\Http\Requests\Admin\Finance;
use App\Concerns\CurrencyStripping;
use Illuminate\Foundation\Http\FormRequest;
use Override;
class CashTransactionRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
}
#[Override]
public function prepareForValidation()
public function prepareForValidation(): void
{
if ($this->has('amount')) {
$this->merge([
'amount' => str_replace('.', '', $this->amount),
]);
}
$this->merge($this->stripCurrencyDot($this->validated(), 'amount'));
}
public function rules(): array

View File

@ -2,24 +2,23 @@
namespace App\Http\Requests\Admin\Finance;
use App\Concerns\CurrencyStripping;
use Illuminate\Foundation\Http\FormRequest;
use Override;
class EmployeeAdvanceRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
}
#[Override]
public function prepareForValidation()
public function prepareForValidation(): void
{
if ($this->has('amount')) {
$this->merge([
'amount' => str_replace('.', '', $this->amount),
]);
}
$this->merge($this->stripCurrencyDot($this->validated(), 'amount'));
}
public function rules(): array

View File

@ -2,24 +2,23 @@
namespace App\Http\Requests\Admin\Finance;
use App\Concerns\CurrencyStripping;
use Illuminate\Foundation\Http\FormRequest;
use Override;
class ExpenseRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
}
#[Override]
public function prepareForValidation()
public function prepareForValidation(): void
{
if ($this->has('amount')) {
$this->merge([
'amount' => str_replace('.', '', $this->amount),
]);
}
$this->merge($this->stripCurrencyDot($this->validated(), 'amount'));
}
public function rules(): array

View File

@ -2,6 +2,7 @@
namespace App\Http\Requests\Admin\Finance;
use App\Concerns\CurrencyStripping;
use App\Enums\PayrollAdjustmentType;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@ -9,19 +10,17 @@
class PayrollAdjustmentRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
}
#[Override]
public function prepareForValidation()
public function prepareForValidation(): void
{
if ($this->has('amount')) {
$this->merge([
'amount' => str_replace('.', '', $this->amount),
]);
}
$this->merge($this->stripCurrencyDot($this->validated(), 'amount'));
}
public function rules(): array

View File

@ -2,12 +2,15 @@
namespace App\Http\Requests\Admin\Manage;
use App\Concerns\CurrencyStripping;
use App\Enums\RawMaterialUnit;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class PurchaseRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
@ -15,22 +18,7 @@ public function authorize(): bool
public function prepareForValidation(): void
{
$variants = $this->variants;
if (is_array($variants)) {
foreach ($variants as $i => $variant) {
if (isset($variant['price']) && is_string($variant['price'])) {
$this->request->set("variants.$i.price", (int) str_replace('.', '', $variant['price']));
}
}
}
if (is_string($this->discount)) {
$this->request->set('discount', (int) str_replace('.', '', $this->discount));
}
if (is_string($this->shipping_cost)) {
$this->request->set('shipping_cost', (int) str_replace('.', '', $this->shipping_cost));
}
$this->merge($this->stripCurrencyDot($this->validated(), 'variants.*.price', 'discount', 'shipping_cost'));
}
public function rules(): array

View File

@ -2,6 +2,7 @@
namespace App\Http\Requests\Admin\Manage;
use App\Concerns\CurrencyStripping;
use App\Enums\OrderChannel;
use App\Enums\PaymentType;
use App\Enums\PriceType;
@ -11,6 +12,8 @@
class TransactionRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
@ -18,17 +21,7 @@ public function authorize(): bool
public function prepareForValidation(): void
{
if ($this->has('discount')) {
$this->merge([
'discount' => str_replace('.', '', $this->discount),
]);
}
if ($this->has('nego_price')) {
$this->merge([
'nego_price' => str_replace('.', '', $this->nego_price),
]);
}
$this->merge($this->stripCurrencyDot($this->validated(), 'discount', 'nego_price'));
}
public function rules(): array

View File

@ -2,6 +2,7 @@
namespace App\Http\Requests\Admin\Master\Product;
use App\Concerns\CurrencyStripping;
use App\Enums\PriceType;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
@ -9,35 +10,17 @@
class ProductRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
}
#[Override]
public function prepareForValidation()
public function prepareForValidation(): void
{
$sharedPrices = $this->shared_prices;
if (is_array($sharedPrices)) {
foreach ($sharedPrices as $i => $price) {
if (isset($price['price']) && is_string($price['price'])) {
$this->request->set("shared_prices.$i.price", (int) str_replace('.', '', $price['price']));
}
}
}
$variants = $this->variants;
if (is_array($variants)) {
foreach ($variants as $i => $variant) {
if (isset($variant['prices']) && is_array($variant['prices'])) {
foreach ($variant['prices'] as $j => $price) {
if (isset($price['price']) && is_string($price['price'])) {
$this->request->set("variants.$i.prices.$j.price", (int) str_replace('.', '', $price['price']));
}
}
}
}
}
$this->merge($this->stripCurrencyDot($this->validated(), 'shared_prices.*.price', 'variants.*.prices.*.price'));
}
public function rules(): array

View File

@ -2,12 +2,15 @@
namespace App\Http\Requests\Admin\Master\Product;
use App\Concerns\CurrencyStripping;
use App\Enums\PriceType;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class ProductVariantRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
@ -15,14 +18,7 @@ public function authorize(): bool
public function prepareForValidation(): void
{
$prices = $this->prices;
if (is_array($prices)) {
foreach ($prices as $i => $price) {
if (isset($price['price']) && is_string($price['price'])) {
$this->request->set("prices.$i.price", (int) str_replace('.', '', $price['price']));
}
}
}
$this->merge($this->stripCurrencyDot($this->validated(), 'prices.*.price'));
}
public function rules(): array

View File

@ -2,12 +2,15 @@
namespace App\Http\Requests\Admin\Master\RawMaterial;
use App\Concerns\CurrencyStripping;
use App\Enums\RawMaterialUnit;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class RawMaterialRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
@ -15,14 +18,7 @@ public function authorize(): bool
public function prepareForValidation(): void
{
$variants = $this->variants;
if (is_array($variants)) {
foreach ($variants as $i => $variant) {
if (isset($variant['price']) && is_string($variant['price'])) {
$this->request->set("variants.$i.price", (int) str_replace('.', '', $variant['price']));
}
}
}
$this->merge($this->stripCurrencyDot($this->validated(), 'variants.*.price'));
}
public function rules(): array

View File

@ -2,10 +2,13 @@
namespace App\Http\Requests\Admin\Master\RawMaterial;
use App\Concerns\CurrencyStripping;
use Illuminate\Foundation\Http\FormRequest;
class RawMaterialVariantRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
@ -13,10 +16,7 @@ public function authorize(): bool
public function prepareForValidation(): void
{
$price = $this->price;
if (is_string($price)) {
$this->request->set('price', (int) str_replace('.', '', $price));
}
$this->merge($this->stripCurrencyDot($this->validated(), 'price'));
}
public function rules(): array

View File

@ -2,30 +2,23 @@
namespace App\Http\Requests\Admin\Settings;
use App\Concerns\CurrencyStripping;
use Illuminate\Foundation\Http\FormRequest;
use Override;
class UpdateHRRequest extends FormRequest
{
use CurrencyStripping;
public function authorize(): bool
{
return true;
}
#[Override]
public function prepareForValidation()
public function prepareForValidation(): void
{
if ($this->has('late_penalty_amount')) {
$this->merge([
'late_penalty_amount' => str_replace('.', '', $this->late_penalty_amount),
]);
}
if ($this->has('absent_penalty_amount')) {
$this->merge([
'absent_penalty_amount' => str_replace('.', '', $this->absent_penalty_amount),
]);
}
$this->merge($this->stripCurrencyDot($this->validated(), 'late_penalty_amount', 'absent_penalty_amount'));
}
public function rules(): array

View File

@ -10,6 +10,11 @@ class PasswordUpdateRequest extends FormRequest
{
use PasswordValidationRules;
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*

View File

@ -10,6 +10,11 @@ class ProfileDeleteRequest extends FormRequest
{
use PasswordValidationRules;
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*

View File

@ -8,6 +8,11 @@
class ProfileUpdateRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*

View File

@ -10,6 +10,11 @@ class TwoFactorAuthenticationRequest extends FormRequest
{
use InteractsWithTwoFactorState;
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*