feat: initial commit
This commit is contained in:
10
app/Actions/BaseAction.php
Normal file
10
app/Actions/BaseAction.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
abstract class BaseAction
|
||||
{
|
||||
abstract public function __invoke(Data $payload, \Closure $next) ;
|
||||
}
|
||||
31
app/Actions/Branch/StoreBranch.php
Normal file
31
app/Actions/Branch/StoreBranch.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Branch;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Commands\Branches\CreateBranchCommand;
|
||||
use App\DataObjects\CreateBranchDTO;
|
||||
use Exception;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class StoreBranch extends BaseAction
|
||||
{
|
||||
|
||||
public function __construct(private CreateBranchCommand $createBranchCommand) {}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __invoke(CreateBranchDTO | Data $payload, \Closure $next)
|
||||
{
|
||||
try {
|
||||
|
||||
$payload->branch = $this->createBranchCommand->execute($payload->data);
|
||||
return $next($payload);
|
||||
|
||||
} catch (Exception $exception)
|
||||
{
|
||||
throw new \LogicException('Error Storing Branch: ' . $exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
30
app/Actions/Branch/StoreBranchSeries.php
Normal file
30
app/Actions/Branch/StoreBranchSeries.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Branch;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Commands\Series\CreateSeriesCommand;
|
||||
use App\DataObjects\CreateBranchDTO;
|
||||
use App\DataObjects\CreateSeriesDTO;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class StoreBranchSeries extends BaseAction
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private CreateSeriesCommand $createSeriesCommand
|
||||
) {}
|
||||
|
||||
public function __invoke(CreateBranchDTO|Data $payload, \Closure $next)
|
||||
{
|
||||
try {
|
||||
$seriesPayload = CreateSeriesDTO::from(['branch_id' => $payload->branch->id, 'series' => $payload->data['series'], 'is_start' => true]);
|
||||
|
||||
$payload->series = $this->createSeriesCommand->execute($seriesPayload->toArray());
|
||||
|
||||
return $next($payload);
|
||||
} catch (\Exception $exception) {
|
||||
throw new \LogicException('Failed to create branch series', $exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
29
app/Actions/Transmittal/CreateTransmittal.php
Normal file
29
app/Actions/Transmittal/CreateTransmittal.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Transmittal;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Commands\Transmittal\StoreTransmittalCommand;
|
||||
use App\DataObjects\CreateTransmittalDTO;
|
||||
use Illuminate\Support\Arr;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateTransmittal extends BaseAction
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private readonly StoreTransmittalCommand $storeTransmittalCommand
|
||||
) {}
|
||||
|
||||
public function __invoke(CreateTransmittalDTO | Data $payload, \Closure $next)
|
||||
{
|
||||
try {
|
||||
$payload->transmittal = $this->storeTransmittalCommand->execute(Arr::except($payload->data, ['files']));
|
||||
|
||||
return $next($payload);
|
||||
} catch (\Exception $exception)
|
||||
{
|
||||
throw new \LogicException('Error creating transmittal: ' . $exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
63
app/Actions/Transmittal/CreateTransmittalFiles.php
Normal file
63
app/Actions/Transmittal/CreateTransmittalFiles.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Transmittal;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Commands\Transmittal\StoreCommentCommand;
|
||||
use App\Commands\Transmittal\StoreFileCommand;
|
||||
use App\Commands\Transmittal\StoreRemarkCommand;
|
||||
use App\DataObjects\CreateCommentDTO;
|
||||
use App\DataObjects\CreateFileDTO;
|
||||
use App\DataObjects\CreateRemarkDTO;
|
||||
use App\DataObjects\CreateTransmittalDTO;
|
||||
use Illuminate\Support\Arr;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateTransmittalFiles extends BaseAction
|
||||
{
|
||||
|
||||
public function __construct(
|
||||
private readonly StoreFileCommand $storeFileCommand,
|
||||
private readonly StoreCommentCommand $storeCommentCommand,
|
||||
private readonly StoreRemarkCommand $storeRemarkCommand
|
||||
) {}
|
||||
|
||||
public function __invoke(CreateTransmittalDTO | Data $payload, \Closure $next)
|
||||
{
|
||||
try {
|
||||
$files = Arr::only($payload->data, 'files');
|
||||
$filesCreated = [];
|
||||
foreach ($files as $file) {
|
||||
|
||||
//save each file
|
||||
$filePayload = new CreateFileDTO(transmittal_id: $payload->transmittal->id, description: Arr::first($file)['description']);
|
||||
$fileCreated = $this->storeFileCommand->execute($filePayload->except('file')->toArray());
|
||||
|
||||
|
||||
$comments = Arr::first($file)['comments'];
|
||||
$remarks = Arr::first($file)['remarks'];
|
||||
|
||||
//save each comments of each file
|
||||
foreach ($comments as $key => $comment) {
|
||||
$commentPayload = new CreateCommentDTO(file_id: $fileCreated->id, comment: $comment['comment']);
|
||||
$this->storeCommentCommand->execute($commentPayload->except('commentModel')->toArray());
|
||||
}
|
||||
|
||||
//save each remarks of each file
|
||||
foreach ($remarks as $key => $remark) {
|
||||
$remarkPayload = new CreateRemarkDTO(file_id: $fileCreated->id, remark: $remark['remark']);
|
||||
$this->storeRemarkCommand->execute($remarkPayload->except('remarkModel')->toArray());
|
||||
}
|
||||
|
||||
$filesCreated[] = $fileCreated;
|
||||
}
|
||||
|
||||
$payload->files = $filesCreated;
|
||||
|
||||
return $next($payload);
|
||||
} catch (\Exception $exception)
|
||||
{
|
||||
throw new \LogicException('Error creating transmittal files: ' . $exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
20
app/Commands/Branches/CreateBranchCommand.php
Normal file
20
app/Commands/Branches/CreateBranchCommand.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Branches;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\Branch;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CreateBranchCommand implements Command
|
||||
{
|
||||
public function execute(array $data): \Illuminate\Database\Eloquent\Model
|
||||
{
|
||||
return DB::transaction(
|
||||
callback: fn() => Branch::query()->updateOrCreate(['id' => $data['id'] ?? null], Arr::except($data, ['series'])),
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
11
app/Commands/Command.php
Normal file
11
app/Commands/Command.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands;
|
||||
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
interface Command
|
||||
{
|
||||
public function execute(array $data) : mixed;
|
||||
}
|
||||
21
app/Commands/Series/CreateSeriesCommand.php
Normal file
21
app/Commands/Series/CreateSeriesCommand.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Series;
|
||||
|
||||
use App\Actions\BaseAction;
|
||||
use App\Commands\Command;
|
||||
use App\Models\Series;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CreateSeriesCommand implements Command
|
||||
{
|
||||
public function execute($data) : Model
|
||||
{
|
||||
return DB::transaction(
|
||||
callback: fn () => Series::query()->create($data),
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
23
app/Commands/Transmittal/GenerateTransmittalSeries.php
Normal file
23
app/Commands/Transmittal/GenerateTransmittalSeries.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Transmittal;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\Transmittal;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GenerateTransmittalSeries implements Command
|
||||
{
|
||||
|
||||
public function execute(array $data): string
|
||||
{
|
||||
$lastSeries = Transmittal::query()->orderBy('id', 'desc')->first();
|
||||
|
||||
if ($lastSeries) {
|
||||
$series = explode('-', $lastSeries->series)[1];
|
||||
return 'TR-'.str_pad((int)$series + 1, 10, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
return $series = 'TR-'.str_pad(1, 10, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
19
app/Commands/Transmittal/StoreCommentCommand.php
Normal file
19
app/Commands/Transmittal/StoreCommentCommand.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Transmittal;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\Comment;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StoreCommentCommand implements Command
|
||||
{
|
||||
|
||||
public function execute(array $data): mixed
|
||||
{
|
||||
return DB::transaction(
|
||||
callback: fn () => Comment::query()->create($data),
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
}
|
||||
20
app/Commands/Transmittal/StoreFileCommand.php
Normal file
20
app/Commands/Transmittal/StoreFileCommand.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Transmittal;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\File;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use function PHPUnit\Framework\callback;
|
||||
|
||||
class StoreFileCommand implements Command
|
||||
{
|
||||
|
||||
public function execute(array $data): mixed
|
||||
{
|
||||
return DB::transaction(
|
||||
callback: fn () => File::query()->create($data),
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
}
|
||||
19
app/Commands/Transmittal/StoreRemarkCommand.php
Normal file
19
app/Commands/Transmittal/StoreRemarkCommand.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Transmittal;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\Remark;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StoreRemarkCommand implements Command
|
||||
{
|
||||
|
||||
public function execute(array $data): mixed
|
||||
{
|
||||
return DB::transaction(
|
||||
callback: fn () => Remark::query()->create($data),
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
}
|
||||
20
app/Commands/Transmittal/StoreTransmittalCommand.php
Normal file
20
app/Commands/Transmittal/StoreTransmittalCommand.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Commands\Transmittal;
|
||||
|
||||
use App\Commands\Command;
|
||||
use App\Models\Transmittal;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StoreTransmittalCommand implements Command
|
||||
{
|
||||
|
||||
public function execute(array $data): Model
|
||||
{
|
||||
return DB::transaction(
|
||||
callback: fn () => Transmittal::query()->updateOrCreate(['id' => $data['id'] ?? null], $data),
|
||||
attempts: 2
|
||||
);
|
||||
}
|
||||
}
|
||||
15
app/DataObjects/CreateBranchDTO.php
Normal file
15
app/DataObjects/CreateBranchDTO.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateBranchDTO extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public array $data,
|
||||
public ?Model $branch = null,
|
||||
public ?Model $series = null
|
||||
) {}
|
||||
}
|
||||
15
app/DataObjects/CreateCommentDTO.php
Normal file
15
app/DataObjects/CreateCommentDTO.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateCommentDTO extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public int $file_id,
|
||||
public string $comment,
|
||||
public ?Model $commentModel = null
|
||||
) {}
|
||||
}
|
||||
15
app/DataObjects/CreateFileDTO.php
Normal file
15
app/DataObjects/CreateFileDTO.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateFileDTO extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public int $transmittal_id,
|
||||
public string $description,
|
||||
public ?Model $file = null,
|
||||
) {}
|
||||
}
|
||||
15
app/DataObjects/CreateRemarkDTO.php
Normal file
15
app/DataObjects/CreateRemarkDTO.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateRemarkDTO extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public int $file_id,
|
||||
public string $remark,
|
||||
public ?Model $remarkModel = null
|
||||
) {}
|
||||
}
|
||||
16
app/DataObjects/CreateSeriesDTO.php
Normal file
16
app/DataObjects/CreateSeriesDTO.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateSeriesDTO extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public ?int $id,
|
||||
public string $series,
|
||||
public ?int $branch_id,
|
||||
public ?int $sale_id,
|
||||
public ?bool $is_start,
|
||||
) {}
|
||||
}
|
||||
22
app/DataObjects/CreateTransmittalDTO.php
Normal file
22
app/DataObjects/CreateTransmittalDTO.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class CreateTransmittalDTO extends Data
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param Model|null $transmittal
|
||||
* @param Model[]|null $files
|
||||
*/
|
||||
public function __construct(
|
||||
public array $data,
|
||||
public ?Model $transmittal = null,
|
||||
public ?array $files = null,
|
||||
) {}
|
||||
}
|
||||
133
app/Exports/TransmittalsExport.php
Normal file
133
app/Exports/TransmittalsExport.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exports;
|
||||
|
||||
use App\Models\Transmittal;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Maatwebsite\Excel\Concerns\Exportable;
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\FromView;
|
||||
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||
use Maatwebsite\Excel\Concerns\WithDefaultStyles;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use PhpOffice\PhpSpreadsheet\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
|
||||
class TransmittalsExport implements FromCollection, WithMapping, ShouldAutoSize, ShouldQueue, WithDefaultStyles, WithHeadings
|
||||
{
|
||||
|
||||
use Exportable, Queueable, SerializesModels;
|
||||
|
||||
|
||||
public function __construct(
|
||||
private readonly array $id
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
public function view(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$transmittals = Transmittal::query()->with(['client','branch', 'files.notes', 'files.remarks'])->whereIn('id', Arr::flatten($this->id))->get();
|
||||
return View::make('transmittal.export.transmittal-export-table')->with(['transmittals' => $transmittals]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function defaultStyles(Style $defaultStyle)
|
||||
{
|
||||
return $defaultStyle->applyFromArray([
|
||||
'alignment' => [
|
||||
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
||||
'vertical' => Alignment::VERTICAL_CENTER,
|
||||
],
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'series',
|
||||
'files',
|
||||
'notes',
|
||||
'remarks'
|
||||
];
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
$transmittals = Transmittal::query()->with(['client','branch', 'files.notes', 'files.remarks'])
|
||||
->withCount(['files','notes','remarks'])->with(['files' => function($files) {
|
||||
$files->withCount(['notes','remarks']);
|
||||
}])
|
||||
->whereIn('id', Arr::flatten($this->id))->get();
|
||||
|
||||
|
||||
|
||||
return $transmittals;
|
||||
}
|
||||
|
||||
public function map($transmittal): array
|
||||
{
|
||||
|
||||
|
||||
|
||||
$data = [];
|
||||
|
||||
|
||||
|
||||
$firstFile = $transmittal->files->first();
|
||||
|
||||
|
||||
$data[] = [$transmittal->series, $firstFile?->description, $firstFile->notes->first()?->comment, $firstFile->remarks->first()?->remark];
|
||||
|
||||
$fileRowCounter = 0;
|
||||
foreach ($transmittal->files as $file) {
|
||||
$notes = $file->notes->pluck('comment');
|
||||
$remarks = $file->remarks->pluck('remark');
|
||||
|
||||
$fileNoteCount = count($notes);
|
||||
$fileRemarkCount = count($remarks);
|
||||
|
||||
$fileRowCount = $fileNoteCount;
|
||||
if($fileRemarkCount > $fileNoteCount) {
|
||||
$fileRowCount = $fileRemarkCount;
|
||||
}
|
||||
|
||||
|
||||
if($fileRowCounter != 0) {
|
||||
$data[] = [
|
||||
'',
|
||||
$file->description ,
|
||||
$notes[$fileRowCounter - 1] ?? '',
|
||||
$remarks[$fileRowCounter - 1] ?? '',
|
||||
];
|
||||
|
||||
for ($i = 0; $i < $fileRowCount; $i++) {
|
||||
$data[] = [
|
||||
'',
|
||||
'',
|
||||
$notes[$i] ?? '',
|
||||
$remarks[$i] ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$fileRowCounter++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
38
app/Filament/Exports/ClientAccountsExporter.php
Normal file
38
app/Filament/Exports/ClientAccountsExporter.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Exports;
|
||||
|
||||
use App\Models\ClientAccounts;
|
||||
use Filament\Actions\Exports\ExportColumn;
|
||||
use Filament\Actions\Exports\Exporter;
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
|
||||
class ClientAccountsExporter extends Exporter
|
||||
{
|
||||
protected static ?string $model = ClientAccounts::class;
|
||||
|
||||
public static function getColumns(): array
|
||||
{
|
||||
return [
|
||||
ExportColumn::make('id')
|
||||
->label('ID'),
|
||||
ExportColumn::make('account'),
|
||||
ExportColumn::make('description'),
|
||||
ExportColumn::make('acountType.type'),
|
||||
ExportColumn::make('client.company'),
|
||||
ExportColumn::make('created_at'),
|
||||
ExportColumn::make('updated_at'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getCompletedNotificationBody(Export $export): string
|
||||
{
|
||||
$body = 'Your client accounts export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
|
||||
|
||||
if ($failedRowsCount = $export->getFailedRowsCount()) {
|
||||
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
39
app/Filament/Exports/ClientExporter.php
Normal file
39
app/Filament/Exports/ClientExporter.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Exports;
|
||||
|
||||
use App\Models\Client;
|
||||
use Filament\Actions\Exports\ExportColumn;
|
||||
use Filament\Actions\Exports\Exporter;
|
||||
use Filament\Actions\Exports\Models\Export;
|
||||
|
||||
class ClientExporter extends Exporter
|
||||
{
|
||||
protected static ?string $model = Client::class;
|
||||
|
||||
public static function getColumns(): array
|
||||
{
|
||||
return [
|
||||
ExportColumn::make('id')
|
||||
->label('ID'),
|
||||
ExportColumn::make('firstname'),
|
||||
ExportColumn::make('lastname'),
|
||||
ExportColumn::make('middlename'),
|
||||
ExportColumn::make('company'),
|
||||
ExportColumn::make('type.type'),
|
||||
ExportColumn::make('created_at'),
|
||||
ExportColumn::make('updated_at'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getCompletedNotificationBody(Export $export): string
|
||||
{
|
||||
$body = 'Your client export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
|
||||
|
||||
if ($failedRowsCount = $export->getFailedRowsCount()) {
|
||||
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
67
app/Filament/Resources/BranchResource.php
Normal file
67
app/Filament/Resources/BranchResource.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\BranchResource\Pages;
|
||||
use App\Filament\Resources\BranchResource\RelationManagers;
|
||||
use App\Models\Branch;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
|
||||
class BranchResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Branch::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||
|
||||
|
||||
protected static bool $shouldRegisterNavigation = false;
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
//
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
//
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListBranches::route('/'),
|
||||
'create' => Pages\CreateBranch::route('/create'),
|
||||
'edit' => Pages\EditBranch::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
12
app/Filament/Resources/BranchResource/Pages/CreateBranch.php
Normal file
12
app/Filament/Resources/BranchResource/Pages/CreateBranch.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\BranchResource\Pages;
|
||||
|
||||
use App\Filament\Resources\BranchResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateBranch extends CreateRecord
|
||||
{
|
||||
protected static string $resource = BranchResource::class;
|
||||
}
|
||||
19
app/Filament/Resources/BranchResource/Pages/EditBranch.php
Normal file
19
app/Filament/Resources/BranchResource/Pages/EditBranch.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\BranchResource\Pages;
|
||||
|
||||
use App\Filament\Resources\BranchResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditBranch extends EditRecord
|
||||
{
|
||||
protected static string $resource = BranchResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
19
app/Filament/Resources/BranchResource/Pages/ListBranches.php
Normal file
19
app/Filament/Resources/BranchResource/Pages/ListBranches.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\BranchResource\Pages;
|
||||
|
||||
use App\Filament\Resources\BranchResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListBranches extends ListRecords
|
||||
{
|
||||
protected static string $resource = BranchResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
101
app/Filament/Resources/ClientResource.php
Normal file
101
app/Filament/Resources/ClientResource.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
|
||||
use App\Filament\Resources\ClientResource\RelationManagers\AccountsRelationManager;
|
||||
use App\Filament\Resources\ClientResource\RelationManagers\BranchesRelationManager;
|
||||
use App\Filament\Resources\ClientResource\RelationManagers\TransmittalsRelationManager;
|
||||
use App\Models\Client;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Infolists\Components\Grid;
|
||||
use Filament\Infolists\Components\Section;
|
||||
use Filament\Infolists\Components\Split;
|
||||
use Filament\Infolists\Components\TextEntry;
|
||||
use Filament\Infolists\Infolist;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ClientResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Client::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-user';
|
||||
|
||||
public static function authorizeView(Model $record): void
|
||||
{
|
||||
parent::authorizeView($record); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('firstname')->label('First Name')->required(),
|
||||
Forms\Components\TextInput::make('middlename')->label('Middle Name')->nullable(),
|
||||
Forms\Components\TextInput::make('lastname')->label('Last Name')->required(),
|
||||
Forms\Components\Grid::make()->schema([
|
||||
Forms\Components\TextInput::make('company')->label('Company')->required(),
|
||||
Forms\Components\Select::make('type_id')
|
||||
->relationship('type', 'type')
|
||||
->label('Type')->required(),
|
||||
])->columns(2)
|
||||
])->columns(3);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('firstname')->label('First Name')->searchable(),
|
||||
Tables\Columns\TextColumn::make('middlename')->label('Middle Name'),
|
||||
Tables\Columns\TextColumn::make('lastname')->label('Last Name'),
|
||||
Tables\Columns\TextColumn::make('company')->label('Company')->searchable(),
|
||||
Tables\Columns\TextColumn::make('type.type')->label('Type'),
|
||||
])
|
||||
->filters([
|
||||
Tables\Filters\Filter::make('Vatable')
|
||||
->query(fn (Builder $query) => $query->orWhereHas('type', function (Builder $query) {
|
||||
$query->where('type', 'Vatable');
|
||||
}) ),
|
||||
Tables\Filters\Filter::make('Non-Vatable')
|
||||
->query(fn (Builder $query) => $query->orWhereHas('type', function (Builder $query) {
|
||||
$query->where('type', 'Non Vatable');
|
||||
}) )
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\ViewAction::make(),
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make()->requiresConfirmation()
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
AccountsRelationManager::class,
|
||||
BranchesRelationManager::class,
|
||||
TransmittalsRelationManager::class
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'view' => \App\Filament\Resources\ClientResource\Pages\ViewClient:: route('/{record}'),
|
||||
'edit' => \App\Filament\Resources\ClientResource\Pages\EditClient::route('/{record}/edit'),
|
||||
'index' => \App\Filament\Resources\ClientResource\Pages\ListClients::route('/'),
|
||||
];
|
||||
}
|
||||
}
|
||||
11
app/Filament/Resources/ClientResource/Pages/CreateClient.php
Normal file
11
app/Filament/Resources/ClientResource/Pages/CreateClient.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ClientResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateClient extends CreateRecord
|
||||
{
|
||||
protected static string $resource = ClientResource::class;
|
||||
}
|
||||
20
app/Filament/Resources/ClientResource/Pages/EditClient.php
Normal file
20
app/Filament/Resources/ClientResource/Pages/EditClient.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ClientResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditClient extends EditRecord
|
||||
{
|
||||
protected static string $resource = ClientResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make()->icon('heroicon-s-trash')->requiresConfirmation(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
25
app/Filament/Resources/ClientResource/Pages/ListClients.php
Normal file
25
app/Filament/Resources/ClientResource/Pages/ListClients.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\Pages;
|
||||
|
||||
use App\Filament\Exports\ClientExporter;
|
||||
use App\Filament\Resources\ClientResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListClients extends ListRecords
|
||||
{
|
||||
protected static string $resource = ClientResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\ExportAction::make('Export clients')
|
||||
->exporter(ClientExporter::class)
|
||||
->formats([
|
||||
Actions\Exports\Enums\ExportFormat::Csv,
|
||||
]),
|
||||
Actions\CreateAction::make()->slideOver(),
|
||||
];
|
||||
}
|
||||
}
|
||||
56
app/Filament/Resources/ClientResource/Pages/ViewClient.php
Normal file
56
app/Filament/Resources/ClientResource/Pages/ViewClient.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ClientResource;
|
||||
use App\Filament\Resources\ClientResource\RelationManagers\AccountsRelationManager;
|
||||
use App\Filament\Resources\ClientResource\RelationManagers\BranchesRelationManager;
|
||||
use App\Filament\Resources\ClientResource\RelationManagers\TransmittalsRelationManager;
|
||||
use App\Models\Account;
|
||||
use App\Models\Transmittal;
|
||||
use Filament\Actions;
|
||||
use Filament\Infolists\Components\Grid;
|
||||
use Filament\Infolists\Components\RepeatableEntry;
|
||||
use Filament\Infolists\Components\Section;
|
||||
use Filament\Infolists\Components\TextEntry;
|
||||
use Filament\Infolists\Infolist;
|
||||
use Filament\Resources\Pages\ViewRecord;
|
||||
|
||||
class ViewClient extends ViewRecord
|
||||
{
|
||||
protected static string $resource = ClientResource::class;
|
||||
|
||||
public function infolist(Infolist $infolist): Infolist
|
||||
{
|
||||
return $infolist
|
||||
->schema([
|
||||
Section::make()->schema([
|
||||
Grid::make()->schema([
|
||||
TextEntry::make('firstname')->label('First Name'),
|
||||
TextEntry::make('middlename')->label('Middle Name'),
|
||||
TextEntry::make('lastname')->label('Last Name'),
|
||||
TextEntry::make('company')->label('Company'),
|
||||
TextEntry::make('type.type')->label('Type'),
|
||||
])->columns(3),
|
||||
]),
|
||||
|
||||
Section::make('Branches')->schema([
|
||||
RepeatableEntry::make('branches')
|
||||
->schema([
|
||||
TextEntry::make('code')->label('Branch Code'),
|
||||
TextEntry::make('current_series')->label('Branch Current Series'),
|
||||
])
|
||||
->hiddenLabel()
|
||||
->grid(2)
|
||||
])->collapsible()
|
||||
]);
|
||||
}
|
||||
|
||||
public function getRelationManagers(): array
|
||||
{
|
||||
return [
|
||||
AccountsRelationManager::class,
|
||||
TransmittalsRelationManager::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\RelationManagers;
|
||||
|
||||
use App\Filament\Exports\ClientAccountsExporter;
|
||||
use App\Models\Account;
|
||||
use Filament\Actions\Exports\Enums\ExportFormat;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class AccountsRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'accounts';
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('account')->required(),
|
||||
Forms\Components\Textarea::make('description')->nullable(),
|
||||
Forms\Components\Select::make('account_type_id')
|
||||
->relationship('accountType','type')
|
||||
->required(),
|
||||
Forms\Components\Select::make('normal_balance')->options(
|
||||
['debit' => 'Debit','credit' => 'Credit']
|
||||
)->required()
|
||||
]);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->recordTitleAttribute('client_id')
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('account')->description(fn (Account $record): string => $record->description),
|
||||
Tables\Columns\TextColumn::make('accountType.type'),
|
||||
Tables\Columns\TextColumn::make('normal_balance'),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->headerActions([
|
||||
Tables\Actions\ExportAction::make('Export Accounts')->exporter(ClientAccountsExporter::class)->formats([ExportFormat::Csv]),
|
||||
Tables\Actions\CreateAction::make()->label('New Account')->icon('heroicon-o-plus')->slideOver(),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make()->slideOver(),
|
||||
Tables\Actions\DeleteAction::make()->requiresConfirmation(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make()->icon('heroicon-s-trash')->requiresConfirmation(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\RelationManagers;
|
||||
|
||||
use App\DataObjects\CreateBranchDTO;
|
||||
use App\Processes\Branch\CreateBranchProcess;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Support\RawJs;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class BranchesRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'branches';
|
||||
|
||||
protected static bool $shouldCheckPolicyExistence = true;
|
||||
|
||||
protected CreateBranchProcess $createBranchProcess;
|
||||
public function __construct() {
|
||||
$this->createBranchProcess = new CreateBranchProcess();
|
||||
}
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('code')->required()->unique('branches','code'),
|
||||
Forms\Components\TextInput::make('series')->label('Current Series')
|
||||
->required()
|
||||
->numeric()
|
||||
->integer()
|
||||
->maxLength(6)
|
||||
->minLength(1)
|
||||
->mask(RawJs::make(<<<'JS'
|
||||
'999999'
|
||||
JS))
|
||||
])->columns(1);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->recordTitleAttribute('client_id')
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('code')->label('Branch Code'),
|
||||
Tables\Columns\TextColumn::make('current_series')->label('Current Series'),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->headerActions([
|
||||
Tables\Actions\CreateAction::make()
|
||||
->mutateFormDataUsing(function (array $data): array {
|
||||
$data['client_id'] = $this->ownerRecord->id;
|
||||
return $data;
|
||||
})
|
||||
->using(function($data) {
|
||||
$payload = new CreateBranchDTO(data: $data);
|
||||
return $this->createBranchProcess->run($payload)->branch;
|
||||
}),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\RelationManagers;
|
||||
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class ExpensesRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'expenses';
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('client_id')
|
||||
->required()
|
||||
->maxLength(255),
|
||||
]);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->recordTitleAttribute('client_id')
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('client_id'),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->headerActions([
|
||||
Tables\Actions\CreateAction::make(),
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ClientResource\RelationManagers;
|
||||
|
||||
use App\Commands\Transmittal\GenerateTransmittalSeries;
|
||||
use App\Commands\Transmittal\StoreTransmittalCommand;
|
||||
use App\DataObjects\CreateTransmittalDTO;
|
||||
use App\Filament\Resources\TransmittalResource;
|
||||
use App\Models\Branch;
|
||||
use App\Models\Client;
|
||||
use App\Models\Transmittal;
|
||||
use App\Processes\Transmittal\CreateTransmittalProcess;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TransmittalsRelationManager extends RelationManager
|
||||
{
|
||||
protected static string $relationship = 'transmittals';
|
||||
|
||||
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
|
||||
{
|
||||
return auth()->user()->can('update_transmittal');
|
||||
}
|
||||
|
||||
protected CreateTransmittalProcess $transmittalProcess;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->transmittalProcess = new CreateTransmittalProcess();
|
||||
}
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return TransmittalResource::form($form)
|
||||
->fill(
|
||||
['client_id' => $this->getOwnerRecord()->id]
|
||||
);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return TransmittalResource::table($table)->headerActions([
|
||||
Tables\Actions\Action::make('New Transmittal')->action('openCreateForm')
|
||||
]);
|
||||
}
|
||||
|
||||
public function openCreateForm() {
|
||||
return redirect()->route('filament.admin.resources.transmittals.create');
|
||||
}
|
||||
|
||||
}
|
||||
400
app/Filament/Resources/Shield/RoleResource.php
Normal file
400
app/Filament/Resources/Shield/RoleResource.php
Normal file
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Shield;
|
||||
|
||||
use App\Filament\Resources\Shield\RoleResource\Pages;
|
||||
use BezhanSalleh\FilamentShield\Contracts\HasShieldPermissions;
|
||||
use BezhanSalleh\FilamentShield\Facades\FilamentShield;
|
||||
use BezhanSalleh\FilamentShield\FilamentShieldPlugin;
|
||||
use BezhanSalleh\FilamentShield\Forms\ShieldSelectAllToggle;
|
||||
use BezhanSalleh\FilamentShield\Support\Utils;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\Component;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RoleResource extends Resource implements HasShieldPermissions
|
||||
{
|
||||
protected static ?string $recordTitleAttribute = 'name';
|
||||
|
||||
public static function getPermissionPrefixes(): array
|
||||
{
|
||||
return [
|
||||
'view',
|
||||
'view_any',
|
||||
'create',
|
||||
'update',
|
||||
'delete',
|
||||
'delete_any',
|
||||
];
|
||||
}
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Grid::make()
|
||||
->schema([
|
||||
Forms\Components\Section::make()
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('name')
|
||||
->label(__('filament-shield::filament-shield.field.name'))
|
||||
->unique(ignoreRecord: true)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
Forms\Components\TextInput::make('guard_name')
|
||||
->label(__('filament-shield::filament-shield.field.guard_name'))
|
||||
->default(Utils::getFilamentAuthGuard())
|
||||
->nullable()
|
||||
->maxLength(255),
|
||||
|
||||
ShieldSelectAllToggle::make('select_all')
|
||||
->onIcon('heroicon-s-shield-check')
|
||||
->offIcon('heroicon-s-shield-exclamation')
|
||||
->label(__('filament-shield::filament-shield.field.select_all.name'))
|
||||
->helperText(fn (): HtmlString => new HtmlString(__('filament-shield::filament-shield.field.select_all.message')))
|
||||
->dehydrated(fn ($state): bool => $state),
|
||||
|
||||
])
|
||||
->columns([
|
||||
'sm' => 2,
|
||||
'lg' => 3,
|
||||
]),
|
||||
]),
|
||||
Forms\Components\Tabs::make('Permissions')
|
||||
->contained()
|
||||
->tabs([
|
||||
static::getTabFormComponentForResources(),
|
||||
static::getTabFormComponentForPage(),
|
||||
static::getTabFormComponentForWidget(),
|
||||
static::getTabFormComponentForCustomPermissions(),
|
||||
])
|
||||
->columnSpan('full'),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('name')
|
||||
->badge()
|
||||
->label(__('filament-shield::filament-shield.column.name'))
|
||||
->formatStateUsing(fn ($state): string => Str::headline($state))
|
||||
->colors(['primary'])
|
||||
->searchable(),
|
||||
Tables\Columns\TextColumn::make('guard_name')
|
||||
->badge()
|
||||
->label(__('filament-shield::filament-shield.column.guard_name')),
|
||||
Tables\Columns\TextColumn::make('permissions_count')
|
||||
->badge()
|
||||
->label(__('filament-shield::filament-shield.column.permissions'))
|
||||
->counts('permissions')
|
||||
->colors(['success']),
|
||||
Tables\Columns\TextColumn::make('updated_at')
|
||||
->label(__('filament-shield::filament-shield.column.updated_at'))
|
||||
->dateTime(),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListRoles::route('/'),
|
||||
'create' => Pages\CreateRole::route('/create'),
|
||||
'view' => Pages\ViewRole::route('/{record}'),
|
||||
'edit' => Pages\EditRole::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getCluster(): ?string
|
||||
{
|
||||
return Utils::getResourceCluster() ?? static::$cluster;
|
||||
}
|
||||
|
||||
public static function getModel(): string
|
||||
{
|
||||
return Utils::getRoleModel();
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('filament-shield::filament-shield.resource.label.role');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('filament-shield::filament-shield.resource.label.roles');
|
||||
}
|
||||
|
||||
public static function shouldRegisterNavigation(): bool
|
||||
{
|
||||
return Utils::isResourceNavigationRegistered();
|
||||
}
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return 'Security Settings';
|
||||
}
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('filament-shield::filament-shield.nav.role.label');
|
||||
}
|
||||
|
||||
public static function getNavigationIcon(): string
|
||||
{
|
||||
return __('filament-shield::filament-shield.nav.role.icon');
|
||||
}
|
||||
|
||||
public static function getNavigationSort(): ?int
|
||||
{
|
||||
return Utils::getResourceNavigationSort();
|
||||
}
|
||||
|
||||
public static function getSlug(): string
|
||||
{
|
||||
return Utils::getResourceSlug();
|
||||
}
|
||||
|
||||
public static function getNavigationBadge(): ?string
|
||||
{
|
||||
return Utils::isResourceNavigationBadgeEnabled()
|
||||
? strval(static::getEloquentQuery()->count())
|
||||
: null;
|
||||
}
|
||||
|
||||
public static function isScopedToTenant(): bool
|
||||
{
|
||||
return Utils::isScopedToTenant();
|
||||
}
|
||||
|
||||
public static function canGloballySearch(): bool
|
||||
{
|
||||
return Utils::isResourceGloballySearchable() && count(static::getGloballySearchableAttributes()) && static::canViewAny();
|
||||
}
|
||||
|
||||
public static function getResourceEntitiesSchema(): ?array
|
||||
{
|
||||
return collect(FilamentShield::getResources())
|
||||
->sortKeys()
|
||||
->map(function ($entity) {
|
||||
$sectionLabel = strval(
|
||||
static::shield()->hasLocalizedPermissionLabels()
|
||||
? FilamentShield::getLocalizedResourceLabel($entity['fqcn'])
|
||||
: $entity['model']
|
||||
);
|
||||
|
||||
return Forms\Components\Section::make($sectionLabel)
|
||||
->description(fn () => new HtmlString('<span style="word-break: break-word;">' . Utils::showModelPath($entity['fqcn']) . '</span>'))
|
||||
->compact()
|
||||
->schema([
|
||||
static::getCheckBoxListComponentForResource($entity),
|
||||
])
|
||||
->columnSpan(static::shield()->getSectionColumnSpan())
|
||||
->collapsible();
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function getResourceTabBadgeCount(): ?int
|
||||
{
|
||||
return collect(FilamentShield::getResources())
|
||||
->map(fn ($resource) => count(static::getResourcePermissionOptions($resource)))
|
||||
->sum();
|
||||
}
|
||||
|
||||
public static function getResourcePermissionOptions(array $entity): array
|
||||
{
|
||||
return collect(Utils::getResourcePermissionPrefixes($entity['fqcn']))
|
||||
->flatMap(function ($permission) use ($entity) {
|
||||
$name = $permission . '_' . $entity['resource'];
|
||||
$label = static::shield()->hasLocalizedPermissionLabels()
|
||||
? FilamentShield::getLocalizedResourcePermissionLabel($permission)
|
||||
: $name;
|
||||
|
||||
return [
|
||||
$name => $label,
|
||||
];
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function setPermissionStateForRecordPermissions(Component $component, string $operation, array $permissions, ?Model $record): void
|
||||
{
|
||||
|
||||
if (in_array($operation, ['edit', 'view'])) {
|
||||
|
||||
if (blank($record)) {
|
||||
return;
|
||||
}
|
||||
if ($component->isVisible() && count($permissions) > 0) {
|
||||
$component->state(
|
||||
collect($permissions)
|
||||
/** @phpstan-ignore-next-line */
|
||||
->filter(fn ($value, $key) => $record->checkPermissionTo($key))
|
||||
->keys()
|
||||
->toArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getPageOptions(): array
|
||||
{
|
||||
return collect(FilamentShield::getPages())
|
||||
->flatMap(fn ($page) => [
|
||||
$page['permission'] => static::shield()->hasLocalizedPermissionLabels()
|
||||
? FilamentShield::getLocalizedPageLabel($page['class'])
|
||||
: $page['permission'],
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function getWidgetOptions(): array
|
||||
{
|
||||
return collect(FilamentShield::getWidgets())
|
||||
->flatMap(fn ($widget) => [
|
||||
$widget['permission'] => static::shield()->hasLocalizedPermissionLabels()
|
||||
? FilamentShield::getLocalizedWidgetLabel($widget['class'])
|
||||
: $widget['permission'],
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function getCustomPermissionOptions(): ?array
|
||||
{
|
||||
return FilamentShield::getCustomPermissions()
|
||||
->mapWithKeys(fn ($customPermission) => [
|
||||
$customPermission => static::shield()->hasLocalizedPermissionLabels() ? str($customPermission)->headline()->toString() : $customPermission,
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public static function getTabFormComponentForResources(): Component
|
||||
{
|
||||
return static::shield()->hasSimpleResourcePermissionView()
|
||||
? static::getTabFormComponentForSimpleResourcePermissionsView()
|
||||
: Forms\Components\Tabs\Tab::make('resources')
|
||||
->label(__('filament-shield::filament-shield.resources'))
|
||||
->visible(fn (): bool => (bool) Utils::isResourceEntityEnabled())
|
||||
->badge(static::getResourceTabBadgeCount())
|
||||
->schema([
|
||||
Forms\Components\Grid::make()
|
||||
->schema(static::getResourceEntitiesSchema())
|
||||
->columns(static::shield()->getGridColumns()),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getCheckBoxListComponentForResource(array $entity): Component
|
||||
{
|
||||
$permissionsArray = static::getResourcePermissionOptions($entity);
|
||||
|
||||
return static::getCheckboxListFormComponent($entity['resource'], $permissionsArray, false);
|
||||
}
|
||||
|
||||
public static function getTabFormComponentForPage(): Component
|
||||
{
|
||||
$options = static::getPageOptions();
|
||||
$count = count($options);
|
||||
|
||||
return Forms\Components\Tabs\Tab::make('pages')
|
||||
->label(__('filament-shield::filament-shield.pages'))
|
||||
->visible(fn (): bool => (bool) Utils::isPageEntityEnabled() && $count > 0)
|
||||
->badge($count)
|
||||
->schema([
|
||||
static::getCheckboxListFormComponent('pages_tab', $options),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getTabFormComponentForWidget(): Component
|
||||
{
|
||||
$options = static::getWidgetOptions();
|
||||
$count = count($options);
|
||||
|
||||
return Forms\Components\Tabs\Tab::make('widgets')
|
||||
->label(__('filament-shield::filament-shield.widgets'))
|
||||
->visible(fn (): bool => (bool) Utils::isWidgetEntityEnabled() && $count > 0)
|
||||
->badge($count)
|
||||
->schema([
|
||||
static::getCheckboxListFormComponent('widgets_tab', $options),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getTabFormComponentForCustomPermissions(): Component
|
||||
{
|
||||
$options = static::getCustomPermissionOptions();
|
||||
$count = count($options);
|
||||
|
||||
return Forms\Components\Tabs\Tab::make('custom')
|
||||
->label(__('filament-shield::filament-shield.custom'))
|
||||
->visible(fn (): bool => (bool) Utils::isCustomPermissionEntityEnabled() && $count > 0)
|
||||
->badge($count)
|
||||
->schema([
|
||||
static::getCheckboxListFormComponent('custom_permissions', $options),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getTabFormComponentForSimpleResourcePermissionsView(): Component
|
||||
{
|
||||
$options = FilamentShield::getAllResourcePermissions();
|
||||
$count = count($options);
|
||||
|
||||
return Forms\Components\Tabs\Tab::make('resources')
|
||||
->label(__('filament-shield::filament-shield.resources'))
|
||||
->visible(fn (): bool => (bool) Utils::isResourceEntityEnabled() && $count > 0)
|
||||
->badge($count)
|
||||
->schema([
|
||||
static::getCheckboxListFormComponent('resources_tab', $options),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getCheckboxListFormComponent(string $name, array $options, bool $searchable = true): Component
|
||||
{
|
||||
return Forms\Components\CheckboxList::make($name)
|
||||
->label('')
|
||||
->options(fn (): array => $options)
|
||||
->searchable($searchable)
|
||||
->afterStateHydrated(
|
||||
fn (Component $component, string $operation, ?Model $record) => static::setPermissionStateForRecordPermissions(
|
||||
component: $component,
|
||||
operation: $operation,
|
||||
permissions: $options,
|
||||
record: $record
|
||||
)
|
||||
)
|
||||
->dehydrated(fn ($state) => ! blank($state))
|
||||
->bulkToggleable()
|
||||
->gridDirection('row')
|
||||
->columns(static::shield()->getCheckboxListColumns())
|
||||
->columnSpan(static::shield()->getCheckboxListColumnSpan());
|
||||
}
|
||||
|
||||
public static function shield(): FilamentShieldPlugin
|
||||
{
|
||||
return FilamentShieldPlugin::get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Shield\RoleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\Shield\RoleResource;
|
||||
use BezhanSalleh\FilamentShield\Support\Utils;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class CreateRole extends CreateRecord
|
||||
{
|
||||
protected static string $resource = RoleResource::class;
|
||||
|
||||
public Collection $permissions;
|
||||
|
||||
protected function mutateFormDataBeforeCreate(array $data): array
|
||||
{
|
||||
$this->permissions = collect($data)
|
||||
->filter(function ($permission, $key) {
|
||||
return ! in_array($key, ['name', 'guard_name', 'select_all']);
|
||||
})
|
||||
->values()
|
||||
->flatten()
|
||||
->unique();
|
||||
|
||||
return Arr::only($data, ['name', 'guard_name']);
|
||||
}
|
||||
|
||||
protected function afterCreate(): void
|
||||
{
|
||||
$permissionModels = collect();
|
||||
$this->permissions->each(function ($permission) use ($permissionModels) {
|
||||
$permissionModels->push(Utils::getPermissionModel()::firstOrCreate([
|
||||
/** @phpstan-ignore-next-line */
|
||||
'name' => $permission,
|
||||
'guard_name' => $this->data['guard_name'],
|
||||
]));
|
||||
});
|
||||
|
||||
$this->record->syncPermissions($permissionModels);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Shield\RoleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\Shield\RoleResource;
|
||||
use BezhanSalleh\FilamentShield\Support\Utils;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class EditRole extends EditRecord
|
||||
{
|
||||
protected static string $resource = RoleResource::class;
|
||||
|
||||
public Collection $permissions;
|
||||
|
||||
protected function getActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function mutateFormDataBeforeSave(array $data): array
|
||||
{
|
||||
$this->permissions = collect($data)
|
||||
->filter(function ($permission, $key) {
|
||||
return ! in_array($key, ['name', 'guard_name', 'select_all']);
|
||||
})
|
||||
->values()
|
||||
->flatten()
|
||||
->unique();
|
||||
|
||||
return Arr::only($data, ['name', 'guard_name']);
|
||||
}
|
||||
|
||||
protected function afterSave(): void
|
||||
{
|
||||
$permissionModels = collect();
|
||||
$this->permissions->each(function ($permission) use ($permissionModels) {
|
||||
$permissionModels->push(Utils::getPermissionModel()::firstOrCreate([
|
||||
'name' => $permission,
|
||||
'guard_name' => $this->data['guard_name'],
|
||||
]));
|
||||
});
|
||||
|
||||
$this->record->syncPermissions($permissionModels);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Shield\RoleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\Shield\RoleResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListRoles extends ListRecords
|
||||
{
|
||||
protected static string $resource = RoleResource::class;
|
||||
|
||||
protected function getActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Shield\RoleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\Shield\RoleResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ViewRecord;
|
||||
|
||||
class ViewRole extends ViewRecord
|
||||
{
|
||||
protected static string $resource = RoleResource::class;
|
||||
|
||||
protected function getActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\EditAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
214
app/Filament/Resources/TransmittalResource.php
Normal file
214
app/Filament/Resources/TransmittalResource.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Commands\Transmittal\GenerateTransmittalSeries;
|
||||
use App\Commands\Transmittal\StoreTransmittalCommand;
|
||||
use App\Exports\TransmittalsExport;
|
||||
use App\Filament\Resources\TransmittalResource\Pages;
|
||||
use App\Filament\Resources\TransmittalResource\RelationManagers;
|
||||
use App\Jobs\ExportCompleteJob;
|
||||
use App\Models\Branch;
|
||||
use App\Models\Client;
|
||||
use App\Models\Transmittal;
|
||||
use App\Models\User;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Support\Enums\FontWeight;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\SelectFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use Illuminate\Support\Arr;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Malzariey\FilamentDaterangepickerFilter\Filters\DateRangeFilter;
|
||||
|
||||
use YOS\FilamentExcel\Actions\Import;
|
||||
|
||||
class TransmittalResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Transmittal::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema(static::getFormSchema());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\Layout\Split::make([
|
||||
Tables\Columns\TextColumn::make('series')
|
||||
->searchable()
|
||||
->label('Series')
|
||||
->weight(FontWeight::Bold)
|
||||
->columnSpan(2),
|
||||
Tables\Columns\Layout\Stack::make([
|
||||
Tables\Columns\TextColumn::make('client.company')
|
||||
->searchable()
|
||||
->weight(FontWeight::SemiBold)->label('Client'),
|
||||
Tables\Columns\TextColumn::make('branch.code')
|
||||
->searchable()
|
||||
->label('Branch'),
|
||||
]),
|
||||
]),
|
||||
Tables\Columns\Layout\View::make('transmittal.tables.collapsible-files-component')->collapsible(),
|
||||
])
|
||||
->filters([
|
||||
SelectFilter::make('client_id')->label('Client filter')->options(function () {
|
||||
return Client::query()->get()->pluck('company', 'id');
|
||||
}),
|
||||
SelectFilter::make('branch_id')->label('Branch Filter')->options(function () {
|
||||
return Branch::query()->get()->pluck('code', 'id');
|
||||
}),
|
||||
SelectFilter::make('user_id')->label('Assigned To Filter')->options(function () {
|
||||
return User::query()->get()->pluck('name', 'id');
|
||||
}),
|
||||
DateRangeFilter::make('date_created'),
|
||||
DateRangeFilter::make('date_dispatch'),
|
||||
DateRangeFilter::make('date_received'),
|
||||
|
||||
])
|
||||
->heading('Transmittals')
|
||||
->description('Click on toggle button at the end of table row to show additional details.')
|
||||
->actions(static::getTableActions())
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
Tables\Actions\BulkAction::make('Bulk Export')->action(function ($records) {
|
||||
|
||||
static::exportTransmittal(Arr::flatten($records->pluck('id')));
|
||||
})
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getFormSchema() : array
|
||||
{
|
||||
return [
|
||||
Forms\Components\Select::make('client_id')
|
||||
->options(function () {
|
||||
return Client::query()->get()->pluck('company', 'id');
|
||||
})
|
||||
->label('Client')
|
||||
->reactive()
|
||||
->required()
|
||||
->required()->columnSpan(3),
|
||||
Forms\Components\Select::make('branch_id')->label('Branch')->relationship('branch')->options(function (callable $get) {
|
||||
return Branch::query()->where('client_id', $get('client_id'))->get()->pluck('code', 'id');
|
||||
})->required(),
|
||||
Forms\Components\TextInput::make('series')->readOnly()->default((new GenerateTransmittalSeries)->execute([]))->unique('transmittals', ignoreRecord: true),
|
||||
Forms\Components\DatePicker::make('date_created')
|
||||
->native(false)
|
||||
->required()->default(now()),
|
||||
|
||||
Repeater::make('files')
|
||||
->relationship('files')
|
||||
->label('Item')
|
||||
->schema([
|
||||
Textarea::make('description')->required(),
|
||||
Repeater::make('comments')
|
||||
->relationship('notes')
|
||||
->label('Note')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('comment')->label('Note')->required(),
|
||||
]),
|
||||
Repeater::make('remarks')
|
||||
->relationship('remarks')
|
||||
->label('Remarks')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('remark')->label('Remark')->required(),
|
||||
]),
|
||||
])
|
||||
->columns(3)
|
||||
->columnSpan(3)
|
||||
];
|
||||
}
|
||||
|
||||
public static function getTableActions () : array
|
||||
{
|
||||
return [
|
||||
Tables\Actions\Action::make('Export')->action(fn ($record) => static::exportTransmittal([$record->id])),
|
||||
Tables\Actions\ViewAction::make(),
|
||||
Tables\Actions\Action::make('Update Status')
|
||||
->fillForm(function($record) {
|
||||
return [
|
||||
'user_id' => $record->user_id,
|
||||
'date_dispatch' => $record->date_dispatch,
|
||||
'date_received' => $record->date_received,
|
||||
'received_by' => $record->received_by,
|
||||
];
|
||||
})
|
||||
->form([
|
||||
Select::make('user_id')->label('Dispatch By')
|
||||
->relationship('user', 'name')
|
||||
->searchable()
|
||||
->preload(),
|
||||
Datepicker::make('date_dispatch')->label('Dispatch Date')
|
||||
->native(false)->default(now()),
|
||||
TextInput::make('received_by')->label('Received By'),
|
||||
Datepicker::make('date_received')->label('Date Received')->native(false),
|
||||
])
|
||||
->action(function ($data, $record) {
|
||||
$data['id'] = $record->id;
|
||||
(new StoreTransmittalCommand())->execute($data);
|
||||
})
|
||||
->icon('heroicon-o-pencil-square')
|
||||
->slideOver()
|
||||
->hidden(!auth()->user()->can('update_transmittal')),
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public static function generateExportNotification() : Notification {
|
||||
|
||||
|
||||
return Notification::make()
|
||||
->title('Your export will be ready. check your notification for file download link.')
|
||||
->success()
|
||||
->send();
|
||||
}
|
||||
|
||||
public static function exportTransmittal(array $id) : void {
|
||||
$recipient = auth()->user();
|
||||
|
||||
static::generateExportNotification();
|
||||
|
||||
(new TransmittalsExport([$id]))->store('public/transmittal-export.xlsx')->chain([
|
||||
app(ExportCompleteJob::class, [ 'user' => $recipient])
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListTransmittals::route('/'),
|
||||
'create' => Pages\CreateTransmittal::route('/create'),
|
||||
'view' => Pages\ViewTransmittal::route('/{record}'),
|
||||
'edit' => Pages\EditTransmittal::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\TransmittalResource\Pages;
|
||||
|
||||
use App\Exports\TransmittalsExport;
|
||||
use App\Filament\Resources\TransmittalResource;
|
||||
use App\Jobs\ExportCompleteJob;
|
||||
use Filament\Actions;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
use Filament\Support\Exceptions\Halt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Throwable;
|
||||
use Filament\Notifications\Actions\Action as NotificationAction;
|
||||
|
||||
class CreateTransmittal extends CreateRecord
|
||||
{
|
||||
protected static string $resource = TransmittalResource::class;
|
||||
|
||||
protected function getFormActions(): array
|
||||
{
|
||||
return [
|
||||
$this->getCreateFormAction(),
|
||||
$this->getCreateAnotherFormAction(),
|
||||
Action::make('Create and Export')->action('saveAndExport')->color('success'),
|
||||
$this->getCancelFormAction()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function saveAndExport(): void
|
||||
{
|
||||
$this->authorizeAccess();
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$this->callHook('beforeValidate');
|
||||
|
||||
$data = $this->form->getState();
|
||||
|
||||
$this->callHook('afterValidate');
|
||||
|
||||
$data = $this->mutateFormDataBeforeCreate($data);
|
||||
|
||||
$this->callHook('beforeCreate');
|
||||
|
||||
$this->record = $this->handleRecordCreation($data);
|
||||
|
||||
$this->form->model($this->getRecord())->saveRelationships();
|
||||
|
||||
$this->callHook('afterCreate');
|
||||
|
||||
DB::commit();
|
||||
} catch (Halt $exception) {
|
||||
$exception->shouldRollbackDatabaseTransaction() ?
|
||||
DB::rollBack() :
|
||||
DB::commit();
|
||||
|
||||
return;
|
||||
} catch (Throwable $exception) {
|
||||
DB::rollBack();
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
$this->rememberData();
|
||||
|
||||
TransmittalResource::exportTransmittal([$this->record->id]);
|
||||
|
||||
Notification::make()
|
||||
->success()
|
||||
->title('Transmittal Was Created Successfully!, Check your notification for file download link')
|
||||
->send();
|
||||
|
||||
}
|
||||
|
||||
public function getCreatedNotificationMessage(): ?string
|
||||
{
|
||||
return 'Transmittal Was Created Successfully!'; // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
protected function getRedirectUrl(): string
|
||||
{
|
||||
return $this->previousUrl ?? $this->getResource()::getUrl('index');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\TransmittalResource\Pages;
|
||||
|
||||
use App\Filament\Resources\TransmittalResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditTransmittal extends EditRecord
|
||||
{
|
||||
protected static string $resource = TransmittalResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\ViewAction::make(),
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\TransmittalResource\Pages;
|
||||
|
||||
use App\Filament\Resources\TransmittalResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListTransmittals extends ListRecords
|
||||
{
|
||||
protected static string $resource = TransmittalResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\TransmittalResource\Pages;
|
||||
|
||||
use App\Filament\Resources\TransmittalResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ViewRecord;
|
||||
|
||||
class ViewTransmittal extends ViewRecord
|
||||
{
|
||||
protected static string $resource = TransmittalResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\EditAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
74
app/Filament/Resources/UserResource.php
Normal file
74
app/Filament/Resources/UserResource.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Admin\Resources\UserResource\Pages;
|
||||
use App\Filament\Admin\Resources\UserResource\RelationManagers;
|
||||
use App\Models\User;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class UserResource extends Resource
|
||||
{
|
||||
protected static ?string $model = User::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-user-group';
|
||||
|
||||
protected static ?string $navigationGroup = 'Security Settings';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->columns([
|
||||
'default' => 2,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('name')->required()->columnSpan(2),
|
||||
TextInput::make('email')->required()->email()->columnSpan(fn () : int => $form->getOperation() === 'edit' ? 2 : 1),
|
||||
TextInput::make('password')->required()->password()->hiddenOn('edit'),
|
||||
Forms\Components\CheckboxList::make('roles')
|
||||
->relationship('roles', 'name')
|
||||
->searchable()
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('name')->searchable(),
|
||||
Tables\Columns\TextColumn::make('email')->searchable(),
|
||||
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make()->slideOver(),
|
||||
Tables\Actions\DeleteAction::make()->requiresConfirmation()
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => \App\Filament\Resources\UserResource\Pages\ListUsers::route('/'),
|
||||
];
|
||||
}
|
||||
}
|
||||
11
app/Filament/Resources/UserResource/Pages/CreateUser.php
Normal file
11
app/Filament/Resources/UserResource/Pages/CreateUser.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\UserResource\Pages;
|
||||
|
||||
use App\Filament\Resources\UserResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateUser extends CreateRecord
|
||||
{
|
||||
protected static string $resource = UserResource::class;
|
||||
}
|
||||
19
app/Filament/Resources/UserResource/Pages/EditUser.php
Normal file
19
app/Filament/Resources/UserResource/Pages/EditUser.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\UserResource\Pages;
|
||||
|
||||
use App\Filament\Resources\UserResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditUser extends EditRecord
|
||||
{
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
19
app/Filament/Resources/UserResource/Pages/ListUsers.php
Normal file
19
app/Filament/Resources/UserResource/Pages/ListUsers.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\UserResource\Pages;
|
||||
|
||||
use App\Filament\Resources\UserResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListUsers extends ListRecords
|
||||
{
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make()->icon('heroicon-o-user-plus')->slideOver(),
|
||||
];
|
||||
}
|
||||
}
|
||||
27
app/Http/Controllers/Auth/VerifyEmailController.php
Normal file
27
app/Http/Controllers/Auth/VerifyEmailController.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Foundation\Auth\EmailVerificationRequest;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class VerifyEmailController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the authenticated user's email address as verified.
|
||||
*/
|
||||
public function __invoke(EmailVerificationRequest $request): RedirectResponse
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
|
||||
}
|
||||
|
||||
if ($request->user()->markEmailAsVerified()) {
|
||||
event(new Verified($request->user()));
|
||||
}
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
|
||||
}
|
||||
}
|
||||
42
app/Jobs/ExportCompleteJob.php
Normal file
42
app/Jobs/ExportCompleteJob.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Filament\Notifications\Actions\Action as NotificationAction;
|
||||
use Filament\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ExportCompleteJob implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(private $user)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
Notification::make()->success()
|
||||
->title('Export Completed')
|
||||
->actions([
|
||||
NotificationAction::make('download_transmittal-export.xlsx')
|
||||
->label('Download File')
|
||||
->url(url: Storage::url('public/transmittal-export.xlsx') ,shouldOpenInNewTab: true)
|
||||
->markAsRead(),
|
||||
]
|
||||
)
|
||||
->sendToDatabase($this->user);
|
||||
}
|
||||
}
|
||||
20
app/Livewire/Actions/Logout.php
Normal file
20
app/Livewire/Actions/Logout.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Actions;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class Logout
|
||||
{
|
||||
/**
|
||||
* Log the current user out of the application.
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
Auth::guard('web')->logout();
|
||||
|
||||
Session::invalidate();
|
||||
Session::regenerateToken();
|
||||
}
|
||||
}
|
||||
72
app/Livewire/Forms/LoginForm.php
Normal file
72
app/Livewire/Forms/LoginForm.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Forms;
|
||||
|
||||
use Illuminate\Auth\Events\Lockout;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Form;
|
||||
|
||||
class LoginForm extends Form
|
||||
{
|
||||
#[Validate('required|string|email')]
|
||||
public string $email = '';
|
||||
|
||||
#[Validate('required|string')]
|
||||
public string $password = '';
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $remember = false;
|
||||
|
||||
/**
|
||||
* Attempt to authenticate the request's credentials.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function authenticate(): void
|
||||
{
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
if (! Auth::attempt($this->only(['email', 'password']), $this->remember)) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'form.email' => trans('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the authentication request is not rate limited.
|
||||
*/
|
||||
protected function ensureIsNotRateLimited(): void
|
||||
{
|
||||
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event(new Lockout(request()));
|
||||
|
||||
$seconds = RateLimiter::availableIn($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'form.email' => trans('auth.throttle', [
|
||||
'seconds' => $seconds,
|
||||
'minutes' => ceil($seconds / 60),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authentication rate limiting throttle key.
|
||||
*/
|
||||
protected function throttleKey(): string
|
||||
{
|
||||
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());
|
||||
}
|
||||
}
|
||||
24
app/Models/Account.php
Normal file
24
app/Models/Account.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Account extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded= [];
|
||||
|
||||
public function accountType() : BelongsTo
|
||||
{
|
||||
return $this->belongsTo(AccountType::class);
|
||||
}
|
||||
|
||||
public function client() : BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Client::class);
|
||||
}
|
||||
}
|
||||
25
app/Models/AccountType.php
Normal file
25
app/Models/AccountType.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class AccountType extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Get all of the accounts for the AccountType
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function accounts(): HasMany
|
||||
{
|
||||
return $this->hasMany(Account::class);
|
||||
}
|
||||
}
|
||||
|
||||
29
app/Models/Balance.php
Normal file
29
app/Models/Balance.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Balance extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function account(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ledger that owns the Balance
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function ledger(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Ledger::class);
|
||||
}
|
||||
}
|
||||
64
app/Models/Branch.php
Normal file
64
app/Models/Branch.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Branch extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Get the client that owns the Branch
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function client(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Client::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the series for the Branch
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function series(): HasMany
|
||||
{
|
||||
return $this->hasMany(Series::class);
|
||||
}
|
||||
|
||||
public function getCurrentSeriesAttribute()
|
||||
{
|
||||
if ($this->series()->count() > 0) {
|
||||
return $this->series()->orderBy('id', 'desc')->first()->series;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the sales for the Branch
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function sales(): HasMany
|
||||
{
|
||||
return $this->hasMany(Sale::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the expenses for the Branch
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function expenses(): HasMany
|
||||
{
|
||||
return $this->hasMany(Expense::class);
|
||||
}
|
||||
}
|
||||
70
app/Models/Client.php
Normal file
70
app/Models/Client.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Client extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $appends = ['vatable'];
|
||||
|
||||
public function getFullNameAttribute()
|
||||
{
|
||||
return $this->lname . ', ' . $this->fname . ' ' . $this->mname;
|
||||
}
|
||||
|
||||
public function getVatableAttribute()
|
||||
{
|
||||
return $this->type->type == 'Vatable' ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the branches for the Client
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function branches(): HasMany
|
||||
{
|
||||
return $this->hasMany(Branch::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type associated with the Client
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function type(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ClientType::class);
|
||||
}
|
||||
|
||||
public function accounts(): HasMany
|
||||
{
|
||||
return $this->hasMany(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* The users that belong to the Client
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(User::class);
|
||||
}
|
||||
|
||||
public function transmittals() : HasMany
|
||||
{
|
||||
return $this->hasMany(Transmittal::class);
|
||||
}
|
||||
|
||||
}
|
||||
13
app/Models/ClientType.php
Normal file
13
app/Models/ClientType.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ClientType extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'types';
|
||||
}
|
||||
13
app/Models/Comment.php
Normal file
13
app/Models/Comment.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Comment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
}
|
||||
11
app/Models/Expense.php
Normal file
11
app/Models/Expense.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Expense extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
30
app/Models/File.php
Normal file
30
app/Models/File.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class File extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function transmittal(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Transmittal::class);
|
||||
}
|
||||
|
||||
public function notes(): HasMany
|
||||
{
|
||||
return $this->hasMany(Comment::class);
|
||||
}
|
||||
|
||||
public function remarks(): HasMany
|
||||
{
|
||||
return $this->hasMany(Remark::class);
|
||||
}
|
||||
}
|
||||
33
app/Models/Journal.php
Normal file
33
app/Models/Journal.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\HasPeriod;
|
||||
use App\Traits\HasUser;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
class Journal extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = ['happened_on' => 'date'];
|
||||
|
||||
public function ledger(): HasOne
|
||||
{
|
||||
return $this->hasOne(Ledger::class);
|
||||
}
|
||||
|
||||
public function scopeDateCreatedFilter(Builder $query, $date) : Builder
|
||||
{
|
||||
$dates = explode(' to ',$date);
|
||||
if (isset($dates[1])) {
|
||||
return $query->whereBetween('happened_on' ,[$dates[0], $dates[1]]);
|
||||
}
|
||||
return $query->where('happened_on', $dates[0]);
|
||||
}
|
||||
}
|
||||
65
app/Models/Ledger.php
Normal file
65
app/Models/Ledger.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Ledger extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function scopeIsTransaction($query)
|
||||
{
|
||||
return $query->whereNotNull('transaction_id');
|
||||
}
|
||||
|
||||
public function scopeIsJournal($query)
|
||||
{
|
||||
return $query->whereNull('transaction_id');
|
||||
}
|
||||
|
||||
public function account(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
public function journal(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Journal::class);
|
||||
}
|
||||
|
||||
public function transaction() : BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Transaction::class);
|
||||
}
|
||||
|
||||
public function scopeDateCreatedFilter(Builder $query, $date) : Builder
|
||||
{
|
||||
$dates = explode(' to ',$date);
|
||||
if (isset($dates[1])) {
|
||||
return $query->whereHas('transaction', function ($transaction) use ($dates) {
|
||||
$transaction->whereBetween('happened_on' ,[$dates[0], $dates[1]]);
|
||||
});
|
||||
}
|
||||
return $query->whereHas('transaction', function ($transaction) use ($dates) {
|
||||
$transaction->where('created_at', $dates[0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the balances for the Ledger
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function balances(): HasMany
|
||||
{
|
||||
return $this->hasMany(Balance::class);
|
||||
}
|
||||
|
||||
}
|
||||
23
app/Models/PermissionType.php
Normal file
23
app/Models/PermissionType.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
|
||||
class PermissionType extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Get all of the permissions for the PermissionType
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function permissions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Permission::class);
|
||||
}
|
||||
}
|
||||
13
app/Models/Remark.php
Normal file
13
app/Models/Remark.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Remark extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
}
|
||||
11
app/Models/Sale.php
Normal file
11
app/Models/Sale.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Sale extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
11
app/Models/SaleSeries.php
Normal file
11
app/Models/SaleSeries.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SaleSeries extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
19
app/Models/Series.php
Normal file
19
app/Models/Series.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Series extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
// public function setSeriesAttribute($value)
|
||||
// {
|
||||
// $this->attributes['series'] = str_pad($value, 6, '0', STR_PAD_LEFT);
|
||||
// }
|
||||
}
|
||||
55
app/Models/Transaction.php
Normal file
55
app/Models/Transaction.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Transaction extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Get the expense that owns the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function expense(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Expense::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sale that owns the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function sale(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Sale::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the account that owns the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function account(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ledgers associated with the Transaction
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function ledgers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Ledger::class);
|
||||
}
|
||||
}
|
||||
82
app/Models/Transmittal.php
Normal file
82
app/Models/Transmittal.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Laravel\Prompts\Note;
|
||||
|
||||
class Transmittal extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'date_created' => 'date',
|
||||
'date_dispatch' => 'date',
|
||||
'date_received' => 'date'
|
||||
];
|
||||
|
||||
public function files(): HasMany
|
||||
{
|
||||
return $this->hasMany(File::class);
|
||||
}
|
||||
|
||||
public function notes(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Comment::class, File::class);
|
||||
}
|
||||
|
||||
public function remarks(): HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Remark::class, File::class);
|
||||
}
|
||||
|
||||
public function client(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Client::class);
|
||||
}
|
||||
|
||||
public function branch(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Branch::class);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function scopeDateCreatedFilter(Builder $query, $date) : Builder
|
||||
{
|
||||
$dates = explode(' to ',$date);
|
||||
if(isset($dates[1])) {
|
||||
return $query->whereBetween('date_created' ,[$dates[0], $dates[1]]);
|
||||
}
|
||||
return $query->where('date_created', $dates[0]);
|
||||
}
|
||||
|
||||
public function scopeDateDispatchedFilter(Builder $query, $date) : Builder
|
||||
{
|
||||
$dates = explode(' to ',$date);
|
||||
if(isset($dates[1])) {
|
||||
return $query->whereBetween('date_dispatch', [$dates[0], $dates[1]]);
|
||||
}
|
||||
|
||||
return $query->where('date_dispatch', $dates[0]);
|
||||
}
|
||||
|
||||
public function scopeDateReceivedFilter(Builder $query, $date) : Builder
|
||||
{
|
||||
$dates = explode(' to ',$date);
|
||||
if(isset($dates[1])) {
|
||||
return $query->whereBetween('date_received', [$dates[0], $dates[1]]);
|
||||
}
|
||||
return $query->where('date_received', $dates[0]);
|
||||
}
|
||||
}
|
||||
11
app/Models/Type.php
Normal file
11
app/Models/Type.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Type extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
@@ -3,13 +3,17 @@
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use BezhanSalleh\FilamentShield\Traits\HasPanelShield;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Spatie\Permission\Traits\HasPermissions;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasFactory, Notifiable;
|
||||
use HasFactory, Notifiable, HasRoles, HasPermissions;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
||||
108
app/Policies/ClientPolicy.php
Normal file
108
app/Policies/ClientPolicy.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Client;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class ClientPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Client $client): bool
|
||||
{
|
||||
return $user->can('view_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Client $client): bool
|
||||
{
|
||||
return $user->can('update_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Client $client): bool
|
||||
{
|
||||
return $user->can('delete_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, Client $client): bool
|
||||
{
|
||||
return $user->can('force_delete_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, Client $client): bool
|
||||
{
|
||||
return $user->can('restore_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, Client $client): bool
|
||||
{
|
||||
return $user->can('replicate_client');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_client');
|
||||
}
|
||||
}
|
||||
108
app/Policies/RolePolicy.php
Normal file
108
app/Policies/RolePolicy.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class RolePolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_shield::role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Role $role): bool
|
||||
{
|
||||
return $user->can('view_shield::role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_shield::role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Role $role): bool
|
||||
{
|
||||
return $user->can('update_shield::role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Role $role): bool
|
||||
{
|
||||
return $user->can('delete_shield::role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_shield::role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, Role $role): bool
|
||||
{
|
||||
return $user->can('{{ ForceDelete }}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('{{ ForceDeleteAny }}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, Role $role): bool
|
||||
{
|
||||
return $user->can('{{ Restore }}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('{{ RestoreAny }}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, Role $role): bool
|
||||
{
|
||||
return $user->can('{{ Replicate }}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('{{ Reorder }}');
|
||||
}
|
||||
}
|
||||
108
app/Policies/TransmittalPolicy.php
Normal file
108
app/Policies/TransmittalPolicy.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Transmittal;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class TransmittalPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Transmittal $transmittal): bool
|
||||
{
|
||||
return $user->can('view_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Transmittal $transmittal): bool
|
||||
{
|
||||
return $user->can('update_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Transmittal $transmittal): bool
|
||||
{
|
||||
return $user->can('delete_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, Transmittal $transmittal): bool
|
||||
{
|
||||
return $user->can('force_delete_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, Transmittal $transmittal): bool
|
||||
{
|
||||
return $user->can('restore_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, Transmittal $transmittal): bool
|
||||
{
|
||||
return $user->can('replicate_transmittal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_transmittal');
|
||||
}
|
||||
}
|
||||
144
app/Policies/UserPolicy.php
Normal file
144
app/Policies/UserPolicy.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class UserPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function view(User $user): bool
|
||||
{
|
||||
return $user->can('view_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function update(User $user): bool
|
||||
{
|
||||
return $user->can('update_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(User $user): bool
|
||||
{
|
||||
return $user->can('delete_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function forceDelete(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function restore(User $user): bool
|
||||
{
|
||||
return $user->can('restore_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function replicate(User $user): bool
|
||||
{
|
||||
return $user->can('replicate_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_user');
|
||||
}
|
||||
}
|
||||
23
app/Processes/BaseProcess.php
Normal file
23
app/Processes/BaseProcess.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Processes;
|
||||
|
||||
use Illuminate\Support\Facades\Pipeline;
|
||||
|
||||
abstract class BaseProcess
|
||||
{
|
||||
/**
|
||||
* @var array<class-string>
|
||||
*
|
||||
*/
|
||||
protected array $tasks = [];
|
||||
|
||||
public function run(mixed $payload): mixed
|
||||
{
|
||||
return Pipeline::send(
|
||||
passable: $payload,
|
||||
)->through(
|
||||
pipes: $this->tasks,
|
||||
)->thenReturn();
|
||||
}
|
||||
}
|
||||
15
app/Processes/Branch/CreateBranchProcess.php
Normal file
15
app/Processes/Branch/CreateBranchProcess.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Processes\Branch;
|
||||
|
||||
use App\Actions\Branch\StoreBranch;
|
||||
use App\Actions\Branch\StoreBranchSeries;
|
||||
use App\Processes\BaseProcess;
|
||||
|
||||
class CreateBranchProcess extends BaseProcess
|
||||
{
|
||||
protected array $tasks = [
|
||||
StoreBranch::class,
|
||||
StoreBranchSeries::class
|
||||
];
|
||||
}
|
||||
15
app/Processes/Transmittal/CreateTransmittalProcess.php
Normal file
15
app/Processes/Transmittal/CreateTransmittalProcess.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Processes\Transmittal;
|
||||
|
||||
use App\Actions\Transmittal\CreateTransmittal;
|
||||
use App\Actions\Transmittal\CreateTransmittalFiles;
|
||||
use App\Processes\BaseProcess;
|
||||
|
||||
class CreateTransmittalProcess extends BaseProcess
|
||||
{
|
||||
public array $tasks = [
|
||||
CreateTransmittal::class,
|
||||
CreateTransmittalFiles::class
|
||||
];
|
||||
}
|
||||
78
app/Providers/Filament/AdminPanelProvider.php
Normal file
78
app/Providers/Filament/AdminPanelProvider.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers\Filament;
|
||||
|
||||
use Filament\Http\Middleware\Authenticate;
|
||||
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||
use Filament\Pages;
|
||||
use Filament\Panel;
|
||||
use Filament\PanelProvider;
|
||||
use Filament\Support\Colors\Color;
|
||||
use Filament\Widgets;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||
use Illuminate\Session\Middleware\AuthenticateSession;
|
||||
use Illuminate\Session\Middleware\StartSession;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
|
||||
class AdminPanelProvider extends PanelProvider
|
||||
{
|
||||
public function panel(Panel $panel): Panel
|
||||
{
|
||||
return $panel
|
||||
->default()
|
||||
->id('admin')
|
||||
->path('admin')
|
||||
->login()
|
||||
->colors([
|
||||
'primary' => Color::Amber,
|
||||
])
|
||||
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
|
||||
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
|
||||
->pages([
|
||||
Pages\Dashboard::class,
|
||||
])
|
||||
->databaseNotifications()
|
||||
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
|
||||
->widgets([
|
||||
Widgets\AccountWidget::class,
|
||||
])
|
||||
->middleware([
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartSession::class,
|
||||
AuthenticateSession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
SubstituteBindings::class,
|
||||
DisableBladeIconComponents::class,
|
||||
DispatchServingFilamentEvent::class,
|
||||
])
|
||||
->authMiddleware([
|
||||
Authenticate::class,
|
||||
])
|
||||
->plugins([
|
||||
\BezhanSalleh\FilamentShield\FilamentShieldPlugin::make()
|
||||
->gridColumns([
|
||||
'default' => 1,
|
||||
'sm' => 2,
|
||||
'lg' => 3
|
||||
])
|
||||
->sectionColumnSpan(1)
|
||||
->checkboxListColumns([
|
||||
'default' => 1,
|
||||
'sm' => 2,
|
||||
'lg' => 4,
|
||||
])
|
||||
->resourceCheckboxListColumns([
|
||||
'default' => 1,
|
||||
'sm' => 2,
|
||||
]),
|
||||
])
|
||||
->viteTheme('resources/css/filament/admin/theme.css')
|
||||
;
|
||||
}
|
||||
}
|
||||
28
app/Providers/VoltServiceProvider.php
Normal file
28
app/Providers/VoltServiceProvider.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Livewire\Volt\Volt;
|
||||
|
||||
class VoltServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
Volt::mount([
|
||||
config('livewire.view_path', resource_path('views/livewire')),
|
||||
resource_path('views/pages'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
17
app/View/Components/AppLayout.php
Normal file
17
app/View/Components/AppLayout.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AppLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*/
|
||||
public function render(): View
|
||||
{
|
||||
return view('layouts.app');
|
||||
}
|
||||
}
|
||||
17
app/View/Components/GuestLayout.php
Normal file
17
app/View/Components/GuestLayout.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class GuestLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*/
|
||||
public function render(): View
|
||||
{
|
||||
return view('layouts.guest');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user