diff --git a/app/Enums/CashTransactionType.php b/app/Enums/CashTransactionType.php
index 4d9bec2..661e9e1 100644
--- a/app/Enums/CashTransactionType.php
+++ b/app/Enums/CashTransactionType.php
@@ -10,6 +10,7 @@ enum CashTransactionType: string
case DEPOSIT = 'deposit';
case EXPENSE = 'expense';
+ case TRANSACTION = 'transaction';
case WITHDRAWAL = 'withdrawal';
case EMPLOYEE_ADVANCE = 'employee_advance';
case SALARY = 'salary';
@@ -19,6 +20,7 @@ public function label(): string
return match ($this) {
self::DEPOSIT => 'Deposit',
self::EXPENSE => 'Pengeluaran',
+ self::TRANSACTION => 'Transaksi',
self::WITHDRAWAL => 'Withdrawal',
self::EMPLOYEE_ADVANCE => 'Kasbon',
self::SALARY => 'Gaji',
diff --git a/app/Models/CashTransaction.php b/app/Models/CashTransaction.php
index f86dc78..c6d7588 100644
--- a/app/Models/CashTransaction.php
+++ b/app/Models/CashTransaction.php
@@ -75,6 +75,12 @@ protected function expenseType(Builder $query): void
$query->where('type', CashTransactionType::EXPENSE);
}
+ #[Scope]
+ protected function transactionType(Builder $query): void
+ {
+ $query->where('type', CashTransactionType::TRANSACTION);
+ }
+
#[Scope]
protected function transfer(Builder $query): void
{
diff --git a/app/Services/Admin/Manage/TransactionService.php b/app/Services/Admin/Manage/TransactionService.php
index 2eeae1d..a87c1c1 100644
--- a/app/Services/Admin/Manage/TransactionService.php
+++ b/app/Services/Admin/Manage/TransactionService.php
@@ -2,6 +2,7 @@
namespace App\Services\Admin\Manage;
+use App\Enums\CashTransactionType;
use App\Enums\OrderChannel;
use App\Enums\OrderStatus;
use App\Enums\PaymentType;
@@ -14,6 +15,7 @@
use App\Models\ProductVariant;
use App\Models\User;
use App\Services\Concerns\HasStockAdjustment;
+use App\Services\Concerns\HandlesCashTransactions;
use App\Services\Concerns\RegistersMedia;
use App\Services\NotificationService;
use App\Services\S3PresignedService;
@@ -23,7 +25,7 @@
class TransactionService
{
- use HasStockAdjustment, RegistersMedia;
+ use HasStockAdjustment, HandlesCashTransactions, RegistersMedia;
private const SELLING_PRICE_MAP = [
PriceType::DISTRIBUTOR->value => PriceType::DISTRIBUTOR,
@@ -233,7 +235,14 @@ public function store(array $data): Order
$this->applyStock($data['items'], $stockType, -1);
- if ($paymentType !== PaymentType::CASH->value) {
+ if ($paymentType === PaymentType::CASH->value) {
+ $cashTransaction = $this->creditCash(
+ amount: $totalAmount,
+ description: 'Pembayaran tunai: '.$order->order_number,
+ type: CashTransactionType::TRANSACTION,
+ );
+ $order->update(['cash_transaction_id' => $cashTransaction->id]);
+ } else {
$this->syncPhoto($order, $data);
}
@@ -253,6 +262,7 @@ public function update(Order $order, array $data): Order
$order = DB::transaction(function () use ($order, $data) {
$order->load('orderItems');
+ $oldPaymentType = $order->payment_type;
$oldStockType = $order->orderItems->first()?->stock_quality?->value ?? ProductStockQuality::GOOD->value;
$order->orderItems->each(function (OrderItem $item) use ($oldStockType) {
@@ -284,13 +294,15 @@ public function update(Order $order, array $data): Order
}
DB::table('order_items')->insert($itemRows);
+ $newPaymentType = $data['payment_type'] ?? $order->payment_type->value;
+
$order->update([
'customer_id' => $data['customer_id'] ?? null,
'marketing_id' => $data['marketing_id'] ?? null,
'channel' => $data['channel'] ?? $order->channel->value,
'price_type' => $priceType,
'status' => ($data['is_completed'] ?? false) ? OrderStatus::COMPLETED : OrderStatus::PENDING,
- 'payment_type' => $data['payment_type'] ?? $order->payment_type->value,
+ 'payment_type' => $newPaymentType,
'tiktok_order_id' => $data['tiktok_order_id'] ?? null,
'shopee_order_id' => $data['shopee_order_id'] ?? null,
'subtotal' => $subtotal,
@@ -303,11 +315,39 @@ public function update(Order $order, array $data): Order
$this->applyStock($data['items'], $stockType, -1);
- $paymentType = $data['payment_type'] ?? $order->payment_type->value;
- if ($paymentType !== PaymentType::CASH->value) {
- $this->syncPhoto($order, $data);
- } else {
+ if ($oldPaymentType === PaymentType::CASH && $newPaymentType !== PaymentType::CASH->value) {
+ if ($order->cash_transaction_id) {
+ $order->cashTransaction()->delete();
+ $order->update(['cash_transaction_id' => null]);
+ }
+ } elseif ($oldPaymentType !== PaymentType::CASH && $newPaymentType === PaymentType::CASH->value) {
+ $cashTransaction = $this->creditCash(
+ amount: $totalAmount,
+ description: 'Pembayaran tunai: '.$order->order_number,
+ type: CashTransactionType::TRANSACTION,
+ );
+ $order->update(['cash_transaction_id' => $cashTransaction->id]);
+ } elseif ($oldPaymentType === PaymentType::CASH && $newPaymentType === PaymentType::CASH->value && $order->cash_transaction_id) {
+ $cashTransaction = $order->cashTransaction;
+ $oldAmount = $cashTransaction->amount;
+ $difference = $totalAmount - $oldAmount;
+
+ if ($difference !== 0) {
+ $cashAccount = \App\Models\CashAccount::firstOrFail();
+ $newBalance = $cashAccount->balance + $difference;
+ $cashAccount->update(['balance' => $newBalance]);
+
+ $cashTransaction->update([
+ 'amount' => $totalAmount,
+ 'balance_after' => $newBalance,
+ ]);
+ }
+ }
+
+ if ($newPaymentType === PaymentType::CASH->value) {
$order->clearMediaCollection('photos');
+ } else {
+ $this->syncPhoto($order, $data);
}
return $order;
@@ -336,6 +376,14 @@ public function destroy(Order $order): bool
});
}
+ if ($order->payment_type === PaymentType::CASH && $order->cash_transaction_id) {
+ $this->debitCash(
+ amount: $order->total_amount,
+ description: 'Pembatalan transaksi: '.$order->order_number,
+ type: CashTransactionType::EXPENSE,
+ );
+ }
+
$order->orderItems()->delete();
$order->delete();
@@ -365,6 +413,14 @@ public function updateStatus(Order $order, string $status): Order
$order->orderItems->each(function (OrderItem $item) use ($stockType) {
$this->adjustVariantStock($item->product_variant_id, $item->quantity, 1, $stockType);
});
+
+ if ($order->payment_type === PaymentType::CASH && $order->cash_transaction_id) {
+ $this->debitCash(
+ amount: $order->total_amount,
+ description: 'Pembatalan transaksi: '.$order->order_number,
+ type: CashTransactionType::EXPENSE,
+ );
+ }
}
return $order;
diff --git a/resources/js/pages/admin/finance/cash-account/transaction-columns.tsx b/resources/js/pages/admin/finance/cash-account/transaction-columns.tsx
index e825a27..a4d1f06 100644
--- a/resources/js/pages/admin/finance/cash-account/transaction-columns.tsx
+++ b/resources/js/pages/admin/finance/cash-account/transaction-columns.tsx
@@ -1,7 +1,7 @@
+import { RowActions } from '@/components/data-display';
+import { ImagePreviewButton } from '@/components/dialogs';
import type { ColumnDef } from '@tanstack/react-table';
import { Pencil, Trash2 } from 'lucide-react';
-import { ImagePreviewButton } from '@/components/dialogs';
-import { RowActions } from '@/components/data-display';
export type CashTransaction = {
id: number;
@@ -32,7 +32,8 @@ function getTypeLabel(type: string): string {
withdrawal: 'Withdrawal',
expense: 'Pengeluaran',
employee_advance: 'Kasbon',
- salary : 'Gaji'
+ salary: 'Gaji',
+ transaction: 'Transaksi'
};
return labels[type] ?? type;
@@ -77,13 +78,13 @@ export function createTransactionColumns(
header: () => Jumlah,
cell: ({ row }) => {
const transaction = row.original;
- const isDeposit = transaction.type === 'deposit';
+ const isDeposit = transaction.type === 'deposit' || transaction.type === 'transaction';
return (