simedkom/app/Filament/Pages/Company/Services/CompanySaveService.php

214 lines
7.2 KiB
PHP

<?php
namespace App\Filament\Pages\Company\Services;
use App\Enums\DataChangeStatus;
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
use App\Filament\Support\CheerfulNotification;
use App\Models\Company as CompanyModel;
use App\Models\DataChangeRequest;
use App\Models\User;
use App\Notifications\BroadcastNotification;
use Filament\Actions\Action;
use Illuminate\Support\Facades\Storage;
class CompanySaveService
{
public static function handle(
?CompanyModel $existingCompany,
array $formState,
array $pageData,
array $originalDocuments,
bool $needsReview,
array $actionData = [],
): ?CompanyModel {
if ($needsReview && $existingCompany) {
self::createDataChangeRequest(
company: $existingCompany,
formState: $formState,
pageData: $pageData,
originalDocuments: $originalDocuments,
actionData: $actionData,
);
return $existingCompany;
}
return self::saveCompanyDirectly($existingCompany, $formState, $pageData);
}
private static function createDataChangeRequest(
CompanyModel $company,
array $formState,
array $pageData,
array $originalDocuments,
array $actionData,
): void {
$existingRequest = DataChangeRequest::where('entity_type', CompanyModel::class)
->where('entity_id', $company->id)
->where('status', DataChangeStatus::PENDING)
->exists();
if ($existingRequest) {
CheerfulNotification::warning(
CheerfulNotification::getByKey('data_change.existing.title'),
CheerfulNotification::getByKey('data_change.existing.body')
)->send();
return;
}
$data = array_merge($formState, $actionData);
$fieldLabels = CompanyModel::dataChangeEntryLabels();
$editableFields = [
'name',
'email',
'phone_number',
'address',
'director_name',
'director_nik',
'deed_incorporation',
'trade_license',
'tax_id_number',
'taxable_enterprise',
'annual_tax_return',
'domicile_certificate',
'profile',
];
$changedFields = [];
$oldData = [];
foreach ($editableFields as $field) {
if ($company->{$field} !== ($data[$field] ?? null)) {
$label = $fieldLabels[$field] ?? $field;
$changedFields[$label] = $data[$field] ?? null;
$oldData[$label] = $company->{$field};
}
}
$documents = [
'director_nik_docs',
'deed_incorporation_docs',
'trade_license_docs',
'tax_id_number_docs',
'taxable_enterprise_docs',
'annual_tax_return_docs',
'domicile_certificate_docs',
'profile_docs',
];
foreach ($documents as $field) {
$newValue = $pageData[$field] ?? [];
$oldValue = $originalDocuments[$field] ?? [];
// Compare as arrays since file uploads are often arrays
if (json_encode($newValue) !== json_encode($oldValue)) {
$label = $fieldLabels[$field] ?? $field;
$changedFields[$label] = $newValue;
$oldData[$label] = $oldValue;
}
}
if (empty($changedFields)) {
CheerfulNotification::info(
CheerfulNotification::getByKey('data_change.no_change.title'),
CheerfulNotification::getByKey('data_change.no_change.body')
)->send();
return;
}
$dataChangeRequest = DataChangeRequest::create([
'user_id' => auth()->id(),
'entity_type' => CompanyModel::class,
'entity_id' => $company->id,
'old_data' => $oldData,
'new_data' => $changedFields,
'change_reason' => $data['change_reason'] ?? null,
]);
CheerfulNotification::success(
CheerfulNotification::getByKey('data_change.success.title'),
CheerfulNotification::getByKey('data_change.success.body')
)->send();
User::query()
->superAdmin()
->get()
->each(function ($admin) use ($dataChangeRequest): void {
$admin->notify(new BroadcastNotification([
'title' => CheerfulNotification::getByKey('data_change.admin_notify.title'),
'body' => CheerfulNotification::getByKey('data_change.admin_notify.body', ['name' => auth()->user()->name]),
'action' => [
Action::make('view')
->label('Lihat')
->url(DataChangesResource::getUrl('view', ['record' => $dataChangeRequest->id])),
],
]));
});
}
private static function saveCompanyDirectly(?CompanyModel $existingCompany, array $formState, array $pageData): CompanyModel
{
$company = CompanyModel::updateOrCreate([
'id' => $existingCompany?->id,
], [
'user_id' => auth()->id(),
'name' => $formState['name'],
'email' => $formState['email'],
'phone_number' => $formState['phone_number'],
'address' => $formState['address'],
'director_name' => $formState['director_name'],
'director_nik' => $formState['director_nik'],
'deed_incorporation' => $formState['deed_incorporation'],
'trade_license' => $formState['trade_license'],
'tax_id_number' => $formState['tax_id_number'],
'taxable_enterprise' => $formState['taxable_enterprise'],
'annual_tax_return' => $formState['annual_tax_return'],
'domicile_certificate' => $formState['domicile_certificate'],
'profile' => $formState['profile'],
]);
$documents = [
'director_nik_docs',
'deed_incorporation_docs',
'trade_license_docs',
'tax_id_number_docs',
'taxable_enterprise_docs',
'annual_tax_return_docs',
'domicile_certificate_docs',
'profile_docs',
];
foreach ($documents as $field) {
if (empty($pageData[$field])) {
continue;
}
foreach ((array) $pageData[$field] as $filePath) {
$fullPath = Storage::disk(config('filesystems.default'))->path($filePath);
if (! file_exists($fullPath)) {
continue;
}
$company
->addMediaFromDisk($filePath, config('filesystems.default'))
->preservingOriginal()
->withCustomProperties([
'feature' => 'companies',
'date' => now()->toDateString(),
'doc_type' => str($field)
->replace('_docs', '')
->slug('-'),
])
->toMediaCollection('companies');
}
}
return $company;
}
}