Giant Update

This commit is contained in:
Wian Drs
2026-07-31 13:57:11 +07:00
parent f68d967c8b
commit b0d08211ec
112 changed files with 6674 additions and 3 deletions
@@ -0,0 +1,61 @@
<?php
namespace App\Http\Controllers\Billing;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Billing\IndexBillingRequest;
use App\Http\Requests\Billing\StoreBillingProfileRequest;
use App\Http\Requests\Billing\UpdateBillingProfileRequest;
use App\Http\Resources\Billing\BillingProfileResource;
use App\Services\Billing\BillingProfileService;
use Illuminate\Http\Request;
class BillingProfileController extends ApiController
{
public function __construct(protected BillingProfileService $service) {}
public function index(IndexBillingRequest $request)
{
return $this->successPaginated($this->service->list($request->validated(), $request->user(), $this->tenantId($request)), BillingProfileResource::class, 'Daftar profile tagihan berhasil diambil');
}
public function store(StoreBillingProfileRequest $request)
{
return $this->created(new BillingProfileResource($this->service->create($request->validated(), $request->user(), $this->tenantId($request))), 'Profile tagihan berhasil dibuat');
}
public function show(Request $request, int $id)
{
$profile = $this->service->find($id);
$this->authorizeTenant($request, $profile->tenant_id);
return $this->success(new BillingProfileResource($profile), 'Detail profile tagihan berhasil diambil');
}
public function update(UpdateBillingProfileRequest $request, int $id)
{
$profile = $this->service->find($id);
$this->authorizeTenant($request, $profile->tenant_id);
return $this->updated(new BillingProfileResource($this->service->update($profile, $request->validated(), $request->user())), 'Profile tagihan berhasil diperbarui');
}
public function destroy(Request $request, int $id)
{
$profile = $this->service->find($id);
$this->authorizeTenant($request, $profile->tenant_id);
$this->service->delete($profile);
return $this->deleted('Profile tagihan berhasil dihapus');
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
private function authorizeTenant(Request $request, int $tenantId): void
{
abort_unless($request->user()->isMasterAdmin() || $tenantId === $this->tenantId($request), 403);
}
}
@@ -0,0 +1,79 @@
<?php
namespace App\Http\Controllers\Billing;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Billing\IndexBillingRequest;
use App\Http\Requests\Billing\PayInvoiceRequest;
use App\Http\Requests\Billing\StoreInvoiceRequest;
use App\Http\Requests\Billing\UpdateInvoiceRequest;
use App\Http\Resources\Billing\InvoiceResource;
use App\Services\Billing\InvoiceService;
use Illuminate\Http\Request;
class InvoiceController extends ApiController
{
public function __construct(protected InvoiceService $service) {}
public function index(IndexBillingRequest $request)
{
return $this->successPaginated($this->service->list($this->scope($request), $request->validated(), $request->user(), $this->tenantId($request)), InvoiceResource::class, 'Daftar tagihan berhasil diambil');
}
public function options(Request $request)
{
return $this->success($this->service->options($request->user(), $this->tenantId($request)), 'Pilihan tagihan berhasil diambil');
}
public function store(StoreInvoiceRequest $request)
{
return $this->created(new InvoiceResource($this->service->create($request->validated(), $request->user(), $this->tenantId($request))), 'Tagihan berhasil dibuat');
}
public function show(Request $request, int $id)
{
$invoice = $this->service->find($id);
$this->authorizeTenant($request, $invoice->tenant_id);
return $this->success(new InvoiceResource($invoice), 'Detail tagihan berhasil diambil');
}
public function update(UpdateInvoiceRequest $request, int $id)
{
$invoice = $this->service->find($id);
$this->authorizeTenant($request, $invoice->tenant_id);
return $this->updated(new InvoiceResource($this->service->update($invoice, $request->validated(), $request->user())), 'Tagihan berhasil diperbarui');
}
public function pay(PayInvoiceRequest $request, int $id)
{
$invoice = $this->service->find($id);
$this->authorizeTenant($request, $invoice->tenant_id);
return $this->updated(new InvoiceResource($this->service->pay($invoice, $request->validated(), $request->user())), 'Pembayaran manual berhasil dicatat');
}
public function cancel(Request $request, int $id)
{
$invoice = $this->service->find($id);
$this->authorizeTenant($request, $invoice->tenant_id);
return $this->updated(new InvoiceResource($this->service->cancel($invoice, $request->user())), 'Tagihan berhasil dibatalkan');
}
private function scope(Request $request): string
{
return $request->route()->defaults['invoice_scope'] ?? 'running';
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
private function authorizeTenant(Request $request, int $tenantId): void
{
abort_unless($request->user()->isMasterAdmin() || $tenantId === $this->tenantId($request), 403);
}
}
@@ -0,0 +1,118 @@
<?php
namespace App\Http\Controllers\Customer;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Customer\ActivateCustomerRequest;
use App\Http\Requests\Customer\IndexCustomerRequest;
use App\Http\Requests\Customer\StoreCustomerRequest;
use App\Http\Requests\Customer\UpdateCustomerRequest;
use App\Http\Resources\Customer\CustomerResource;
use App\Services\Customer\CustomerService;
use Illuminate\Http\Request;
class CustomerController extends ApiController
{
public function __construct(protected CustomerService $service) {}
public function index(IndexCustomerRequest $request)
{
return $this->successPaginated(
$this->service->list($this->scope($request), $request->validated(), $request->user(), $this->tenantId($request)),
CustomerResource::class,
'Daftar customer berhasil diambil'
);
}
public function options(Request $request)
{
return $this->success(
$this->service->options($request->user(), $this->tenantId($request)),
'Pilihan relasi customer berhasil diambil'
);
}
public function store(StoreCustomerRequest $request)
{
return $this->created(
new CustomerResource($this->service->create($request->validated(), $request->user(), $this->tenantId($request))),
'Customer berhasil didaftarkan'
);
}
public function show(Request $request, int $id)
{
$customer = $this->service->find($id, $this->scope($request) === 'trash');
$this->authorizeTenant($request, $customer->tenant_id);
return $this->success(new CustomerResource($customer), 'Detail customer berhasil diambil');
}
public function update(UpdateCustomerRequest $request, int $id)
{
$customer = $this->service->find($id);
$this->authorizeTenant($request, $customer->tenant_id);
return $this->updated(
new CustomerResource($this->service->update($customer, $request->validated(), $request->user())),
'Data customer berhasil diperbarui'
);
}
public function activate(ActivateCustomerRequest $request, int $id)
{
$customer = $this->service->find($id);
$this->authorizeTenant($request, $customer->tenant_id);
return $this->updated(new CustomerResource($this->service->activate($customer, $request->validated())), 'Customer berhasil diaktifkan');
}
public function deactivate(Request $request, int $id)
{
$customer = $this->service->find($id);
$this->authorizeTenant($request, $customer->tenant_id);
return $this->updated(new CustomerResource($this->service->deactivate($customer)), 'Customer berhasil dinonaktifkan');
}
public function destroy(Request $request, int $id)
{
$customer = $this->service->find($id);
$this->authorizeTenant($request, $customer->tenant_id);
$this->service->trash($customer);
return $this->deleted('Customer dipindahkan ke Sampah');
}
public function restore(Request $request, int $id)
{
$customer = $this->service->find($id, true);
$this->authorizeTenant($request, $customer->tenant_id);
return $this->updated(new CustomerResource($this->service->restore($customer)), 'Customer berhasil dipulihkan');
}
public function forceDelete(Request $request, int $id)
{
$customer = $this->service->find($id, true);
$this->authorizeTenant($request, $customer->tenant_id);
$this->service->forceDelete($customer);
return $this->deleted('Customer dihapus permanen');
}
private function scope(Request $request): string
{
return $request->route()->defaults['customer_scope'] ?? 'orders';
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
private function authorizeTenant(Request $request, int $tenantId): void
{
abort_unless($request->user()->isMasterAdmin() || $tenantId === $this->tenantId($request), 403);
}
}
@@ -0,0 +1,192 @@
<?php
namespace App\Http\Controllers\Notification;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Notification\IndexNotificationRequest;
use App\Http\Requests\Notification\SaveNotificationPreferencesRequest;
use App\Http\Requests\Notification\StoreCustomerContactRequest;
use App\Http\Requests\Notification\StoreNotificationBroadcastRequest;
use App\Http\Requests\Notification\StoreNotificationChannelRequest;
use App\Http\Requests\Notification\StoreNotificationTemplateRequest;
use App\Http\Resources\Notification\NotificationDeliveryResource;
use App\Models\Customer;
use App\Models\CustomerContact;
use App\Models\NotificationBroadcast;
use App\Models\NotificationChannel;
use App\Models\NotificationEvent;
use App\Models\NotificationTemplate;
use App\Services\Notification\NotificationService;
use Illuminate\Http\Request;
class NotificationController extends ApiController
{
public function __construct(protected NotificationService $service) {}
public function events()
{
return $this->success(NotificationEvent::where('enabled', true)->orderBy('category')->orderBy('name')->get(), 'Daftar event notifikasi berhasil diambil');
}
public function channels(Request $request)
{
return $this->success($this->service->channels($this->channel($request), $request->user(), $this->tenantId($request)), 'Konfigurasi channel berhasil diambil');
}
public function storeChannel(StoreNotificationChannelRequest $request)
{
abort_unless($request->validated('channel') === $this->channel($request), 422);
return $this->created($this->service->saveChannel($request->validated(), $request->user(), $this->tenantId($request)), 'Konfigurasi channel berhasil dibuat');
}
public function updateChannel(StoreNotificationChannelRequest $request, NotificationChannel $notificationChannel)
{
$this->authorizeTenant($request, $notificationChannel->tenant_id);
abort_unless($notificationChannel->channel === $this->channel($request), 404);
return $this->updated($this->service->saveChannel($request->validated(), $request->user(), $this->tenantId($request), $notificationChannel), 'Konfigurasi channel berhasil diperbarui');
}
public function testChannel(Request $request, NotificationChannel $notificationChannel)
{
$this->authorizeTenant($request, $notificationChannel->tenant_id);
abort_unless($notificationChannel->channel === $this->channel($request), 404);
return $this->success($this->service->testChannel($notificationChannel), 'Pengujian channel selesai');
}
public function templates(Request $request)
{
return $this->success($this->service->templates($this->channel($request), $request->user(), $this->tenantId($request)), 'Daftar template berhasil diambil');
}
public function storeTemplate(StoreNotificationTemplateRequest $request)
{
abort_unless($request->validated('channel') === $this->channel($request), 422);
return $this->created($this->service->saveTemplate($request->validated(), $request->user(), $this->tenantId($request)), 'Template berhasil dibuat');
}
public function updateTemplate(StoreNotificationTemplateRequest $request, NotificationTemplate $notificationTemplate)
{
if ($notificationTemplate->tenant_id) {
$this->authorizeTenant($request, $notificationTemplate->tenant_id);
}
abort_unless($notificationTemplate->channel === $this->channel($request), 404);
return $this->updated($this->service->saveTemplate($request->validated(), $request->user(), $this->tenantId($request), $notificationTemplate), 'Template berhasil diperbarui');
}
public function preferences(Request $request)
{
$tenantId = $request->user()->isMasterAdmin() && $request->integer('tenant_id')
? $request->integer('tenant_id')
: $this->tenantId($request);
return $this->success($this->service->preferences($request->user(), $tenantId), 'Preference notifikasi berhasil diambil');
}
public function savePreferences(SaveNotificationPreferencesRequest $request)
{
$this->service->savePreferences($request->validated('preferences'), $request->user(), $this->tenantId($request));
return $this->updated(null, 'Preference notifikasi berhasil disimpan');
}
public function deliveries(IndexNotificationRequest $request)
{
return $this->successPaginated(
$this->service->deliveries($this->channel($request), $request->validated(), $request->user(), $this->tenantId($request)),
NotificationDeliveryResource::class,
'Log pesan berhasil diambil',
);
}
public function broadcasts(IndexNotificationRequest $request)
{
return $this->success($this->service->broadcasts($request->validated(), $request->user(), $this->tenantId($request)), 'Daftar pesan siaran berhasil diambil');
}
public function previewBroadcast(StoreNotificationBroadcastRequest $request)
{
return $this->success($this->service->previewBroadcast($request->validated(), $request->user(), $this->tenantId($request)), 'Preview penerima berhasil dihitung');
}
public function storeBroadcast(StoreNotificationBroadcastRequest $request)
{
return $this->created($this->service->createBroadcast($request->validated(), $request->user(), $this->tenantId($request)), 'Pesan siaran masuk antrean');
}
public function showBroadcast(Request $request, NotificationBroadcast $notificationBroadcast)
{
$this->authorizeTenant($request, $notificationBroadcast->tenant_id);
return $this->success($notificationBroadcast->load(['template', 'channelConfig', 'recipients.customer:id,customer_code,name']), 'Detail siaran berhasil diambil');
}
public function approveBroadcast(Request $request, NotificationBroadcast $notificationBroadcast)
{
$this->authorizeTenant($request, $notificationBroadcast->tenant_id);
return $this->updated($this->service->approveBroadcast($notificationBroadcast, $request->user()), 'Pesan siaran berhasil disetujui');
}
public function myNotifications(IndexNotificationRequest $request)
{
return $this->success($this->service->userNotifications($request->user(), $request->validated()), 'Notifikasi aplikasi berhasil diambil');
}
public function markRead(Request $request, string $uuid)
{
$notification = $request->user()->userNotifications()->where('uuid', $uuid)->firstOrFail();
$notification->update(['read_at' => now()]);
return $this->updated($notification, 'Notifikasi ditandai sudah dibaca');
}
public function contacts(Request $request, Customer $customer)
{
$this->authorizeTenant($request, $customer->tenant_id);
return $this->success($customer->contacts()->orderBy('type')->orderByDesc('is_primary')->get(), 'Kontak notifikasi berhasil diambil');
}
public function storeContact(StoreCustomerContactRequest $request, Customer $customer)
{
$this->authorizeTenant($request, $customer->tenant_id);
return $this->created($this->service->saveContact($customer, $request->validated()), 'Kontak notifikasi berhasil dibuat');
}
public function updateContact(StoreCustomerContactRequest $request, Customer $customer, CustomerContact $contact)
{
$this->authorizeTenant($request, $customer->tenant_id);
return $this->updated($this->service->saveContact($customer, $request->validated(), $contact), 'Kontak notifikasi berhasil diperbarui');
}
public function destroyContact(Request $request, Customer $customer, CustomerContact $contact)
{
$this->authorizeTenant($request, $customer->tenant_id);
abort_unless((int) $contact->customer_id === (int) $customer->id, 404);
$contact->delete();
return $this->deleted('Kontak notifikasi berhasil dihapus');
}
private function channel(Request $request): string
{
return $request->route()->defaults['notification_channel'];
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
private function authorizeTenant(Request $request, int $tenantId): void
{
abort_unless($request->user()->isMasterAdmin() || $tenantId === $this->tenantId($request), 403);
}
}
@@ -0,0 +1,90 @@
<?php
namespace App\Http\Controllers\Notification;
use App\Http\Controllers\Controller;
use App\Models\NotificationChannel;
use App\Models\NotificationDelivery;
use App\Models\NotificationWebhookLog;
use Illuminate\Http\Request;
class NotificationWebhookController extends Controller
{
public function verify(Request $request, NotificationChannel $notificationChannel)
{
abort_unless(
$request->query('hub.mode') === 'subscribe'
&& hash_equals((string) data_get($notificationChannel->credentials, 'webhook_verify_token'), (string) $request->query('hub.verify_token')),
403,
);
return response($request->query('hub.challenge'), 200);
}
public function handle(Request $request, NotificationChannel $notificationChannel)
{
$valid = $this->validSignature($request, $notificationChannel);
$payload = $request->all();
$updates = $this->updates($payload);
$log = NotificationWebhookLog::create([
'notification_channel_id' => $notificationChannel->id,
'provider' => $notificationChannel->provider,
'event_type' => data_get($payload, 'entry.0.changes.0.field') ?? data_get($payload, 'event'),
'provider_message_id' => data_get($updates, '0.id'),
'signature_valid' => $valid,
'payload' => $payload,
]);
abort_unless($valid, 401);
foreach ($updates as $update) {
$delivery = NotificationDelivery::where('provider_message_id', $update['id'] ?? null)->first();
if (! $delivery) {
continue;
}
$status = match ($update['status'] ?? null) {
'delivered' => 'delivered',
'read' => 'read',
'failed' => 'failed',
default => 'sent',
};
$delivery->update([
'status' => $status,
'delivered_at' => $status === 'delivered' ? now() : $delivery->delivered_at,
'read_at' => $status === 'read' ? now() : $delivery->read_at,
'failed_at' => $status === 'failed' ? now() : $delivery->failed_at,
'error_code' => data_get($update, 'errors.0.code'),
'error_message' => data_get($update, 'errors.0.title'),
]);
}
$log->update(['processed_at' => now()]);
return response()->json(['success' => true]);
}
private function validSignature(Request $request, NotificationChannel $channel): bool
{
if ($channel->channel === 'whatsapp_official') {
$secret = data_get($channel->credentials, 'app_secret');
$signature = $request->header('X-Hub-Signature-256');
return $secret && $signature && hash_equals('sha256='.hash_hmac('sha256', $request->getContent(), $secret), $signature);
}
$secret = data_get($channel->credentials, 'webhook_secret');
return $secret && hash_equals((string) $secret, (string) $request->header('X-Webhook-Secret'));
}
private function updates(array $payload): array
{
$statuses = data_get($payload, 'entry.0.changes.0.value.statuses');
if (is_array($statuses)) {
return $statuses;
}
return [[
'id' => data_get($payload, 'message_id') ?? data_get($payload, 'id'),
'status' => data_get($payload, 'status') ?? data_get($payload, 'event'),
'errors' => data_get($payload, 'errors', []),
]];
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Http\Controllers\Payment;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Payment\IndexPaymentRequest;
use App\Http\Requests\Payment\SaveTenantPaymentSettingRequest;
use App\Http\Requests\Payment\StoreGatewayAccountRequest;
use App\Http\Resources\Payment\PaymentTransactionResource;
use App\Models\PaymentGatewayAccount;
use App\Services\Payment\PaymentGatewayService;
use Illuminate\Http\Request;
class PaymentGatewayController extends ApiController
{
public function __construct(protected PaymentGatewayService $service) {}
public function providers()
{
return $this->success($this->service->providers(), 'Daftar provider berhasil diambil');
}
public function settings(Request $request)
{
return $this->success($this->service->settings($request->user(), $this->tenantId($request)), 'Pengaturan payment gateway berhasil diambil');
}
public function storeAccount(StoreGatewayAccountRequest $request)
{
return $this->created($this->service->saveAccount($request->validated(), $request->user(), $this->tenantId($request)), 'Akun gateway berhasil dibuat');
}
public function updateAccount(StoreGatewayAccountRequest $request, PaymentGatewayAccount $account)
{
return $this->updated($this->service->saveAccount($request->validated(), $request->user(), $this->tenantId($request), $account), 'Akun gateway berhasil diperbarui');
}
public function saveSetting(SaveTenantPaymentSettingRequest $request)
{
return $this->updated($this->service->saveTenantSetting($request->validated(), $request->user(), $this->tenantId($request)), 'Mode pembayaran tenant berhasil disimpan');
}
public function transactions(IndexPaymentRequest $request)
{
return $this->successPaginated($this->service->transactions($request->validated(), $request->user(), $this->tenantId($request)), PaymentTransactionResource::class, 'Log pembayaran berhasil diambil');
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
}
@@ -0,0 +1,154 @@
<?php
namespace App\Http\Controllers\Topology;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Topology\IndexTopologyRequest;
use App\Http\Requests\Topology\StoreCustomerConnectionRequest;
use App\Http\Requests\Topology\StoreTopologyRequest;
use App\Http\Requests\Topology\UpdateTopologyRequest;
use App\Http\Resources\Topology\TopologyResource;
use App\Models\Customer;
use App\Models\TopologyNode;
use App\Models\TopologyPort;
use App\Services\Topology\TopologyService;
use Illuminate\Http\Request;
class TopologyController extends ApiController
{
public function __construct(protected TopologyService $service) {}
public function index(IndexTopologyRequest $request)
{
return $this->successPaginated(
$this->service->list($this->resource($request), $request->validated(), $request->user(), $this->tenantId($request)),
TopologyResource::class,
'Daftar topologi berhasil diambil',
);
}
public function store(StoreTopologyRequest $request)
{
return $this->created(
new TopologyResource($this->service->create($this->resource($request), $request->validated(), $request->user(), $this->tenantId($request))),
'Data topologi berhasil dibuat',
);
}
public function show(Request $request, int $id)
{
$model = $this->service->find($this->resource($request), $id);
$this->authorizeModel($request, $model);
return $this->success(new TopologyResource($model), 'Detail topologi berhasil diambil');
}
public function update(UpdateTopologyRequest $request, int $id)
{
$resource = $this->resource($request);
$model = $this->service->find($resource, $id);
$this->authorizeModel($request, $model, true);
return $this->updated(
new TopologyResource($this->service->update($resource, $model, $request->validated(), $request->user())),
'Data topologi berhasil diperbarui',
);
}
public function destroy(Request $request, int $id)
{
$resource = $this->resource($request);
$model = $this->service->find($resource, $id);
$this->authorizeModel($request, $model, true);
$this->service->delete($resource, $model);
return $this->deleted('Data topologi berhasil dihapus');
}
public function options(Request $request)
{
return $this->success($this->service->options($request->user(), $this->tenantId($request)), 'Pilihan topologi berhasil diambil');
}
public function map(IndexTopologyRequest $request)
{
return $this->success($this->service->map($request->validated(), $request->user(), $this->tenantId($request)), 'Data peta topologi berhasil diambil');
}
public function ports(Request $request, TopologyNode $node)
{
$this->authorizeTenant($request, $node->tenant_id);
return $this->success($this->service->ports($node), 'Daftar port berhasil diambil');
}
public function storePort(StoreTopologyRequest $request, TopologyNode $node)
{
$this->authorizeTenant($request, $node->tenant_id);
return $this->created($this->service->createPort($node, $request->validated()), 'Port berhasil dibuat');
}
public function updatePort(UpdateTopologyRequest $request, TopologyPort $port)
{
$this->authorizeTenant($request, $port->tenant_id);
return $this->updated($this->service->updatePort($port, $request->validated()), 'Port berhasil diperbarui');
}
public function destroyPort(Request $request, TopologyPort $port)
{
$this->authorizeTenant($request, $port->tenant_id);
$this->service->deletePort($port);
return $this->deleted('Port berhasil dihapus');
}
public function trace(Request $request, TopologyNode $node, string $direction)
{
abort_unless(in_array($direction, ['upstream', 'downstream'], true), 404);
$this->authorizeTenant($request, $node->tenant_id);
return $this->success($this->service->trace($node, $direction), 'Jalur topologi berhasil ditelusuri');
}
public function connectCustomer(StoreCustomerConnectionRequest $request)
{
return $this->created(
$this->service->connectCustomer($request->validated(), $request->user(), $this->tenantId($request)),
'Customer berhasil dihubungkan ke ODP',
);
}
public function customerPath(Request $request, Customer $customer)
{
$this->authorizeTenant($request, $customer->tenant_id);
return $this->success($this->service->customerPath($customer), 'Jalur customer berhasil ditelusuri');
}
private function resource(Request $request): string
{
return $request->route()->defaults['topology_resource'];
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
private function authorizeModel(Request $request, $model, bool $write = false): void
{
if ($model->tenant_id === null) {
abort_if($write && ! $request->user()->isMasterAdmin(), 403);
return;
}
$this->authorizeTenant($request, $model->tenant_id);
}
private function authorizeTenant(Request $request, int $tenantId): void
{
abort_unless($request->user()->isMasterAdmin() || $tenantId === $this->tenantId($request), 403);
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Http\Controllers\Wallet;
use App\Http\Controllers\ApiController;
use App\Http\Requests\Wallet\StoreWithdrawalRequest;
use App\Http\Requests\Wallet\TransferWalletRequest;
use App\Models\Wallet;
use App\Services\Wallet\WalletService;
use Illuminate\Http\Request;
class WalletController extends ApiController
{
public function __construct(protected WalletService $service) {}
public function index(Request $request)
{
return $this->success($this->service->wallets($request->user(), $this->tenantId($request)), 'Daftar dompet berhasil diambil');
}
public function ledger(Request $request, Wallet $wallet)
{
return $this->success($this->service->ledger($wallet, $request->user(), $this->tenantId($request), $request->validate(['per_page' => ['nullable', 'integer', 'min:1', 'max:100']])), 'Mutasi dompet berhasil diambil');
}
public function transfer(TransferWalletRequest $request, Wallet $wallet)
{
return $this->created($this->service->transfer($wallet, Wallet::findOrFail($request->integer('destination_wallet_id')), $request->float('amount'), $request->user(), $this->tenantId($request)), 'Saldo berhasil dipindahkan');
}
public function withdraw(StoreWithdrawalRequest $request, Wallet $wallet)
{
return $this->created($this->service->requestWithdrawal($wallet, $request->validated(), $request->user(), $this->tenantId($request)), 'Permintaan penarikan berhasil dibuat');
}
private function tenantId(Request $request): ?int
{
return $request->attributes->get('tenant_id');
}
}