Compare commits
2 Commits
a496679cb1
...
7fa427ef65
| Author | SHA1 | Date |
|---|---|---|
|
|
7fa427ef65 | 2 months ago |
|
|
33da380c20 | 3 months ago |
159 changed files with 1282 additions and 2914 deletions
@ -0,0 +1,18 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Domains\Academic\Queries\Lookup; |
||||
|
|
||||
|
use App\Domains\Academic\Models\Faculty; |
||||
|
use Illuminate\Support\Collection; |
||||
|
|
||||
|
class FacultyLookup |
||||
|
{ |
||||
|
public static function fetch(): Collection |
||||
|
{ |
||||
|
return once(fn () => Faculty::query() |
||||
|
->select(['id', 'name']) |
||||
|
->latest() |
||||
|
->get() |
||||
|
->pluck('name', 'id')); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Domains\Academic\Queries\Lookup; |
||||
|
|
||||
|
use App\Domains\Academic\Models\Term; |
||||
|
use Illuminate\Support\Collection; |
||||
|
|
||||
|
class TermLookup |
||||
|
{ |
||||
|
public static function fetch($search = null): Collection |
||||
|
{ |
||||
|
return once(fn () => Term::query() |
||||
|
->select(['id', 'name']) |
||||
|
->when($search, fn ($query) => $query->where('name', 'like', "%{$search}%")) |
||||
|
->latest('date_start') |
||||
|
->pluck('name', 'name')); |
||||
|
} |
||||
|
} |
||||
@ -1,15 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Academic\Queries\Selection; |
|
||||
|
|
||||
use App\Domains\Academic\Models\Faculty; |
|
||||
use Illuminate\Support\Collection; |
|
||||
|
|
||||
class SelectFacultyQuery |
|
||||
{ |
|
||||
public static function fetch(): Collection |
|
||||
{ |
|
||||
return once(fn () => Faculty::all(['id', 'name']) |
|
||||
->pluck('name', 'id')); |
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Academic\Queries\Selection; |
|
||||
|
|
||||
use App\Domains\Academic\Models\Term; |
|
||||
use Illuminate\Support\Collection; |
|
||||
|
|
||||
class SelectTermQuery |
|
||||
{ |
|
||||
public static function fetch(): Collection |
|
||||
{ |
|
||||
return once(fn () => Term::all(['id', 'name']) |
|
||||
->pluck('name', 'id')); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,15 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Domains\Admission\Events\Pricing; |
||||
|
|
||||
|
use Illuminate\Foundation\Events\Dispatchable; |
||||
|
use Illuminate\Queue\SerializesModels; |
||||
|
|
||||
|
class AdmissionFeeRateWasSetUp |
||||
|
{ |
||||
|
use Dispatchable, SerializesModels; |
||||
|
|
||||
|
public function __construct( |
||||
|
public string $productName |
||||
|
) {} |
||||
|
} |
||||
@ -0,0 +1,108 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Domains\Admission\Integration\Mappers; |
||||
|
|
||||
|
use App\Domains\Academic\Models\StudyProgram; |
||||
|
use App\Domains\Admission\Actions\AdmissionPricing\SetUpAdmissionFeeRates; |
||||
|
use App\Domains\Admission\DTOs\AdmissionPricing\AdmissionFeeRatesDTO; |
||||
|
use App\Domains\Admission\Models\AcademicProgram; |
||||
|
use App\Domains\Admission\Models\AdmissionSchedule; |
||||
|
use App\Domains\Admission\Models\FeeRate; |
||||
|
use App\Domains\Admission\Models\FeeType; |
||||
|
use Illuminate\Database\Eloquent\Model; |
||||
|
use App\Domains\System\Support\Integration\DataPayloadMapper; |
||||
|
|
||||
|
class FeeRateDataMapper implements DataPayloadMapper |
||||
|
{ |
||||
|
private static array $cache = []; |
||||
|
|
||||
|
public function __construct( |
||||
|
protected SetUpAdmissionFeeRates $setUpAdmissionFeeRates, |
||||
|
) |
||||
|
{ |
||||
|
// Inject required Domain and Cross-Domain Actions via constructor composition |
||||
|
} |
||||
|
|
||||
|
public function getLookupKey(): array |
||||
|
{ |
||||
|
// Return the unique string key used to identify existing records (e.g., 'email') |
||||
|
return ['admission_schedule_id', 'fee_type_id', 'academic_program_id']; |
||||
|
} |
||||
|
|
||||
|
public function transform(array $rawData): array |
||||
|
{ |
||||
|
if(!isset($rawData['jalur'])){ |
||||
|
dd($rawData); |
||||
|
} |
||||
|
// Normalize incoming data array formats into an internal domain-safe layout |
||||
|
return [ |
||||
|
'admission_schedule_id' => $this->resolveAdmissionScheduleId($rawData['jalur'], $rawData['angkatan']), |
||||
|
'academic_program_id' => $this->resolveAcademicProgramId($rawData['kode_Skuliah']), |
||||
|
'study_program_id' => $this->resolveStudyProgramId($rawData['kode_prodi']), |
||||
|
'fee_type_id'=> $this->resolveFeeTypeId($rawData['kode_Jtagihan']), |
||||
|
'amount' => $rawData['nominal_TRFtagihan'], |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
public function updateOrCreateDomainState(array $payload, ?Model $existingModel = null): void |
||||
|
{ |
||||
|
$this->setUpAdmissionFeeRates->execute(new AdmissionFeeRatesDTO( |
||||
|
academicProgramId: $payload['academic_program_id'], |
||||
|
admissionScheduleId: $payload['admission_schedule_id'], |
||||
|
studyProgramId: $payload['study_program_id'], |
||||
|
feeTypeId: $payload['fee_type_id'], |
||||
|
amount: $payload['amount'], |
||||
|
)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return class-string |
||||
|
*/ |
||||
|
public function getModelClass(): string |
||||
|
{ |
||||
|
return FeeRate::class; |
||||
|
} |
||||
|
|
||||
|
public function resolveAdmissionScheduleId(string $admissionTrackSlug, int $yearStudy): int { |
||||
|
$key = hex2bin(md5("{$admissionTrackSlug}-{$yearStudy}") ); |
||||
|
if (!isset(self::$cache['admission_schedule'][$key])) { |
||||
|
self::$cache['admission_schedule'][$key] = AdmissionSchedule::query() |
||||
|
->whereHas( |
||||
|
'admissionTrack', |
||||
|
fn($builder) => $builder->where('slug', str($admissionTrackSlug)->slug()) |
||||
|
)->whereHas( |
||||
|
'term', |
||||
|
fn($builder) => $builder->where('year_study', $yearStudy) |
||||
|
)->first()?->id; |
||||
|
} |
||||
|
|
||||
|
return self::$cache['admission_schedule'][$key]; |
||||
|
} |
||||
|
|
||||
|
public function resolveStudyProgramId($code): int { |
||||
|
if (!isset(self::$cache['study_program'][$code])) { |
||||
|
self::$cache['study_program'][$code] = StudyProgram::where('code', $code)->first()?->id; |
||||
|
} |
||||
|
|
||||
|
return self::$cache['study_program'][$code]; |
||||
|
} |
||||
|
|
||||
|
public function resolveFeeTypeId(string $code): int { |
||||
|
$key = hex2bin(md5($code)); |
||||
|
if (!isset(self::$cache['fee_type'][$key])) { |
||||
|
self::$cache['fee_type'][$key] = FeeType::where('code', $code)->first()?->id; |
||||
|
} |
||||
|
|
||||
|
return self::$cache['fee_type'][$key]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public function resolveAcademicProgramId(string $code): int { |
||||
|
$key = hex2bin(md5($code)); |
||||
|
if (!isset(self::$cache['academic_program'][$key])) { |
||||
|
self::$cache['academic_program'][$key] = AcademicProgram::where('code', $code)->first()?->id; |
||||
|
} |
||||
|
|
||||
|
return self::$cache['academic_program'][$key]; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Domains\Admission\Queries\Lookup; |
||||
|
|
||||
|
use App\Domains\Admission\Models\FeeType; |
||||
|
use Illuminate\Support\Collection; |
||||
|
|
||||
|
class FeeTypeLookup |
||||
|
{ |
||||
|
public static function fetch(): Collection |
||||
|
{ |
||||
|
return once(fn () => FeeType::query() |
||||
|
->select(['id', 'name']) |
||||
|
->latest() |
||||
|
->get() |
||||
|
->pluck('name', 'id')); |
||||
|
} |
||||
|
} |
||||
@ -1,13 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Admission\Queries\Selection; |
|
||||
|
|
||||
use Illuminate\Database\Eloquent\Collection; |
|
||||
|
|
||||
class SelectFeeTypeQuery |
|
||||
{ |
|
||||
public function fetch(): Collection |
|
||||
{ |
|
||||
return new Collection; |
|
||||
} |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\DisbursementProcessing; |
|
||||
|
|
||||
class DisburseFunds |
|
||||
{ |
|
||||
public function execute(): void |
|
||||
{ |
|
||||
// |
|
||||
} |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\DisbursementProcessing; |
|
||||
|
|
||||
class RecordVendorBill |
|
||||
{ |
|
||||
public function execute(): void |
|
||||
{ |
|
||||
// |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\LedgerConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\DTOs\LedgerConfiguration\AdjustAccountClassificationDTO; |
|
||||
use App\Domains\Finance\Models\ChartOfAccount; |
|
||||
|
|
||||
class AdjustAccountClassification |
|
||||
{ |
|
||||
public function execute(ChartOfAccount $coa, AdjustAccountClassificationDTO $dto): void |
|
||||
{ |
|
||||
$coa->update([ |
|
||||
'code' => $dto->code, |
|
||||
'classification' => $dto->classification, |
|
||||
'parent_id' => $dto->parentId, |
|
||||
]); |
|
||||
} |
|
||||
} |
|
||||
@ -1,20 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\LedgerConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\DTOs\LedgerConfiguration\RegisterChartOfAccountDTO; |
|
||||
use App\Domains\Finance\Models\ChartOfAccount; |
|
||||
|
|
||||
class RegisterChartOfAccount |
|
||||
{ |
|
||||
public function execute(RegisterChartOfAccountDTO $dto): void |
|
||||
{ |
|
||||
ChartOfAccount::create([ |
|
||||
'code' => $dto->code, |
|
||||
'name' => $dto->name, |
|
||||
'classification' => $dto->classification, |
|
||||
'status' => $dto->status, |
|
||||
'parent_id' => $dto->parentId, |
|
||||
]); |
|
||||
} |
|
||||
} |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\LedgerConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\Models\ChartOfAccount; |
|
||||
use App\Domains\System\Enums\LifecycleStatus; |
|
||||
|
|
||||
class SuspendAccountPostings |
|
||||
{ |
|
||||
public function execute(ChartOfAccount $coa): void |
|
||||
{ |
|
||||
$coa->update([ |
|
||||
'status' => LifecycleStatus::INACTIVE, |
|
||||
]); |
|
||||
} |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\PaymentProcessing; |
|
||||
|
|
||||
use App\Domains\Finance\DTOs\PaymentProcessing\IssueInvoiceDTO; |
|
||||
use App\Domains\Finance\Models\Invoice; |
|
||||
|
|
||||
class InitializeInvoice |
|
||||
{ |
|
||||
public function execute(IssueInvoiceDTO $dto): void |
|
||||
{ |
|
||||
Invoice::create([ |
|
||||
'name' => $dto->name, |
|
||||
'detail' => $dto->detail->toArray(), |
|
||||
'client_ref_id' => $dto->clientRefId, |
|
||||
'type' => $dto->type, |
|
||||
'amount' => $dto->amount, |
|
||||
'status' => $dto->status, |
|
||||
'client_id' => $dto->clientId, |
|
||||
'chart_of_account_id' => $dto->coaId, |
|
||||
]); |
|
||||
} |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\PaymentProcessing; |
|
||||
|
|
||||
class ProcessIncomingPaymentWebhook |
|
||||
{ |
|
||||
public function execute(): void |
|
||||
{ |
|
||||
// |
|
||||
} |
|
||||
} |
|
||||
@ -1,13 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\ProductConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\Models\ProductMapping; |
|
||||
|
|
||||
class ModifyProductMapping |
|
||||
{ |
|
||||
public function execute(ProductMapping $productMapping, string|int $coaId): void |
|
||||
{ |
|
||||
$productMapping->update(['chart_of_account_id' => $coaId]); |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Actions\ProductConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\DTOs\ProductConfiguration\RegisterProductMappingDTO; |
|
||||
use App\Domains\Finance\Models\ProductMapping; |
|
||||
|
|
||||
class RegisterProductMapping |
|
||||
{ |
|
||||
public function execute(RegisterProductMappingDTO $dto): void |
|
||||
{ |
|
||||
ProductMapping::create([ |
|
||||
'name' => $dto->name, |
|
||||
'code' => $dto->code, |
|
||||
'chart_of_account_id' => $dto->coaId, |
|
||||
]); |
|
||||
} |
|
||||
} |
|
||||
@ -1,10 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\DisbursementProcessing; |
|
||||
|
|
||||
readonly class DisburseFundsDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
// |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,10 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\DisbursementProcessing; |
|
||||
|
|
||||
readonly class VendorBillDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
// |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,14 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\LedgerConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\Enums\AccountClassification; |
|
||||
|
|
||||
readonly class AdjustAccountClassificationDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
public string $code, |
|
||||
public AccountClassification $classification, |
|
||||
public ?int $parentId, |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,17 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\LedgerConfiguration; |
|
||||
|
|
||||
use App\Domains\Finance\Enums\AccountClassification; |
|
||||
use App\Domains\System\Enums\LifecycleStatus; |
|
||||
|
|
||||
readonly class RegisterChartOfAccountDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
public string $code, |
|
||||
public string $name, |
|
||||
public AccountClassification $classification, |
|
||||
public LifecycleStatus $status, |
|
||||
public ?int $parentId, |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,17 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\PaymentProcessing; |
|
||||
|
|
||||
use Carbon\CarbonImmutable; |
|
||||
|
|
||||
readonly class BankWebhookPayloadDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
public int $virtualAccount, |
|
||||
public string $bankRefId, |
|
||||
public CarbonImmutable $validUntil, |
|
||||
public float $amount, |
|
||||
public string $status, |
|
||||
public string $transactionId |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,10 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\PaymentProcessing\Detail; |
|
||||
|
|
||||
interface InvoiceDetailDTO |
|
||||
{ |
|
||||
public function toArray(): array; |
|
||||
|
|
||||
public static function fromArray(array $data): self; |
|
||||
} |
|
||||
@ -1,36 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\PaymentProcessing\Detail; |
|
||||
|
|
||||
class StudentInvoiceDetailDTO implements InvoiceDetailDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
public string $studentId, |
|
||||
public string $studentName, |
|
||||
public string $faculty, |
|
||||
public string $studyProgram, |
|
||||
public string $term, |
|
||||
) {} |
|
||||
|
|
||||
public function toArray(): array |
|
||||
{ |
|
||||
return [ |
|
||||
'student_id' => $this->studentId, |
|
||||
'student_name' => $this->studentName, |
|
||||
'faculty' => $this->faculty, |
|
||||
'study_program' => $this->studyProgram, |
|
||||
'term' => $this->term, |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
public static function fromArray(array $data): self |
|
||||
{ |
|
||||
return new self( |
|
||||
studentId: $data['student_id'], |
|
||||
studentName: $data['student_name'], |
|
||||
faculty: $data['faculty'], |
|
||||
studyProgram: $data['study_program'], |
|
||||
term: $data['term'], |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
@ -1,21 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\PaymentProcessing; |
|
||||
|
|
||||
use App\Domains\Finance\DTOs\PaymentProcessing\Detail\InvoiceDetailDTO; |
|
||||
use App\Domains\Finance\Enums\InvoiceStatus; |
|
||||
use App\Domains\Finance\Enums\InvoiceType; |
|
||||
|
|
||||
readonly class IssueInvoiceDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
public string $name, |
|
||||
public string $clientRefId, |
|
||||
public InvoiceDetailDTO $detail, |
|
||||
public InvoiceType $type, |
|
||||
public InvoiceStatus $status, |
|
||||
public int $amount, |
|
||||
public string $coaId, |
|
||||
public string $clientId |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,10 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\ProductConfiguration; |
|
||||
|
|
||||
readonly class ModifyProductMappingDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
// |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,12 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\DTOs\ProductConfiguration; |
|
||||
|
|
||||
readonly class RegisterProductMappingDTO |
|
||||
{ |
|
||||
public function __construct( |
|
||||
public string $name, |
|
||||
public string $code, |
|
||||
public int $coaId |
|
||||
) {} |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Enums; |
|
||||
|
|
||||
use App\Domains\System\Traits\Enum\HasPredicateMethod; |
|
||||
use App\UI\Enums\Concerns\InteractsWithLabels; |
|
||||
use App\UI\Enums\Contracts\HasLabel; |
|
||||
|
|
||||
enum AccountClassification: string implements HasLabel |
|
||||
{ |
|
||||
use HasPredicateMethod; |
|
||||
use InteractsWithLabels; |
|
||||
|
|
||||
case ASSET = 'asset'; |
|
||||
case LIABILITY = 'liability'; |
|
||||
case EQUITY = 'equity'; |
|
||||
case REVENUE = 'revenue'; |
|
||||
case EXPENSE = 'expense'; |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Enums; |
|
||||
|
|
||||
use App\Domains\System\Traits\Enum\HasPredicateMethod; |
|
||||
use App\UI\Enums\Concerns\InteractsWithLabels; |
|
||||
use App\UI\Enums\Contracts\HasLabel; |
|
||||
|
|
||||
enum InvoiceStatus: string implements HasLabel |
|
||||
{ |
|
||||
use HasPredicateMethod; |
|
||||
use InteractsWithLabels; |
|
||||
|
|
||||
case PAID = 'paid'; |
|
||||
case PENDING = 'pending'; |
|
||||
case PARTIALLY_PAID = 'partially_paid'; |
|
||||
case OVERDUE = 'overdue'; |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Enums; |
|
||||
|
|
||||
use App\Domains\Finance\DTOs\PaymentProcessing\Detail\InvoiceDetailDTO; |
|
||||
use App\Domains\Finance\DTOs\PaymentProcessing\Detail\StudentInvoiceDetailDTO; |
|
||||
use App\Domains\Finance\Schemas\Invoice\StudentInvoiceSchema; |
|
||||
use App\Domains\Finance\Support\Schemas\InvoiceSchema; |
|
||||
use App\Domains\System\Traits\Enum\HasPredicateMethod; |
|
||||
use App\UI\Enums\Concerns\InteractsWithLabels; |
|
||||
use App\UI\Enums\Contracts\HasLabel; |
|
||||
use App\UI\Enums\Contracts\HasSchema; |
|
||||
use App\UI\Support\Schemas\InputSchemaField; |
|
||||
|
|
||||
enum InvoiceType: string implements HasLabel, HasSchema |
|
||||
{ |
|
||||
use HasPredicateMethod; |
|
||||
use InteractsWithLabels; |
|
||||
|
|
||||
case STUDENT_INVOICE = 'student_invoice'; |
|
||||
case VENDOR_BILL = 'vendor_bill'; |
|
||||
case CREDIT_NOTE = 'credit_note'; |
|
||||
|
|
||||
public function schema(): InvoiceSchema |
|
||||
{ |
|
||||
return match ($this) { |
|
||||
self::STUDENT_INVOICE => StudentInvoiceSchema::make(), |
|
||||
default => InvoiceSchema::make()->withCoaVisibility(), |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
public function dtoTransform(array $data): InvoiceDetailDTO |
|
||||
{ |
|
||||
return match ($this) { |
|
||||
self::STUDENT_INVOICE => StudentInvoiceDetailDTO::fromArray($data), |
|
||||
default => false |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Resolve all field schemas, keyed by their input keys. |
|
||||
* |
|
||||
* @return array<string, InputSchemaField> |
|
||||
*/ |
|
||||
public function getSchema(): array |
|
||||
{ |
|
||||
return $this->schema()->getSchema(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Enums; |
|
||||
|
|
||||
use App\Domains\System\Traits\Enum\HasPredicateMethod; |
|
||||
use App\UI\Enums\Concerns\InteractsWithLabels; |
|
||||
use App\UI\Enums\Contracts\HasLabel; |
|
||||
|
|
||||
enum PaymentDirection: string implements HasLabel |
|
||||
{ |
|
||||
use HasPredicateMethod; |
|
||||
use InteractsWithLabels; |
|
||||
|
|
||||
case RECEIPT = 'receipt'; |
|
||||
case DISBURSEMENT = 'disbursement'; |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Enums; |
|
||||
|
|
||||
use App\Domains\System\Traits\Enum\HasPredicateMethod; |
|
||||
use App\UI\Enums\Concerns\InteractsWithLabels; |
|
||||
use App\UI\Enums\Contracts\HasLabel; |
|
||||
|
|
||||
enum PaymentStatus: string implements HasLabel |
|
||||
{ |
|
||||
use HasPredicateMethod; |
|
||||
use InteractsWithLabels; |
|
||||
|
|
||||
case PENDING = 'pending'; |
|
||||
case SUCCESS = 'success'; |
|
||||
case FAILED = 'failed'; |
|
||||
case EXPIRED = 'expired'; |
|
||||
} |
|
||||
@ -1,38 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Models; |
|
||||
|
|
||||
use App\Domains\Finance\Enums\AccountClassification; |
|
||||
use App\Domains\Finance\Policies\ChartOfAccountPolicy; |
|
||||
use App\Domains\System\Enums\LifecycleStatus; |
|
||||
use App\Domains\System\Traits\Model\HasPublicUlid; |
|
||||
use Database\Factories\Finance\ChartOfAccountFactory; |
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable; |
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy; |
|
||||
use Illuminate\Database\Eloquent\Factories\Factory; |
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
|
||||
use Illuminate\Database\Eloquent\Model; |
|
||||
|
|
||||
#[Fillable([ |
|
||||
'code', |
|
||||
'name', |
|
||||
'classification', |
|
||||
'status', |
|
||||
'parent_id', |
|
||||
])] |
|
||||
#[UsePolicy(ChartOfAccountPolicy::class)] |
|
||||
class ChartOfAccount extends Model |
|
||||
{ |
|
||||
use HasFactory; |
|
||||
use HasPublicUlid; |
|
||||
|
|
||||
protected $casts = [ |
|
||||
'classification' => AccountClassification::class, |
|
||||
'status' => LifecycleStatus::class, |
|
||||
]; |
|
||||
|
|
||||
protected static function newFactory(): Factory |
|
||||
{ |
|
||||
return ChartOfAccountFactory::new(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,55 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Models; |
|
||||
|
|
||||
use App\Domains\Finance\Casts\MoneyCurrency; |
|
||||
use App\Domains\Finance\Enums\InvoiceStatus; |
|
||||
use App\Domains\Finance\Enums\InvoiceType; |
|
||||
use App\Domains\Finance\Policies\InvoicePolicy; |
|
||||
use App\Domains\System\Traits\Model\HasPublicUlid; |
|
||||
use Database\Factories\Finance\InvoiceFactory; |
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable; |
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy; |
|
||||
use Illuminate\Database\Eloquent\Factories\Factory; |
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
|
||||
use Illuminate\Database\Eloquent\Model; |
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo; |
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany; |
|
||||
|
|
||||
#[Fillable([ |
|
||||
'name', |
|
||||
'detail', |
|
||||
'client_ref_id', |
|
||||
'type', |
|
||||
'amount', |
|
||||
'status', |
|
||||
'client_id', |
|
||||
'chart_of_account_id', |
|
||||
])] |
|
||||
#[UsePolicy(InvoicePolicy::class)] |
|
||||
class Invoice extends Model |
|
||||
{ |
|
||||
use HasFactory; |
|
||||
use HasPublicUlid; |
|
||||
|
|
||||
protected $casts = [ |
|
||||
'amount' => MoneyCurrency::class, |
|
||||
'type' => InvoiceType::class, |
|
||||
'status' => InvoiceStatus::class, |
|
||||
]; |
|
||||
|
|
||||
protected static function newFactory(): Factory |
|
||||
{ |
|
||||
return InvoiceFactory::new(); |
|
||||
} |
|
||||
|
|
||||
public function chartOfAccount(): BelongsTo |
|
||||
{ |
|
||||
return $this->belongsTo(ChartOfAccount::class); |
|
||||
} |
|
||||
|
|
||||
public function payments(): HasMany |
|
||||
{ |
|
||||
return $this->hasMany(Payment::class); |
|
||||
} |
|
||||
} |
|
||||
@ -1,42 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Models; |
|
||||
|
|
||||
use App\Domains\Finance\Casts\MoneyCurrency; |
|
||||
use App\Domains\Finance\Enums\InvoiceStatus; |
|
||||
use App\Domains\Finance\Policies\InvoiceReportPolicy; |
|
||||
use BadMethodCallException; |
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable; |
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy; |
|
||||
use Illuminate\Database\Eloquent\Model; |
|
||||
|
|
||||
#[Fillable([ |
|
||||
'invoice_id', |
|
||||
'invoice_name', |
|
||||
'customer_id', |
|
||||
'customer_name', |
|
||||
'amount', |
|
||||
'paid_amount', |
|
||||
'issued_at', |
|
||||
'paid_at', |
|
||||
'status', |
|
||||
])] |
|
||||
#[UsePolicy(InvoiceReportPolicy::class)] |
|
||||
class InvoiceReport extends Model |
|
||||
{ |
|
||||
public static function boot(): void |
|
||||
{ |
|
||||
self::boot(); |
|
||||
static::creating(fn (InvoiceReport $invoiceReport) => throw new BadMethodCallException('Cannot create invoice report from here, use event instead.')); |
|
||||
static::deleting(fn (InvoiceReport $invoiceReport) => throw new BadMethodCallException('Cannot delete invoice report.')); |
|
||||
static::updating(fn (InvoiceReport $invoiceReport) => throw new BadMethodCallException('Cannot update invoice report.')); |
|
||||
} |
|
||||
|
|
||||
protected $casts = [ |
|
||||
'amount' => MoneyCurrency::class, |
|
||||
'paid_amount' => MoneyCurrency::class, |
|
||||
'issued_at' => 'datetime', |
|
||||
'paid_at' => 'datetime', |
|
||||
'status' => InvoiceStatus::class, |
|
||||
]; |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Models; |
|
||||
|
|
||||
use App\Domains\Finance\Casts\MoneyCurrency; |
|
||||
use App\Domains\Finance\Enums\PaymentDirection; |
|
||||
use App\Domains\Finance\Enums\PaymentStatus; |
|
||||
use App\Domains\Finance\Policies\PaymentPolicy; |
|
||||
use App\Domains\System\Traits\Model\HasPublicUlid; |
|
||||
use Database\Factories\Finance\PaymentFactory; |
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable; |
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy; |
|
||||
use Illuminate\Database\Eloquent\Factories\Factory; |
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
|
||||
use Illuminate\Database\Eloquent\Model; |
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo; |
|
||||
|
|
||||
#[Fillable([ |
|
||||
'virtual_account', |
|
||||
'bank_ref_id', |
|
||||
'amount', |
|
||||
'valid_until', |
|
||||
'direction', |
|
||||
'status', |
|
||||
'transaction_id', |
|
||||
])] |
|
||||
#[UsePolicy(PaymentPolicy::class)] |
|
||||
class Payment extends Model |
|
||||
{ |
|
||||
use HasFactory; |
|
||||
use HasPublicUlid; |
|
||||
|
|
||||
protected $casts = [ |
|
||||
'amount' => MoneyCurrency::class, |
|
||||
'valid_until' => 'datetime_immutable', |
|
||||
'direction' => PaymentDirection::class, |
|
||||
'status' => PaymentStatus::class, |
|
||||
]; |
|
||||
|
|
||||
protected static function newFactory(): Factory |
|
||||
{ |
|
||||
return PaymentFactory::new(); |
|
||||
} |
|
||||
|
|
||||
public function transaction(): BelongsTo |
|
||||
{ |
|
||||
return $this->belongsTo(Invoice::class); |
|
||||
} |
|
||||
} |
|
||||
@ -1,24 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Models; |
|
||||
|
|
||||
use App\Domains\Finance\Policies\ProductMappingPolicy; |
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable; |
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy; |
|
||||
use Illuminate\Database\Eloquent\Model; |
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo; |
|
||||
|
|
||||
#[Fillable([ |
|
||||
'code', |
|
||||
'name', |
|
||||
'chart_of_account_id', |
|
||||
'client_id', |
|
||||
])] |
|
||||
#[UsePolicy(ProductMappingPolicy::class)] |
|
||||
class ProductMapping extends Model |
|
||||
{ |
|
||||
public function chartOfAccount(): BelongsTo |
|
||||
{ |
|
||||
return $this->belongsTo(ChartOfAccount::class); |
|
||||
} |
|
||||
} |
|
||||
@ -1,47 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Models; |
|
||||
|
|
||||
use App\Domains\Finance\Casts\MoneyCurrency; |
|
||||
use App\Domains\Finance\Enums\InvoiceStatus; |
|
||||
use App\Domains\Finance\Policies\StudentInvoiceReportPolicy; |
|
||||
use BadMethodCallException; |
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable; |
|
||||
use Illuminate\Database\Eloquent\Attributes\UsePolicy; |
|
||||
use Illuminate\Database\Eloquent\Model; |
|
||||
|
|
||||
#[Fillable([ |
|
||||
'invoice_id', |
|
||||
'student_id', |
|
||||
'name', |
|
||||
'faculty_id', |
|
||||
'faculty_name', |
|
||||
'study_program_id', |
|
||||
'study_program_name', |
|
||||
'term_id', |
|
||||
'term_name', |
|
||||
'amount', |
|
||||
'paid_amount', |
|
||||
'issued_at', |
|
||||
'paid_at', |
|
||||
'status', |
|
||||
])] |
|
||||
#[UsePolicy(StudentInvoiceReportPolicy::class)] |
|
||||
class StudentInvoiceReport extends Model |
|
||||
{ |
|
||||
public static function boot(): void |
|
||||
{ |
|
||||
self::boot(); |
|
||||
static::creating(fn (InvoiceReport $invoiceReport) => throw new BadMethodCallException('Cannot create invoice report from here, use event instead.')); |
|
||||
static::deleting(fn (InvoiceReport $invoiceReport) => throw new BadMethodCallException('Cannot delete invoice report.')); |
|
||||
static::updating(fn (InvoiceReport $invoiceReport) => throw new BadMethodCallException('Cannot update invoice report.')); |
|
||||
} |
|
||||
|
|
||||
protected $casts = [ |
|
||||
'amount' => MoneyCurrency::class, |
|
||||
'paid_amount' => MoneyCurrency::class, |
|
||||
'issued_at' => 'datetime', |
|
||||
'paid_at' => 'datetime', |
|
||||
'status' => InvoiceStatus::class, |
|
||||
]; |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Policies; |
|
||||
|
|
||||
use App\Domains\Finance\Models\ChartOfAccount; |
|
||||
use App\Domains\Identity\Models\User; |
|
||||
|
|
||||
class ChartOfAccountPolicy |
|
||||
{ |
|
||||
/** |
|
||||
* Determine whether the user can view any models. |
|
||||
*/ |
|
||||
public function viewAny(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('chart-of-account.viewAny'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can view the model. |
|
||||
*/ |
|
||||
public function view(User $user, ChartOfAccount $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('chart-of-account.view'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can create models. |
|
||||
*/ |
|
||||
public function create(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('chart-of-account.create'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can update the model. |
|
||||
*/ |
|
||||
public function update(User $user, ChartOfAccount $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('chart-of-account.update'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can delete the model. |
|
||||
*/ |
|
||||
public function delete(User $user, ChartOfAccount $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('chart-of-account.delete'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Policies; |
|
||||
|
|
||||
use App\Domains\Finance\Models\Invoice; |
|
||||
use App\Domains\Identity\Models\User; |
|
||||
|
|
||||
class InvoicePolicy |
|
||||
{ |
|
||||
/** |
|
||||
* Determine whether the user can view any models. |
|
||||
*/ |
|
||||
public function viewAny(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice.viewAny'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can view the model. |
|
||||
*/ |
|
||||
public function view(User $user, Invoice $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice.view'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can create models. |
|
||||
*/ |
|
||||
public function create(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice.create'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can update the model. |
|
||||
*/ |
|
||||
public function update(User $user, Invoice $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice.update'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can delete the model. |
|
||||
*/ |
|
||||
public function delete(User $user, Invoice $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice.delete'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Policies; |
|
||||
|
|
||||
use App\Domains\Finance\Models\InvoiceReport; |
|
||||
use App\Domains\Identity\Models\User; |
|
||||
|
|
||||
class InvoiceReportPolicy |
|
||||
{ |
|
||||
/** |
|
||||
* Determine whether the user can view any models. |
|
||||
*/ |
|
||||
public function viewAny(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice-report.viewAny'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can view the model. |
|
||||
*/ |
|
||||
public function view(User $user, InvoiceReport $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('invoice-report.view'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can create models. |
|
||||
*/ |
|
||||
public function create(User $user): bool |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can update the model. |
|
||||
*/ |
|
||||
public function update(User $user, InvoiceReport $model): bool |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can delete the model. |
|
||||
*/ |
|
||||
public function delete(User $user, InvoiceReport $model): bool |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Policies; |
|
||||
|
|
||||
use App\Domains\Finance\Models\Payment; |
|
||||
use App\Domains\Identity\Models\User; |
|
||||
|
|
||||
class PaymentPolicy |
|
||||
{ |
|
||||
/** |
|
||||
* Determine whether the user can view any models. |
|
||||
*/ |
|
||||
public function viewAny(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('payment.viewAny'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can view the model. |
|
||||
*/ |
|
||||
public function view(User $user, Payment $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('payment.view'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can create models. |
|
||||
*/ |
|
||||
public function create(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('payment.create'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can update the model. |
|
||||
*/ |
|
||||
public function update(User $user, Payment $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('payment.update'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can delete the model. |
|
||||
*/ |
|
||||
public function delete(User $user, Payment $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('payment.delete'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Policies; |
|
||||
|
|
||||
use App\Domains\Finance\Models\ProductMapping; |
|
||||
use App\Domains\Identity\Models\User; |
|
||||
|
|
||||
class ProductMappingPolicy |
|
||||
{ |
|
||||
/** |
|
||||
* Determine whether the user can view any models. |
|
||||
*/ |
|
||||
public function viewAny(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('product-mapping.viewAny'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can view the model. |
|
||||
*/ |
|
||||
public function view(User $user, ProductMapping $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('product-mapping.view'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can create models. |
|
||||
*/ |
|
||||
public function create(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('product-mapping.create'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can update the model. |
|
||||
*/ |
|
||||
public function update(User $user, ProductMapping $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('product-mapping.update'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can delete the model. |
|
||||
*/ |
|
||||
public function delete(User $user, ProductMapping $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('product-mapping.delete'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,49 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Policies; |
|
||||
|
|
||||
use App\Domains\Finance\Models\StudentInvoiceReport; |
|
||||
use App\Domains\Identity\Models\User; |
|
||||
|
|
||||
class StudentInvoiceReportPolicy |
|
||||
{ |
|
||||
/** |
|
||||
* Determine whether the user can view any models. |
|
||||
*/ |
|
||||
public function viewAny(User $user): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('student-invoice-report.viewAny'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can view the model. |
|
||||
*/ |
|
||||
public function view(User $user, StudentInvoiceReport $model): bool |
|
||||
{ |
|
||||
return $user->hasPermissionTo('student-invoice-report.view'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can create models. |
|
||||
*/ |
|
||||
public function create(User $user): bool |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can update the model. |
|
||||
*/ |
|
||||
public function update(User $user, StudentInvoiceReport $model): bool |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether the user can delete the model. |
|
||||
*/ |
|
||||
public function delete(User $user, StudentInvoiceReport $model): bool |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Providers; |
|
||||
|
|
||||
use App\Domains\System\Traits\Provider\RegistersDomainEvents; |
|
||||
use Illuminate\Support\ServiceProvider; |
|
||||
|
|
||||
class FinanceServiceProvider extends ServiceProvider |
|
||||
{ |
|
||||
use RegistersDomainEvents; |
|
||||
|
|
||||
protected array $listen = []; |
|
||||
|
|
||||
public function register(): void |
|
||||
{ |
|
||||
$this->app->register(RelationshipServiceProvider::class); |
|
||||
} |
|
||||
|
|
||||
public function boot(): void |
|
||||
{ |
|
||||
$this->registerEvents(); |
|
||||
} |
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Providers; |
|
||||
|
|
||||
use Illuminate\Support\ServiceProvider; |
|
||||
|
|
||||
class RelationshipServiceProvider extends ServiceProvider |
|
||||
{ |
|
||||
/** |
|
||||
* Boot cross-domain runtime relationships. |
|
||||
* |
|
||||
* This provider is strictly dedicated to runtime, decoupled cross-domain |
|
||||
* relationship definitions. Use Model::resolveRelationUsing() here to wire |
|
||||
* explicit polymorphic or foreign-key macros between models that live in |
|
||||
* different domains — without introducing a hard compile-time dependency |
|
||||
* between those domains/ |
|
||||
* |
|
||||
* Do NOT add route registrations, bindings, event listeners, or any other |
|
||||
* bootstrapping logic here. Keep this file focused on relationships only. |
|
||||
* |
|
||||
* Example: |
|
||||
* |
|
||||
* Order::resolveRelationUsing('customer', fn (Order $order) => |
|
||||
* $order->belongsTo(Customer::class, 'customer_id') |
|
||||
* ); |
|
||||
*/ |
|
||||
public function boot(): void |
|
||||
{ |
|
||||
// Register cross-domain relationships below. |
|
||||
} |
|
||||
} |
|
||||
@ -1,79 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Schemas\Invoice; |
|
||||
|
|
||||
use App\Domains\Academic\Queries\Selection\SelectFacultyQuery; |
|
||||
use App\Domains\Academic\Queries\Selection\SelectStudyProgramQuery; |
|
||||
use App\Domains\Academic\Queries\Selection\SelectTermQuery; |
|
||||
use App\Domains\Finance\Support\Schemas\InvoiceSchema; |
|
||||
use App\UI\Enums\InputType; |
|
||||
use App\UI\Support\Schemas\InputSchema; |
|
||||
|
|
||||
class StudentInvoiceSchema |
|
||||
{ |
|
||||
public static function make(): InvoiceSchema |
|
||||
{ |
|
||||
return InvoiceSchema::make() |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('student_id') |
|
||||
->label(__('domains/finance/field.invoice.detail.student_id')) |
|
||||
->type(InputType::TEXTLINE) |
|
||||
->rules(['required']) |
|
||||
) |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('student_name') |
|
||||
->label(__('domains/finance/field.invoice.detail.student_name')) |
|
||||
->type(InputType::TEXTLINE) |
|
||||
->rules(['required', 'string']) |
|
||||
) |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('faculty') |
|
||||
->label(__('domains/finance/field.invoice.detail.faculty')) |
|
||||
->type(InputType::SELECT) |
|
||||
->rules(['required', 'string']) |
|
||||
->select2() |
|
||||
->live() |
|
||||
->options(fn () => SelectFacultyQuery::fetch()) |
|
||||
) |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('study_program') |
|
||||
->label(__('domains/finance/field.invoice.detail.study_program')) |
|
||||
->type(InputType::SELECT) |
|
||||
->rules(['required', 'string']) |
|
||||
->select2() |
|
||||
->dependsOn('faculty') |
|
||||
->setContextKeys(['faculty']) |
|
||||
->options(fn ($context) => SelectStudyProgramQuery::fetch($context)) |
|
||||
) |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('term_entry') |
|
||||
->label(__('domains/finance/field.invoice.detail.term_entry')) |
|
||||
->type(InputType::SELECT) |
|
||||
->rules(['required']) |
|
||||
->options(fn () => SelectTermQuery::fetch()) |
|
||||
->select2() |
|
||||
) |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('semester') |
|
||||
->label(__('domains/finance/field.invoice.detail.semester')) |
|
||||
->type(InputType::SELECT) |
|
||||
->rules(['required']) |
|
||||
->options(array_combine(range(1, 13), range(1, 13))) |
|
||||
->select2() |
|
||||
) |
|
||||
->addInput( |
|
||||
InputSchema::make() |
|
||||
->key('fee_type') |
|
||||
->label(__('domains/finance/field.invoice.detail.fee_type')) |
|
||||
->type(InputType::SELECT) |
|
||||
->rules(['required']) |
|
||||
->select2() |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
@ -1,25 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Domains\Finance\Support\Schemas; |
|
||||
|
|
||||
use App\UI\Support\Schemas\AbstractGroupSchema; |
|
||||
|
|
||||
class InvoiceSchema extends AbstractGroupSchema |
|
||||
{ |
|
||||
protected bool $coaVisibility = false; |
|
||||
|
|
||||
/** |
|
||||
* Fluent setter for COA visibility. |
|
||||
*/ |
|
||||
public function withCoaVisibility(bool $visible = true): static |
|
||||
{ |
|
||||
$this->coaVisibility = $visible; |
|
||||
|
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
public function isCoaVisible(): bool |
|
||||
{ |
|
||||
return $this->coaVisibility; |
|
||||
} |
|
||||
} |
|
||||
@ -1,8 +1,8 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
namespace App\Domains\Finance\Casts; |
namespace App\Domains\System\Casts; |
||||
|
|
||||
use App\Domains\Finance\Support\ValueObjects\Money; |
use App\Domains\System\Support\ValueObjects\Money; |
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes; |
use Illuminate\Contracts\Database\Eloquent\CastsAttributes; |
||||
use Illuminate\Database\Eloquent\Model; |
use Illuminate\Database\Eloquent\Model; |
||||
use InvalidArgumentException; |
use InvalidArgumentException; |
||||
@ -1,6 +1,6 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
namespace App\Domains\Finance\Support\ValueObjects; |
namespace App\Domains\System\Support\ValueObjects; |
||||
|
|
||||
use InvalidArgumentException; |
use InvalidArgumentException; |
||||
use NumberFormatter; |
use NumberFormatter; |
||||
@ -0,0 +1,21 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace App\Http\Controllers\Api\V1\Lookup; |
||||
|
|
||||
|
use App\Domains\Academic\Queries\Lookup\TermLookup; |
||||
|
use App\Http\Controllers\Controller; |
||||
|
use App\Http\Resources\LookupResource; |
||||
|
use Illuminate\Http\Request; |
||||
|
|
||||
|
class TermLookupController extends Controller |
||||
|
{ |
||||
|
public function __invoke(Request $request, TermLookup $lookup) |
||||
|
{ |
||||
|
$terms = $lookup->fetch()->map(fn ($term) => (object) [ |
||||
|
'id' => $term, |
||||
|
'text' => $term, |
||||
|
]); |
||||
|
|
||||
|
return LookupResource::collection($terms); |
||||
|
} |
||||
|
} |
||||
@ -1,32 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Controllers\Web\Finance; |
|
||||
|
|
||||
use App\Attributes\LayoutData; |
|
||||
use App\Attributes\Seo; |
|
||||
use App\Http\Controllers\Controller; |
|
||||
use App\Http\DataTables\Finance\ChartOfAccountDataTable; |
|
||||
use Illuminate\Http\Request; |
|
||||
|
|
||||
class ChartOfAccountController extends Controller |
|
||||
{ |
|
||||
/** |
|
||||
* Handle the incoming request. |
|
||||
*/ |
|
||||
#[Seo( |
|
||||
title: 'domains/finance/seo.coa.title', |
|
||||
description: 'domains/finance/seo.coa.description', |
|
||||
keywords: 'domains/finance/seo.coa.keywords' |
|
||||
)] |
|
||||
#[LayoutData( |
|
||||
header: 'domains/finance/seo.coa.title', |
|
||||
breadcrumbs: [ |
|
||||
'ui/menu.dashboard' => 'dashboard', |
|
||||
'domains/finance/seo.coa.title' => '', |
|
||||
], |
|
||||
)] |
|
||||
public function __invoke(ChartOfAccountDataTable $dataTable) |
|
||||
{ |
|
||||
return $dataTable->render('pages.finance.chart-of-account.index'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,32 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Controllers\Web\Finance; |
|
||||
|
|
||||
use App\Attributes\LayoutData; |
|
||||
use App\Attributes\Seo; |
|
||||
use App\Http\Controllers\Controller; |
|
||||
use App\Http\DataTables\Finance\InvoiceDataTable; |
|
||||
use Illuminate\Http\Request; |
|
||||
|
|
||||
class InvoiceController extends Controller |
|
||||
{ |
|
||||
/** |
|
||||
* Handle the incoming request. |
|
||||
*/ |
|
||||
#[Seo( |
|
||||
title: 'domains/finance/seo.invoice.title', |
|
||||
description: 'domains/finance/seo.invoice.description', |
|
||||
keywords: 'domains/finance/seo.invoice.keywords' |
|
||||
)] |
|
||||
#[LayoutData( |
|
||||
header: 'domains/finance/seo.invoice.title', |
|
||||
breadcrumbs: [ |
|
||||
'ui/menu.dashboard' => 'dashboard', |
|
||||
'domains/finance/seo.invoice.title' => '', |
|
||||
], |
|
||||
)] |
|
||||
public function __invoke(InvoiceDataTable $dataTable) |
|
||||
{ |
|
||||
return $dataTable->render('pages.finance.invoice.index'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,32 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\Controllers\Web\Finance; |
|
||||
|
|
||||
use App\Attributes\LayoutData; |
|
||||
use App\Attributes\Seo; |
|
||||
use App\Http\Controllers\Controller; |
|
||||
use App\Http\DataTables\Finance\ProductMappingDataTable; |
|
||||
use Illuminate\Http\Request; |
|
||||
|
|
||||
class ProductMappingController extends Controller |
|
||||
{ |
|
||||
/** |
|
||||
* Handle the incoming request. |
|
||||
*/ |
|
||||
#[Seo( |
|
||||
title: 'domains/finance/seo.product_mapping.title', |
|
||||
description: 'domains/finance/seo.product_mapping.description', |
|
||||
keywords: 'domains/finance/seo.product_mapping.keywords' |
|
||||
)] |
|
||||
#[LayoutData( |
|
||||
header: 'domains/finance/seo.product_mapping.title', |
|
||||
breadcrumbs: [ |
|
||||
'ui/menu.dashboard' => 'dashboard', |
|
||||
'domains/finance/seo.product_mapping.title' => '', |
|
||||
], |
|
||||
)] |
|
||||
public function __invoke(ProductMappingDataTable $dataTable) |
|
||||
{ |
|
||||
return $dataTable->render('pages.finance.product-mapping.index'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,143 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\DataTables\Finance; |
|
||||
|
|
||||
use App\Domains\Finance\Models\ChartOfAccount; |
|
||||
use Illuminate\Database\Eloquent\Builder as QueryBuilder; |
|
||||
use Yajra\DataTables\EloquentDataTable; |
|
||||
use Yajra\DataTables\Html\Builder as HtmlBuilder; |
|
||||
use Yajra\DataTables\Html\Button; |
|
||||
use Yajra\DataTables\Html\Column; |
|
||||
use Yajra\DataTables\Services\DataTable; |
|
||||
|
|
||||
class ChartOfAccountDataTable extends DataTable |
|
||||
{ |
|
||||
/** |
|
||||
* Build the DataTable class. |
|
||||
* |
|
||||
* @param QueryBuilder<ChartOfAccount> $query Results from query() method. |
|
||||
*/ |
|
||||
public function dataTable(QueryBuilder $query): EloquentDataTable |
|
||||
{ |
|
||||
return (new EloquentDataTable($query)) |
|
||||
->editColumn('status', fn (ChartOfAccount $coa) => view('components.badge', [ |
|
||||
'label' => $coa->status->label(), |
|
||||
'variant' => $coa->status->variant(), |
|
||||
])) |
|
||||
->editColumn('classification', fn (ChartOfAccount $coa) => $coa->classification->label()) |
|
||||
->addColumn( |
|
||||
'action', |
|
||||
fn ($coa) => view('components.datatables.action-button', [ |
|
||||
'log' => true, |
|
||||
'edit' => [ |
|
||||
'modal' => 'chartofaccount-form-modal', |
|
||||
'permission' => auth()->user()->can('update', $coa), |
|
||||
], |
|
||||
'delete' => [ |
|
||||
'url' => null, |
|
||||
'title' => __('ui/button.delete'), |
|
||||
'message' => __('ui/confirmation.delete', ['resource' => __('resources.chart_of_account')]), |
|
||||
'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.chart_of_account')]), |
|
||||
'permission' => auth()->user()->can('delete', $coa), |
|
||||
], |
|
||||
'table_name' => 'chartofaccount-table', |
|
||||
'id' => $coa->ulid, |
|
||||
]) |
|
||||
) |
|
||||
->rawColumns(['action']) |
|
||||
->addIndexColumn(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the query source of dataTable. |
|
||||
* |
|
||||
* @return QueryBuilder<ChartOfAccount> |
|
||||
*/ |
|
||||
public function query(ChartOfAccount $model): QueryBuilder |
|
||||
{ |
|
||||
return $model->newQuery(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Optional method if you want to use the html builder. |
|
||||
*/ |
|
||||
public function html(): HtmlBuilder |
|
||||
{ |
|
||||
return $this->builder() |
|
||||
->setTableId('chartofaccount-table') |
|
||||
->columns($this->getColumns()) |
|
||||
->minifiedAjax() |
|
||||
->orderBy(-1) |
|
||||
->layout([ |
|
||||
'topStart' => [ |
|
||||
'rowClass' => 'row gap-1', |
|
||||
'className' => 'col-md-auto me-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-start align-items-center align-items-md-start gap-1', |
|
||||
'features' => ['buttons', 'pageLength'], |
|
||||
], |
|
||||
'topEnd' => [ |
|
||||
'className' => 'col-md-auto ms-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-end align-items-center align-items-md-start gap-1', |
|
||||
'features' => ['search'], |
|
||||
], |
|
||||
|
|
||||
'bottomStart' => 'info', |
|
||||
'bottomEnd' => 'paging', |
|
||||
]) |
|
||||
->parameters([ |
|
||||
'language' => [ |
|
||||
'search' => '', |
|
||||
'searchPlaceholder' => __('ui/button.lookup'), |
|
||||
], |
|
||||
'fixedColumns' => [ |
|
||||
'start' => 2, |
|
||||
], |
|
||||
'scrollX' => true, |
|
||||
'scrollCollapse' => true, |
|
||||
'responsive' => true, |
|
||||
]) |
|
||||
->buttons([ |
|
||||
Button::make('add') |
|
||||
->action('javascript:void(0)') |
|
||||
->attr(['data-coreui-toggle' => 'modal', 'data-coreui-target' => '#chartofaccount-form-modal']) |
|
||||
->text(svg('tabler-plus', ['width' => 16, 'height' => 16])->toHtml()) |
|
||||
->addClass('btn-sm'), |
|
||||
Button::make('reload') |
|
||||
->text(svg('tabler-reload', ['width' => 16, 'height' => 16])->toHtml()) |
|
||||
->addClass('btn-sm'), |
|
||||
]); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the dataTable columns definition. |
|
||||
*/ |
|
||||
public function getColumns(): array |
|
||||
{ |
|
||||
return [ |
|
||||
Column::computed('DT_RowIndex') |
|
||||
->width(10) |
|
||||
->title('#'), |
|
||||
Column::make('code') |
|
||||
->title(__('domains/finance/field.coa.code')), |
|
||||
Column::make('name') |
|
||||
->title(__('domains/finance/field.coa.name')), |
|
||||
Column::make('classification') |
|
||||
->title(__('domains/finance/field.coa.classification')), |
|
||||
Column::make('status') |
|
||||
->width(100) |
|
||||
->title(__('domains/finance/field.coa.status')), |
|
||||
Column::computed('action') |
|
||||
->title(__('ui/label.actions')) |
|
||||
->exportable(false) |
|
||||
->printable(false) |
|
||||
->width(60) |
|
||||
->addClass('text-center'), |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the filename for export. |
|
||||
*/ |
|
||||
protected function filename(): string |
|
||||
{ |
|
||||
return 'ChartOfAccount_'.date('YmdHis'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,115 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\DataTables\Finance; |
|
||||
|
|
||||
use App\Domains\Finance\Models\Invoice; |
|
||||
use Illuminate\Database\Eloquent\Builder as QueryBuilder; |
|
||||
use Yajra\DataTables\EloquentDataTable; |
|
||||
use Yajra\DataTables\Html\Builder as HtmlBuilder; |
|
||||
use Yajra\DataTables\Html\Button; |
|
||||
use Yajra\DataTables\Html\Column; |
|
||||
use Yajra\DataTables\Services\DataTable; |
|
||||
|
|
||||
class InvoiceDataTable extends DataTable |
|
||||
{ |
|
||||
/** |
|
||||
* Build the DataTable class. |
|
||||
* |
|
||||
* @param QueryBuilder<Invoice> $query Results from query() method. |
|
||||
*/ |
|
||||
public function dataTable(QueryBuilder $query): EloquentDataTable |
|
||||
{ |
|
||||
return (new EloquentDataTable($query)) |
|
||||
->addColumn('action', 'invoice.action') |
|
||||
->setRowId('id'); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the query source of dataTable. |
|
||||
* |
|
||||
* @return QueryBuilder<Invoice> |
|
||||
*/ |
|
||||
public function query(Invoice $model): QueryBuilder |
|
||||
{ |
|
||||
return $model->newQuery(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Optional method if you want to use the html builder. |
|
||||
*/ |
|
||||
public function html(): HtmlBuilder |
|
||||
{ |
|
||||
return $this->builder() |
|
||||
->setTableId('invoice-table') |
|
||||
->columns($this->getColumns()) |
|
||||
->minifiedAjax() |
|
||||
->orderBy(-1) |
|
||||
->layout([ |
|
||||
'topStart' => [ |
|
||||
'rowClass' => 'row gap-1', |
|
||||
'className' => 'col-md-auto me-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-start align-items-center align-items-md-start gap-1', |
|
||||
'features' => ['buttons', 'pageLength'], |
|
||||
], |
|
||||
'topEnd' => [ |
|
||||
'className' => 'col-md-auto ms-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-end align-items-center align-items-md-start gap-1', |
|
||||
'features' => ['search'], |
|
||||
], |
|
||||
|
|
||||
'bottomStart' => 'info', |
|
||||
'bottomEnd' => 'paging', |
|
||||
]) |
|
||||
->parameters([ |
|
||||
'language' => [ |
|
||||
'search' => '', |
|
||||
'searchPlaceholder' => __('ui/button.lookup'), |
|
||||
], |
|
||||
'fixedColumns' => [ |
|
||||
'start' => 2, |
|
||||
], |
|
||||
'scrollX' => true, |
|
||||
'scrollCollapse' => true, |
|
||||
'responsive' => true, |
|
||||
]) |
|
||||
->buttons([ |
|
||||
Button::make('add') |
|
||||
->action('javascript:void(0)') |
|
||||
->attr(['data-coreui-toggle' => 'modal', 'data-coreui-target' => '#invoice-form-modal']) |
|
||||
->text(svg('tabler-plus', ['width' => 16, 'height' => 16])->toHtml()) |
|
||||
->addClass('btn-sm'), |
|
||||
Button::make('reload') |
|
||||
->text(svg('tabler-reload', ['width' => 16, 'height' => 16])->toHtml()) |
|
||||
->addClass('btn-sm'), |
|
||||
]); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the dataTable columns definition. |
|
||||
*/ |
|
||||
public function getColumns(): array |
|
||||
{ |
|
||||
return [ |
|
||||
Column::computed('DT_RowIndex') |
|
||||
->width(10) |
|
||||
->title('#'), |
|
||||
Column::make('name') |
|
||||
->title(__('domains/finance/field.invoice.name')), |
|
||||
Column::make('type') |
|
||||
->title(__('domains/finance/field.invoice.type')), |
|
||||
Column::make('amount') |
|
||||
->title(__('domains/finance/field.invoice.amount')), |
|
||||
Column::make('client.name') |
|
||||
->title(__('domains/finance/field.invoice.client_name')), |
|
||||
Column::make('status') |
|
||||
->width(100) |
|
||||
->title(__('domains/finance/field.invoice.status')), |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the filename for export. |
|
||||
*/ |
|
||||
protected function filename(): string |
|
||||
{ |
|
||||
return 'Invoice_'.date('YmdHis'); |
|
||||
} |
|
||||
} |
|
||||
@ -1,137 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Http\DataTables\Finance; |
|
||||
|
|
||||
use App\Domains\Finance\Models\ProductMapping; |
|
||||
use Illuminate\Database\Eloquent\Builder as QueryBuilder; |
|
||||
use Yajra\DataTables\EloquentDataTable; |
|
||||
use Yajra\DataTables\Html\Builder as HtmlBuilder; |
|
||||
use Yajra\DataTables\Html\Button; |
|
||||
use Yajra\DataTables\Html\Column; |
|
||||
use Yajra\DataTables\Services\DataTable; |
|
||||
|
|
||||
class ProductMappingDataTable extends DataTable |
|
||||
{ |
|
||||
/** |
|
||||
* Build the DataTable class. |
|
||||
* |
|
||||
* @param QueryBuilder<ProductMapping> $query Results from query() method. |
|
||||
*/ |
|
||||
public function dataTable(QueryBuilder $query): EloquentDataTable |
|
||||
{ |
|
||||
return (new EloquentDataTable($query)) |
|
||||
->addColumn( |
|
||||
'action', |
|
||||
fn ($productMapping) => view('components.datatables.action-button', [ |
|
||||
'log' => true, |
|
||||
'edit' => [ |
|
||||
'modal' => 'product-mapping-form-modal', |
|
||||
'permission' => auth()->user()->can('update', $productMapping), |
|
||||
], |
|
||||
'delete' => [ |
|
||||
'url' => null, |
|
||||
'title' => __('ui/button.delete'), |
|
||||
'message' => __('ui/confirmation.delete', ['resource' => __('resources.product_mapping')]), |
|
||||
'success_message' => __('ui/crud.success.deleted', ['resource' => __('resources.product_mapping')]), |
|
||||
'permission' => auth()->user()->can('delete', $productMapping), |
|
||||
], |
|
||||
'table_name' => 'productmapping-table', |
|
||||
'id' => $productMapping->ulid, |
|
||||
]) |
|
||||
) |
|
||||
->rawColumns(['action']) |
|
||||
->addIndexColumn(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the query source of dataTable. |
|
||||
* |
|
||||
* @return QueryBuilder<ProductMapping> |
|
||||
*/ |
|
||||
public function query(ProductMapping $model): QueryBuilder |
|
||||
{ |
|
||||
return $model->newQuery(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Optional method if you want to use the html builder. |
|
||||
*/ |
|
||||
public function html(): HtmlBuilder |
|
||||
{ |
|
||||
return $this->builder() |
|
||||
->setTableId('productmapping-table') |
|
||||
->columns($this->getColumns()) |
|
||||
->minifiedAjax() |
|
||||
->orderBy(-1) |
|
||||
->layout([ |
|
||||
'topStart' => [ |
|
||||
'rowClass' => 'row gap-1', |
|
||||
'className' => 'col-md-auto me-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-start align-items-center align-items-md-start gap-1', |
|
||||
'features' => ['buttons', 'pageLength'], |
|
||||
], |
|
||||
'topEnd' => [ |
|
||||
'className' => 'col-md-auto ms-auto d-flex flex-sm-row flex-column justify-content-center justify-content-md-end align-items-center align-items-md-start gap-1', |
|
||||
'features' => ['search'], |
|
||||
], |
|
||||
|
|
||||
'bottomStart' => 'info', |
|
||||
'bottomEnd' => 'paging', |
|
||||
]) |
|
||||
->parameters([ |
|
||||
'language' => [ |
|
||||
'search' => '', |
|
||||
'searchPlaceholder' => __('ui/button.lookup'), |
|
||||
], |
|
||||
'fixedColumns' => [ |
|
||||
'start' => 2, |
|
||||
], |
|
||||
'scrollX' => true, |
|
||||
'scrollCollapse' => true, |
|
||||
'responsive' => true, |
|
||||
]) |
|
||||
->buttons([ |
|
||||
Button::make('add') |
|
||||
->action('javascript:void(0)') |
|
||||
->attr(['data-coreui-toggle' => 'modal', 'data-coreui-target' => '#product-mapping-form-modal']) |
|
||||
->text(svg('tabler-plus', ['width' => 16, 'height' => 16])->toHtml()) |
|
||||
->addClass('btn-sm'), |
|
||||
Button::make('reload') |
|
||||
->text(svg('tabler-reload', ['width' => 16, 'height' => 16])->toHtml()) |
|
||||
->addClass('btn-sm'), |
|
||||
]); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the dataTable columns definition. |
|
||||
*/ |
|
||||
public function getColumns(): array |
|
||||
{ |
|
||||
return [ |
|
||||
Column::computed('DT_RowIndex') |
|
||||
->width(10) |
|
||||
->title('#'), |
|
||||
Column::make('code') |
|
||||
->title(__('domains/finance/field.product_mapping.code')), |
|
||||
Column::make('name') |
|
||||
->title(__('domains/finance/field.product_mapping.name')), |
|
||||
Column::make('chart_of_account.name') |
|
||||
->title(__('domains/finance/field.product_mapping.coa_name')), |
|
||||
Column::make('client.name') |
|
||||
->title(__('domains/finance/field.product_mapping.client_name')), |
|
||||
Column::computed('action') |
|
||||
->title(__('ui/label.actions')) |
|
||||
->exportable(false) |
|
||||
->printable(false) |
|
||||
->width(60) |
|
||||
->addClass('text-center'), |
|
||||
]; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the filename for export. |
|
||||
*/ |
|
||||
protected function filename(): string |
|
||||
{ |
|
||||
return 'ProductMapping_'.date('YmdHis'); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,10 @@ |
|||||
|
<?php |
||||
|
|
||||
|
|
||||
|
return [ |
||||
|
'fee_type' => [ |
||||
|
'not_defined' => 'Not Set', |
||||
|
'partially_defined' => 'Partial', |
||||
|
'completely_defined' => 'Complete', |
||||
|
], |
||||
|
]; |
||||
@ -1,38 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
use App\Domains\Finance\Enums\AccountClassification; |
|
||||
use App\Domains\Finance\Enums\InvoiceStatus; |
|
||||
use App\Domains\Finance\Enums\InvoiceType; |
|
||||
use App\Domains\Finance\Enums\PaymentDirection; |
|
||||
use App\Domains\Finance\Enums\PaymentStatus; |
|
||||
|
|
||||
return [ |
|
||||
'invoice_status' => [ |
|
||||
InvoiceStatus::PAID->value => 'Paid', |
|
||||
InvoiceStatus::PENDING->value => 'Pending', |
|
||||
InvoiceStatus::PARTIALLY_PAID->value => 'Partially Paid', |
|
||||
InvoiceStatus::OVERDUE->value => 'Overdue', |
|
||||
], |
|
||||
'invoice_type' => [ |
|
||||
InvoiceType::STUDENT_INVOICE->value => 'Student Invoice', |
|
||||
InvoiceType::VENDOR_BILL->value => 'Vendor Bill', |
|
||||
InvoiceType::CREDIT_NOTE->value => 'Credit Note', |
|
||||
], |
|
||||
'payment_status' => [ |
|
||||
PaymentStatus::PENDING->value => 'Pending', |
|
||||
PaymentStatus::SUCCESS->value => 'Success', |
|
||||
PaymentStatus::FAILED->value => 'Failed', |
|
||||
PaymentStatus::EXPIRED->value => 'Expired', |
|
||||
], |
|
||||
'payment_direction' => [ |
|
||||
PaymentDirection::RECEIPT->value => 'Receipt', |
|
||||
PaymentDirection::DISBURSEMENT->value => 'Disbursement', |
|
||||
], |
|
||||
'account_classification' => [ |
|
||||
AccountClassification::ASSET->value => 'Asset', |
|
||||
AccountClassification::LIABILITY->value => 'Liability', |
|
||||
AccountClassification::EQUITY->value => 'Equity', |
|
||||
AccountClassification::REVENUE->value => 'Revenue', |
|
||||
AccountClassification::EXPENSE->value => 'Expense', |
|
||||
], |
|
||||
]; |
|
||||
@ -1,50 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
return [ |
|
||||
'coa' => [ |
|
||||
'code' => 'Account Code', |
|
||||
'name' => 'Account Name', |
|
||||
'classification' => 'Classification', |
|
||||
'status' => 'Status', |
|
||||
'parent' => 'Derived From', |
|
||||
], |
|
||||
'invoice' => [ |
|
||||
'name' => 'Invoice Name', |
|
||||
'code' => 'Invoice Code', |
|
||||
'type' => 'Invoice Type', |
|
||||
'amount' => 'Invoice Amount', |
|
||||
'client_name' => 'Client Name', |
|
||||
'status' => 'Status', |
|
||||
'coa_name' => 'Account Name (COA)', |
|
||||
'detail' => [ |
|
||||
// Detail for Student |
|
||||
'student_name' => 'Student Name', |
|
||||
'student_id' => 'Student ID', |
|
||||
'faculty' => 'Faculty', |
|
||||
'study_program' => 'Study Program', |
|
||||
'term_entry' => 'Term Entry', |
|
||||
'fee_type' => 'Fee Type', |
|
||||
'semester' => 'Semester', |
|
||||
|
|
||||
// Vendor Bill |
|
||||
'vendor_name' => 'Vendor Name', |
|
||||
'vendor_id' => 'Vendor ID', |
|
||||
], |
|
||||
], |
|
||||
'payment' => [ |
|
||||
'virtual_account' => 'Virtual Account', |
|
||||
'bank_ref_id' => 'Bank Reference Code', |
|
||||
'bank_name' => 'Bank Name', |
|
||||
'nominal' => 'Nominal', |
|
||||
'validity' => 'Validity', |
|
||||
'payment_date' => 'Payment Date', |
|
||||
'direction' => 'Direction', |
|
||||
'status' => 'Status', |
|
||||
], |
|
||||
'product_mapping' => [ |
|
||||
'code' => 'Product Code', |
|
||||
'name' => 'Product Name', |
|
||||
'coa_name' => 'Account Name (COA)', |
|
||||
'client_name' => 'Client Name', |
|
||||
], |
|
||||
]; |
|
||||
@ -1,19 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
return [ |
|
||||
'coa' => [ |
|
||||
'title' => 'Chart of Accounts (COA) Data', |
|
||||
'description' => 'Manage chart of accounts for financial records.', |
|
||||
'keywords' => 'chart of accounts, coa, accounting, finance', |
|
||||
], |
|
||||
'invoice' => [ |
|
||||
'title' => 'Invoice Data', |
|
||||
'description' => 'Manage student payment invoices.', |
|
||||
'keywords' => 'invoice, payment, finance', |
|
||||
], |
|
||||
'product_mapping' => [ |
|
||||
'title' => 'Product Mapping Data', |
|
||||
'description' => 'Manage cost product mappings with Chart of Accounts (COA).', |
|
||||
'keywords' => 'product mapping, product, coa, finance', |
|
||||
], |
|
||||
]; |
|
||||
@ -0,0 +1,7 @@ |
|||||
|
<?php |
||||
|
|
||||
|
return [ |
||||
|
'select' => 'Select :attribute', |
||||
|
'email' => 'name@example.com', |
||||
|
'filter' => ':attribute Filter', |
||||
|
]; |
||||
@ -0,0 +1,9 @@ |
|||||
|
<?php |
||||
|
|
||||
|
return [ |
||||
|
'fee_type' => [ |
||||
|
'not_defined' => 'Not Set', |
||||
|
'partially_defined' => 'Partial', |
||||
|
'completely_defined' => 'Complete', |
||||
|
], |
||||
|
]; |
||||
@ -0,0 +1,7 @@ |
|||||
|
<?php |
||||
|
|
||||
|
return [ |
||||
|
'select' => 'Pilih :attribute', |
||||
|
'email' => 'nama@contoh.com', |
||||
|
'filter' => 'Filter :attribute', |
||||
|
]; |
||||
@ -1,25 +1,212 @@ |
|||||
import '../plugin/apexchart.js' |
|
||||
|
|
||||
export default function AlpineChart(Alpine) { |
export default function AlpineChart(Alpine) { |
||||
Alpine.directive('chart', function (el, { expression }, { evaluate, cleanup }) { |
Alpine.directive( |
||||
let config = evaluate(expression); |
"chart", |
||||
|
function (el, { expression }, { evaluateLater, cleanup }) { |
||||
|
const getContent = evaluateLater(expression); |
||||
|
|
||||
|
import("apexcharts").then(({ default: ApexCharts }) => { |
||||
|
getContent((userConfig) => { |
||||
|
if (!userConfig || typeof userConfig !== "object") return; |
||||
|
|
||||
|
// 1. Fetch live computed CSS variables directly from :root (document.documentElement)
|
||||
|
const getCoreUIColors = () => { |
||||
|
const style = getComputedStyle(document.body); |
||||
|
|
||||
|
// CoreUI v4/v5 & Bootstrap 5 theme variable names
|
||||
|
const bodyColor = |
||||
|
style.getPropertyValue("--cui-body-color").trim() || |
||||
|
style.getPropertyValue("--bs-body-color").trim() || |
||||
|
"#a6b0cf"; |
||||
|
|
||||
|
const secondaryColor = |
||||
|
style |
||||
|
.getPropertyValue("--cui-secondary-color") |
||||
|
.trim() || |
||||
|
style |
||||
|
.getPropertyValue("--bs-secondary-color") |
||||
|
.trim() || |
||||
|
"#8a93a2"; |
||||
|
|
||||
|
const borderColor = |
||||
|
style |
||||
|
.getPropertyValue("--cui-border-color") |
||||
|
.trim() || |
||||
|
style |
||||
|
.getPropertyValue( |
||||
|
"--bs-border-color-translucent", |
||||
|
) |
||||
|
.trim() || |
||||
|
style |
||||
|
.getPropertyValue("--bs-border-color") |
||||
|
.trim() || |
||||
|
"rgba(255, 255, 255, 0.08)"; |
||||
|
|
||||
|
const primaryColor = |
||||
|
style.getPropertyValue("--cui-primary").trim() || |
||||
|
style.getPropertyValue("--bs-primary").trim() || |
||||
|
"#6366f1"; |
||||
|
|
||||
|
const theme = |
||||
|
document.documentElement.getAttribute( |
||||
|
"data-coreui-theme", |
||||
|
) || |
||||
|
document.documentElement.getAttribute( |
||||
|
"data-bs-theme", |
||||
|
) || |
||||
|
"dark"; |
||||
|
|
||||
|
return { |
||||
|
bodyColor, |
||||
|
secondaryColor, |
||||
|
borderColor, |
||||
|
primaryColor, |
||||
|
theme, |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
const colors = getCoreUIColors(); |
||||
|
|
||||
|
// 2. Base Configuration explicitly overriding ApexCharts SVG text fills
|
||||
|
const baseConfig = { |
||||
|
chart: { |
||||
|
type: "line", |
||||
|
height: 360, |
||||
|
foreColor: colors.secondaryColor, // Sets default text/legend colors
|
||||
|
background: "transparent", |
||||
|
}, |
||||
|
colors: [colors.primaryColor], |
||||
|
theme: { |
||||
|
mode: colors.theme, |
||||
|
}, |
||||
|
tooltip: { |
||||
|
theme: colors.theme, |
||||
|
}, |
||||
|
grid: { |
||||
|
borderColor: colors.borderColor, |
||||
|
}, |
||||
|
xaxis: { |
||||
|
labels: { |
||||
|
style: { |
||||
|
colors: colors.secondaryColor, |
||||
|
fontSize: "12px", |
||||
|
}, |
||||
|
}, |
||||
|
axisBorder: { color: colors.borderColor }, |
||||
|
axisTicks: { color: colors.borderColor }, |
||||
|
}, |
||||
|
yaxis: { |
||||
|
labels: { |
||||
|
style: { |
||||
|
colors: colors.secondaryColor, |
||||
|
fontSize: "12px", |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
// Deep merge user options with base configuration
|
||||
|
const options = Object.assign({}, baseConfig, userConfig); |
||||
|
options.chart = Object.assign( |
||||
|
{}, |
||||
|
baseConfig.chart, |
||||
|
userConfig.chart, |
||||
|
); |
||||
|
options.theme = Object.assign( |
||||
|
{}, |
||||
|
baseConfig.theme, |
||||
|
userConfig.theme, |
||||
|
); |
||||
|
options.tooltip = Object.assign( |
||||
|
{}, |
||||
|
baseConfig.tooltip, |
||||
|
userConfig.tooltip, |
||||
|
); |
||||
|
|
||||
|
// Preserve user primary colors if explicitly provided in PHP, otherwise use CoreUI's
|
||||
|
if (!userConfig.colors) { |
||||
|
options.colors = baseConfig.colors; |
||||
|
} |
||||
|
|
||||
|
requestAnimationFrame(() => { |
||||
|
const chart = new ApexCharts(el, options); |
||||
|
chart.render(); |
||||
|
|
||||
|
// 3. Theme switch handler
|
||||
|
const observer = new MutationObserver(() => { |
||||
|
const updated = getCoreUIColors(); |
||||
|
|
||||
const chart = new window.ApexCharts(el, config); |
chart.updateOptions( |
||||
chart.render(); |
{ |
||||
|
chart: { |
||||
|
foreColor: updated.secondaryColor, |
||||
|
}, |
||||
|
theme: { mode: updated.theme }, |
||||
|
tooltip: { theme: updated.theme }, |
||||
|
grid: { borderColor: updated.borderColor }, |
||||
|
xaxis: { |
||||
|
labels: { |
||||
|
style: { |
||||
|
colors: updated.secondaryColor, |
||||
|
}, |
||||
|
}, |
||||
|
axisBorder: { |
||||
|
color: updated.borderColor, |
||||
|
}, |
||||
|
axisTicks: { |
||||
|
color: updated.borderColor, |
||||
|
}, |
||||
|
}, |
||||
|
yaxis: { |
||||
|
labels: { |
||||
|
style: { |
||||
|
colors: updated.secondaryColor, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
false, |
||||
|
true, |
||||
|
); |
||||
|
}); |
||||
|
|
||||
const event = function(event) { |
observer.observe(document.documentElement, { |
||||
const newData = event.detail |
attributes: true, |
||||
chart.updateSeries(newData.series, true, true); |
attributeFilter: [ |
||||
chart.updateOptions(newData.options, true, true); |
"data-coreui-theme", |
||||
} |
"data-bs-theme", |
||||
|
"class", |
||||
|
], |
||||
|
}); |
||||
|
|
||||
name = el.getAttribute('id'); |
// 4. Dynamic update event listener
|
||||
|
const name = el.getAttribute("id"); |
||||
|
const eventHandler = (event) => { |
||||
|
const detail = event.detail || event; |
||||
|
if (detail.series) |
||||
|
chart.updateSeries(detail.series, true); |
||||
|
if (detail.options) |
||||
|
chart.updateOptions(detail.options, true); |
||||
|
}; |
||||
|
|
||||
window.addEventListener(`chart-${name}-update`, event) |
if (name) { |
||||
|
window.addEventListener( |
||||
|
`chart-${name}-update`, |
||||
|
eventHandler, |
||||
|
); |
||||
|
} |
||||
|
|
||||
cleanup(() => { |
cleanup(() => { |
||||
chart.destroy(); |
observer.disconnect(); |
||||
window.removeEventListener(`chart-${name}-update`, event) |
if (name) |
||||
}); |
window.removeEventListener( |
||||
}) |
`chart-${name}-update`, |
||||
|
eventHandler, |
||||
|
); |
||||
|
chart.destroy(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
); |
||||
} |
} |
||||
|
|||||
@ -1,46 +1,94 @@ |
|||||
|
import Quill from "quill"; |
||||
|
import "quill/dist/quill.snow.css"; |
||||
|
|
||||
export default function alpineQuill(Alpine) { |
export default function alpineQuill(Alpine) { |
||||
Alpine.directive('quill', function (el, { expression }, { evaluate, cleanup }) { |
Alpine.directive( |
||||
const options = expression ? evaluate(expression) : {}; |
"quill", |
||||
const defaultOptions = { theme: 'snow', ...options }; |
(el, { expression }, { evaluateLater, cleanup }) => { |
||||
|
// 1. Fallback gracefully if x-quill has no parameters
|
||||
if (typeof window.Quill === 'undefined') { |
const getContent = expression |
||||
throw new Error('Quill must be loaded'); |
? evaluateLater(expression) |
||||
} |
: (cb) => cb({}); |
||||
|
|
||||
const container = document.createElement('div'); |
getContent((userOptions) => { |
||||
el.appendChild(container); |
const options = Object.assign( |
||||
const quill = new window.Quill(container, defaultOptions); |
{ |
||||
|
theme: "snow", |
||||
let isUpdating = false; |
placeholder: "Write something...", |
||||
|
}, |
||||
// 1. Text changes handler
|
typeof userOptions === "object" ? userOptions : {}, |
||||
quill.on('text-change', () => { |
); |
||||
if (isUpdating) return; |
|
||||
isUpdating = true; |
// 2. Identify or create container DIV (Quill crashes on <textarea>)
|
||||
const htmlContent = quill.root.innerHTML; |
let editorContainer; |
||||
el.value = htmlContent === '<p><br></p>' ? '' : htmlContent; |
let targetInput = el; |
||||
el.dispatchEvent(new Event('input', { bubbles: true })); |
|
||||
isUpdating = false; |
if (el.tagName === "TEXTAREA" || el.tagName === "INPUT") { |
||||
}); |
// Create a container DIV for Quill right before the textarea
|
||||
|
editorContainer = document.createElement("div"); |
||||
// 2. Element Value Getter/Setter
|
el.parentNode.insertBefore(editorContainer, el); |
||||
Object.defineProperty(el, 'value', { |
|
||||
get() { return quill.root.innerHTML; }, |
// Hide the textarea without breaking Livewire bindings
|
||||
set(newValue) { |
el.style.display = "none"; |
||||
if (isUpdating || newValue === quill.root.innerHTML) return; |
} else { |
||||
isUpdating = true; |
editorContainer = el; |
||||
quill.root.innerHTML = newValue || ''; |
} |
||||
isUpdating = false; |
|
||||
}, |
// 3. Instantiate Quill on the container DIV
|
||||
configurable: true |
const quill = new Quill(editorContainer, options); |
||||
}); |
|
||||
|
// Populate initial content from textarea / Alpine model
|
||||
quill.on('selection-change', (range) => { |
if (targetInput.value && targetInput.value !== "<p><br></p>") { |
||||
if (range == null) { |
quill.root.innerHTML = targetInput.value; |
||||
el.dispatchEvent(new Event('blur', { bubbles: true })); |
} |
||||
} |
|
||||
}); |
let isUpdating = false; |
||||
|
|
||||
cleanup(() => el.innerHTML = '') |
// 4. Sync Quill edits -> hidden input -> Livewire
|
||||
}) |
quill.on("text-change", () => { |
||||
|
if (isUpdating) return; |
||||
|
isUpdating = true; |
||||
|
|
||||
|
const html = quill.root.innerHTML; |
||||
|
const value = html === "<p><br></p>" ? "" : html; |
||||
|
|
||||
|
targetInput.value = value; |
||||
|
|
||||
|
// Dispatch input & change events on the target input so Livewire detects it
|
||||
|
targetInput.dispatchEvent( |
||||
|
new Event("input", { bubbles: true }), |
||||
|
); |
||||
|
targetInput.dispatchEvent( |
||||
|
new Event("change", { bubbles: true }), |
||||
|
); |
||||
|
|
||||
|
isUpdating = false; |
||||
|
}); |
||||
|
|
||||
|
// 5. Sync Livewire dynamic resets -> Quill
|
||||
|
const handleExternalUpdate = () => { |
||||
|
if (isUpdating) return; |
||||
|
if (targetInput.value !== quill.root.innerHTML) { |
||||
|
isUpdating = true; |
||||
|
quill.root.innerHTML = targetInput.value || ""; |
||||
|
isUpdating = false; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
targetInput.addEventListener("input", handleExternalUpdate); |
||||
|
|
||||
|
// 6. Cleanup DOM when Livewire removes the element
|
||||
|
cleanup(() => { |
||||
|
targetInput.removeEventListener( |
||||
|
"input", |
||||
|
handleExternalUpdate, |
||||
|
); |
||||
|
if (editorContainer !== el) { |
||||
|
editorContainer.remove(); |
||||
|
el.style.display = ""; |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
); |
||||
} |
} |
||||
|
|||||
@ -1,23 +1,23 @@ |
|||||
// resources/js/app.js
|
// resources/js/app.js
|
||||
import { Alpine, Livewire } from '../../vendor/livewire/livewire/dist/livewire.esm'; |
import { Alpine, Livewire } from '../../vendor/livewire/livewire/dist/livewire.esm'; |
||||
import bs from './alpine/bs'; |
import bs from './alpine/bs'; |
||||
import alpineAxios from './alpine/axios'; |
import alpineAxios from './alpine/axios'; |
||||
import alpineSelect2 from "./alpine/select2.js"; |
import alpineSelect2 from "./alpine/select2.js"; |
||||
import alpineQuill from "./alpine/quill.js"; |
import alpineQuill from "./alpine/quill.js"; |
||||
import alpineAsk from "./alpine/ask.js"; |
import alpineAsk from "./alpine/ask.js"; |
||||
import AlpineChart from "./alpine/chart.js"; |
import AlpineChart from "./alpine/chart.js"; |
||||
|
|
||||
// 1. Expose both instances globally so Blade directives can see them
|
// 1. Expose both instances globally so Blade directives can see them
|
||||
window.Alpine = Alpine; |
window.Alpine = Alpine; |
||||
window.Livewire = Livewire; |
window.Livewire = Livewire; |
||||
|
|
||||
// 2. Wrap plugin registration inside the initialization event listener
|
// 2. Wrap plugin registration inside the initialization event listener
|
||||
Alpine.plugin(bs); |
Alpine.plugin(bs); |
||||
Alpine.plugin(alpineAxios); |
Alpine.plugin(alpineAxios); |
||||
Alpine.plugin(alpineAsk); |
Alpine.plugin(alpineAsk); |
||||
Alpine.plugin(alpineSelect2); |
Alpine.plugin(alpineSelect2); |
||||
Alpine.plugin(alpineQuill); |
Alpine.plugin(alpineQuill); |
||||
Alpine.plugin(AlpineChart); |
Alpine.plugin(AlpineChart); |
||||
|
|
||||
// 3. Boot Livewire
|
// 3. Boot Livewire
|
||||
Livewire.start(); |
Livewire.start(); |
||||
|
|||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue