You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.7 KiB
165 lines
4.7 KiB
<?php
|
|
|
|
namespace App\Livewire\Forms\Billing;
|
|
|
|
use App\Domains\Billing\DTOs\Invoicing\InvoiceDTO;
|
|
use App\Domains\Billing\DTOs\Invoicing\InvoiceItemDTO;
|
|
use App\Domains\Billing\DTOs\Invoicing\PricingDTO;
|
|
use App\Domains\Billing\Enums\Invoicing\InvoiceStatus;
|
|
use App\Domains\Billing\Enums\Invoicing\InvoiceType;
|
|
use App\Domains\System\Support\ValueObjects\Money;
|
|
use App\Livewire\Concerns\HasModelFill;
|
|
use App\UI\Support\Schemas\InputSchemaField;
|
|
use Livewire\Attributes\Locked;
|
|
use Livewire\Attributes\Validate;
|
|
use Livewire\Form;
|
|
|
|
class InvoiceForm extends Form
|
|
{
|
|
use HasModelFill;
|
|
|
|
#[Locked]
|
|
public string $id = '';
|
|
|
|
#[Validate('required|string|max:255', as: 'domains/billing/field.invoice.name')]
|
|
public string $name = '';
|
|
|
|
#[Validate('required', as: 'domains/billing/field.invoice.type')]
|
|
public ?InvoiceType $type = null;
|
|
|
|
#[Validate(['required', 'array', 'min:1'])]
|
|
public array $client_detail = [];
|
|
|
|
#[Validate]
|
|
public Money $gross_amount;
|
|
|
|
#[Validate]
|
|
public Money $discount_amount;
|
|
|
|
#[Validate]
|
|
public Money $net_amount;
|
|
|
|
#[Validate(['required', 'array', 'min:1'])]
|
|
public array $items = [];
|
|
|
|
#[Validate(as: 'domains/billing/field.invoice.type')]
|
|
public string $client_ref_id = '';
|
|
|
|
#[Validate('required', as: 'domains/billing/field.invoice.type')]
|
|
public string $client_id = '';
|
|
|
|
public function __construct($component, $propertyName)
|
|
{
|
|
parent::__construct($component, $propertyName);
|
|
|
|
$this->gross_amount = new Money(0);
|
|
$this->discount_amount = new Money(0);
|
|
$this->net_amount = new Money(0);
|
|
}
|
|
|
|
public function addItem(
|
|
string $code,
|
|
string $name,
|
|
int $quantity,
|
|
Money $price,
|
|
Money $discount,
|
|
int $product_id,
|
|
?int $coa_id
|
|
): void
|
|
{
|
|
$netAmount = $price->toInt() * $quantity;
|
|
|
|
$this->items[] = [
|
|
'code' => $code,
|
|
'name' => $name,
|
|
'quantity' => $quantity,
|
|
'gross_amount' => $price,
|
|
'discount_amount' => $discount,
|
|
'net_amount' => new Money($netAmount),
|
|
'product_id' => $product_id,
|
|
'chart_of_account_id' => $coa_id,
|
|
];
|
|
}
|
|
|
|
public function populatePricing(): void
|
|
{
|
|
$this->gross_amount = new Money(collect($this->items)->sum(fn($arr) => $arr['gross_amount']->toInt()));
|
|
$this->discount_amount = new Money(collect($this->items)->sum(fn($arr) => $arr['discount_amount']->toInt()));
|
|
$this->net_amount = new Money(collect($this->items)->sum(fn($arr) => $arr['net_amount']->toInt()));
|
|
}
|
|
|
|
public function updatedClientDetail($val, $prop): void
|
|
{
|
|
$formSchema = $this->type->schema()->getSchema();
|
|
|
|
$this->resetValidation();
|
|
foreach ($formSchema as $key => $schema) {
|
|
/** @var InputSchemaField $schema */
|
|
$schema = $schema->schema->getSchema();
|
|
if ($schema->dependsOn == $prop) {
|
|
$this->client_detail[$key] = '';
|
|
}
|
|
}
|
|
$this->validateOnly($prop);
|
|
}
|
|
|
|
public function resetSchema(): void
|
|
{
|
|
$this->reset('client_detail');
|
|
|
|
$schema = $this->type?->schema()->getSchema() ?? [];
|
|
|
|
foreach ($schema as $value) {
|
|
$this->client_detail[$value->key] = '';
|
|
}
|
|
|
|
$this->resetValidation();
|
|
}
|
|
|
|
public function rules(): array
|
|
{
|
|
return $this->type?->schema()?->getValidationRules('client_detail') ?? [];
|
|
}
|
|
|
|
public function validationAttributes(): array
|
|
{
|
|
return $this->type?->schema()?->getValidationAttributes('client_detail') ?? [];
|
|
}
|
|
|
|
public function toDTO(): InvoiceDTO
|
|
{
|
|
$items = [];
|
|
|
|
$detail = $this->type?->schema()?->resolveInputSnapshots($this->client_detail);
|
|
foreach ($this->items as $item) {
|
|
$itemDTO = new InvoiceItemDTO(
|
|
code: $item['code'],
|
|
name: $item['name'],
|
|
quantity: $item['quantity'],
|
|
product_id: $item['product_id'],
|
|
coa_id: $item['chart_of_account_id'],
|
|
);
|
|
$itemDTO->setPricing(
|
|
price: $item['gross_amount'],
|
|
discount: $item['discount_amount'],
|
|
);
|
|
|
|
|
|
$items[] = $itemDTO;
|
|
}
|
|
|
|
return new InvoiceDTO(
|
|
name: $this->name,
|
|
client_ref_id: $this->client_ref_id,
|
|
client_detail: $detail,
|
|
type: $this->type,
|
|
pricing: new PricingDTO(
|
|
gross_amount: $this->gross_amount,
|
|
discount_amount: $this->discount_amount,
|
|
net_amount: $this->net_amount,
|
|
),
|
|
items: $items,
|
|
client_id: $this->client_id
|
|
);
|
|
}
|
|
}
|
|
|