Refactor order and payroll models to replace 'net_amount' with 'total_amount'. Update related methods, migrations, factories, and frontend components to ensure consistent handling of total amounts across the application.
This commit is contained in:
parent
521e8c5538
commit
64088c82bb
@ -20,7 +20,7 @@
|
||||
'subtotal_formatted',
|
||||
'discount_formatted',
|
||||
'marketplace_fee_formatted',
|
||||
'net_amount_formatted',
|
||||
'total_amount_formatted',
|
||||
'created_at_formatted',
|
||||
'channel_label',
|
||||
'price_type_label',
|
||||
@ -41,7 +41,7 @@ protected function casts(): array
|
||||
'subtotal' => 'integer',
|
||||
'discount' => 'integer',
|
||||
'marketplace_fee' => 'integer',
|
||||
'net_amount' => 'integer',
|
||||
'total_amount' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
@ -93,10 +93,10 @@ public function marketplaceFeeFormatted(): Attribute
|
||||
);
|
||||
}
|
||||
|
||||
public function netAmountFormatted(): Attribute
|
||||
public function totalAmountFormatted(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => 'Rp '.number_format($this->net_amount, 0, ',', '.'),
|
||||
get: fn () => 'Rp '.number_format($this->total_amount, 0, ',', '.'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
'base_salary_formatted',
|
||||
'bonus_amount_formatted',
|
||||
'deduction_amount_formatted',
|
||||
'net_amount_formatted',
|
||||
'total_amount_formatted',
|
||||
'status_label',
|
||||
'employee_name',
|
||||
'paid_at_formatted',
|
||||
@ -37,7 +37,7 @@ protected function casts(): array
|
||||
'base_salary' => 'integer',
|
||||
'bonus_amount' => 'integer',
|
||||
'deduction_amount' => 'integer',
|
||||
'net_amount' => 'integer',
|
||||
'total_amount' => 'integer',
|
||||
'status' => PayrollStatus::class,
|
||||
'paid_at' => 'datetime',
|
||||
];
|
||||
@ -115,10 +115,10 @@ public function employeeName(): Attribute
|
||||
);
|
||||
}
|
||||
|
||||
public function netAmountFormatted(): Attribute
|
||||
public function totalAmountFormatted(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => 'Rp '.number_format($this->net_amount, 0, ',', '.'),
|
||||
get: fn () => 'Rp '.number_format($this->total_amount, 0, ',', '.'),
|
||||
);
|
||||
}
|
||||
|
||||
@ -162,6 +162,6 @@ public function recalculateAmounts(): void
|
||||
|
||||
$this->bonus_amount = $bonusAmount;
|
||||
$this->deduction_amount = $kasbonDeduction + $manualDeduction;
|
||||
$this->net_amount = max(0, $this->base_salary + $bonusAmount - $this->deduction_amount);
|
||||
$this->total_amount = max(0, $this->base_salary + $bonusAmount - $this->deduction_amount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,14 +54,14 @@ public function resolvePeriod(?int $periodId): ?PayrollPeriod
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{total_net_amount: int, total_net_amount_formatted: string, unpaid_count: int, paid_count: int}
|
||||
* @return array{total_total_amount: int, total_total_amount_formatted: string, unpaid_count: int, paid_count: int}
|
||||
*/
|
||||
public function periodSummary(PayrollPeriod $period): array
|
||||
{
|
||||
$totalNetAmount = (int) Payroll::query()
|
||||
$totalTotalAmount = (int) Payroll::query()
|
||||
->where('payroll_period_id', $period->id)
|
||||
->where('status', PayrollStatus::UNPAID)
|
||||
->sum('net_amount');
|
||||
->sum('total_amount');
|
||||
|
||||
$unpaidCount = Payroll::query()
|
||||
->where('payroll_period_id', $period->id)
|
||||
@ -74,8 +74,8 @@ public function periodSummary(PayrollPeriod $period): array
|
||||
->count();
|
||||
|
||||
return [
|
||||
'total_net_amount' => $totalNetAmount,
|
||||
'total_net_amount_formatted' => 'Rp '.number_format($totalNetAmount, 0, ',', '.'),
|
||||
'total_total_amount' => $totalTotalAmount,
|
||||
'total_total_amount_formatted' => 'Rp '.number_format($totalTotalAmount, 0, ',', '.'),
|
||||
'unpaid_count' => $unpaidCount,
|
||||
'paid_count' => $paidCount,
|
||||
];
|
||||
@ -154,7 +154,7 @@ public function closePeriod(PayrollPeriod $period, User $user): void
|
||||
$unpaidCount = Payroll::query()
|
||||
->where('payroll_period_id', $period->id)
|
||||
->where('status', PayrollStatus::UNPAID)
|
||||
->where('net_amount', '>', 0)
|
||||
->where('total_amount', '>', 0)
|
||||
->count();
|
||||
|
||||
if ($unpaidCount > 0) {
|
||||
@ -189,7 +189,7 @@ public function generatePayrollsForPeriod(PayrollPeriod $period): void
|
||||
'base_salary' => $employee->base_salary,
|
||||
'bonus_amount' => 0,
|
||||
'deduction_amount' => 0,
|
||||
'net_amount' => 0,
|
||||
'total_amount' => 0,
|
||||
'status' => PayrollStatus::UNPAID,
|
||||
]);
|
||||
|
||||
@ -242,7 +242,7 @@ public function pay(Payroll $payroll, User $user): void
|
||||
]);
|
||||
}
|
||||
|
||||
if ($payroll->net_amount <= 0) {
|
||||
if ($payroll->total_amount <= 0) {
|
||||
DB::transaction(function () use ($payroll, $user): void {
|
||||
$payroll->status = PayrollStatus::PAID;
|
||||
$payroll->paid_at = now();
|
||||
@ -264,7 +264,7 @@ public function pay(Payroll $payroll, User $user): void
|
||||
|
||||
$cashTransaction = $this->cashService->recordOutgoing(
|
||||
$payroll,
|
||||
$payroll->net_amount,
|
||||
$payroll->total_amount,
|
||||
$description,
|
||||
$user,
|
||||
);
|
||||
@ -332,7 +332,7 @@ private function settleKasbonFromPayroll(Payroll $payroll, User $user): void
|
||||
|
||||
private function applySorting(Builder $query, string $sort, string $direction): void
|
||||
{
|
||||
if (in_array($sort, ['base_salary', 'bonus_amount', 'deduction_amount', 'net_amount', 'status', 'created_at'], true)) {
|
||||
if (in_array($sort, ['base_salary', 'bonus_amount', 'deduction_amount', 'total_amount', 'status', 'created_at'], true)) {
|
||||
$query->orderBy($sort, $direction);
|
||||
|
||||
return;
|
||||
|
||||
@ -284,7 +284,7 @@ public function create(array $validated, User $user): Order
|
||||
$subtotal = $draftItems->sum('subtotal');
|
||||
$discount = (int) ($validated['discount'] ?? 0);
|
||||
$marketplaceFee = (int) ($validated['marketplace_fee'] ?? 0);
|
||||
$netAmount = max($subtotal - $discount - $marketplaceFee, 0);
|
||||
$totalAmount = max($subtotal - $discount - $marketplaceFee, 0);
|
||||
|
||||
$order = Order::create([
|
||||
'customer_id' => $validated['customer_id'] ?? null,
|
||||
@ -295,7 +295,7 @@ public function create(array $validated, User $user): Order
|
||||
'subtotal' => $subtotal,
|
||||
'discount' => $discount,
|
||||
'marketplace_fee' => $marketplaceFee,
|
||||
'net_amount' => $netAmount,
|
||||
'total_amount' => $totalAmount,
|
||||
'notes' => $validated['notes'] ?? null,
|
||||
]);
|
||||
|
||||
@ -334,7 +334,7 @@ public function update(Order $order, array $validated): void
|
||||
$subtotal = array_sum(array_column($lineItems, 'subtotal'));
|
||||
$discount = (int) ($validated['discount'] ?? 0);
|
||||
$marketplaceFee = (int) ($validated['marketplace_fee'] ?? 0);
|
||||
$netAmount = max($subtotal - $discount - $marketplaceFee, 0);
|
||||
$totalAmount = max($subtotal - $discount - $marketplaceFee, 0);
|
||||
|
||||
$order->customer_id = $validated['customer_id'] ?? null;
|
||||
$order->channel = $validated['channel'];
|
||||
@ -342,7 +342,7 @@ public function update(Order $order, array $validated): void
|
||||
$order->subtotal = $subtotal;
|
||||
$order->discount = $discount;
|
||||
$order->marketplace_fee = $marketplaceFee;
|
||||
$order->net_amount = $netAmount;
|
||||
$order->total_amount = $totalAmount;
|
||||
$order->notes = $validated['notes'] ?? null;
|
||||
$order->save();
|
||||
|
||||
@ -528,7 +528,7 @@ private function incrementStock(OrderItem $item): void
|
||||
|
||||
private function applySorting(Builder $query, string $sort, string $direction): void
|
||||
{
|
||||
if (in_array($sort, ['created_at', 'net_amount', 'discount', 'subtotal', 'order_number'], true)) {
|
||||
if (in_array($sort, ['created_at', 'total_amount', 'discount', 'subtotal', 'order_number'], true)) {
|
||||
$query->orderBy($sort, $direction);
|
||||
|
||||
return;
|
||||
|
||||
@ -31,7 +31,7 @@ public function definition(): array
|
||||
'status' => OrderStatus::PENDING->value,
|
||||
'subtotal' => $subtotal,
|
||||
'discount' => $discount,
|
||||
'net_amount' => $subtotal - $discount,
|
||||
'total_amount' => $subtotal - $discount,
|
||||
'notes' => fake()->optional()->sentence(),
|
||||
'cash_transaction_id' => null,
|
||||
'created_by_id' => User::factory(),
|
||||
|
||||
@ -26,7 +26,7 @@ public function definition(): array
|
||||
'base_salary' => $baseSalary,
|
||||
'bonus_amount' => $bonusAmount,
|
||||
'deduction_amount' => $deductionAmount,
|
||||
'net_amount' => max(0, $baseSalary + $bonusAmount - $deductionAmount),
|
||||
'total_amount' => max(0, $baseSalary + $bonusAmount - $deductionAmount),
|
||||
'status' => PayrollStatus::UNPAID->value,
|
||||
'paid_at' => null,
|
||||
'paid_by_id' => null,
|
||||
|
||||
@ -19,7 +19,7 @@ public function up(): void
|
||||
$table->unsignedInteger('base_salary');
|
||||
$table->unsignedBigInteger('bonus_amount')->default(0);
|
||||
$table->unsignedBigInteger('deduction_amount')->default(0);
|
||||
$table->unsignedBigInteger('net_amount');
|
||||
$table->unsignedBigInteger('total_amount');
|
||||
$table->enum('status', array_column(PayrollStatus::cases(), 'value'))->default(PayrollStatus::UNPAID->value);
|
||||
$table->timestamp('paid_at')->nullable();
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ public function up(): void
|
||||
$table->enum('status', array_column(OrderStatus::cases(), 'value'))->default(OrderStatus::PENDING->value);
|
||||
$table->unsignedBigInteger('subtotal');
|
||||
$table->unsignedBigInteger('discount')->default(0);
|
||||
$table->unsignedBigInteger('net_amount');
|
||||
$table->unsignedBigInteger('total_amount');
|
||||
$table->text('notes')->nullable();
|
||||
|
||||
$table->foreignId('cash_transaction_id')->nullable()->unique()->constrained()->restrictOnDelete();
|
||||
|
||||
@ -22,7 +22,7 @@ public function run(): void
|
||||
'payroll_period_id' => $period->id,
|
||||
'employee_id' => $employee->id,
|
||||
'base_salary' => $employee->base_salary,
|
||||
'net_amount' => $employee->base_salary,
|
||||
'total_amount' => $employee->base_salary,
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
@ -34,9 +34,9 @@ export function createColumns(
|
||||
header: () => h(DataTableColumnHeader, { title: 'Potongan', column: 'deduction_amount' }),
|
||||
},
|
||||
{
|
||||
accessorKey: 'net_amount_formatted',
|
||||
accessorKey: 'total_amount_formatted',
|
||||
enableSorting: true,
|
||||
header: () => h(DataTableColumnHeader, { title: 'Gaji Bersih', column: 'net_amount' }),
|
||||
header: () => h(DataTableColumnHeader, { title: 'Gaji Bersih', column: 'total_amount' }),
|
||||
},
|
||||
{
|
||||
accessorKey: 'status_label',
|
||||
|
||||
@ -64,6 +64,6 @@ function payPayroll() {
|
||||
</div>
|
||||
|
||||
<ConfirmDialog v-if="can('payroll.pay')" v-model:open="payConfirmOpen" title="Bayar gaji?"
|
||||
:description="`Gaji ${payroll.net_amount_formatted} untuk ${payroll.employee_name} akan dibayar dari kas.`"
|
||||
:description="`Gaji ${payroll.total_amount_formatted} untuk ${payroll.employee_name} akan dibayar dari kas.`"
|
||||
confirm-label="Bayar" cancel-label="Batal" :loading="payProcessing" @confirm="payPayroll" />
|
||||
</template>
|
||||
|
||||
@ -107,13 +107,18 @@ function statusVariant(status: string): 'default' | 'secondary' | 'destructive'
|
||||
<p>Oleh {{ order.created_by?.profile?.full_name ?? order.created_by?.username }}</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-x-4 gap-y-1 text-sm">
|
||||
<span>Tipe Harga <strong class="text-foreground">{{ order.price_type_label }}</strong></span>
|
||||
<span>Subtotal <strong class="text-foreground">{{ order.subtotal_formatted }}</strong></span>
|
||||
<span>Diskon <strong class="text-foreground">{{ order.discount_formatted }}</strong></span>
|
||||
<span>Tipe Harga <strong class="text-foreground">{{ order.price_type_label
|
||||
}}</strong></span>
|
||||
<span>Subtotal <strong class="text-foreground">{{ order.subtotal_formatted
|
||||
}}</strong></span>
|
||||
<span>Diskon <strong class="text-foreground">{{ order.discount_formatted
|
||||
}}</strong></span>
|
||||
<span v-if="order.channel !== 'store'">
|
||||
Biaya MP <strong class="text-foreground">{{ order.marketplace_fee_formatted }}</strong>
|
||||
Biaya MP <strong class="text-foreground">{{ order.marketplace_fee_formatted
|
||||
}}</strong>
|
||||
</span>
|
||||
<span>Net <strong class="text-primary">{{ order.net_amount_formatted }}</strong></span>
|
||||
<span>Total <strong class="text-primary">{{ order.total_amount_formatted
|
||||
}}</strong></span>
|
||||
</div>
|
||||
<p v-if="order.notes" class="text-muted-foreground text-sm">
|
||||
{{ order.notes }}
|
||||
|
||||
@ -178,7 +178,7 @@ const subtotal = computed(() =>
|
||||
|
||||
const discountAmount = computed(() => Number(parseRupiah(form.discount)) || 0);
|
||||
const marketplaceFeeAmount = computed(() => Number(parseRupiah(form.marketplace_fee)) || 0);
|
||||
const netAmount = computed(() => Math.max(subtotal.value - discountAmount.value - marketplaceFeeAmount.value, 0));
|
||||
const totalAmount = computed(() => Math.max(subtotal.value - discountAmount.value - marketplaceFeeAmount.value, 0));
|
||||
|
||||
function getVariantPrice(variant: ProductVariantItem): ProductPriceItem | undefined {
|
||||
return variant.prices.find((price) => price.type === form.price_type);
|
||||
@ -558,8 +558,8 @@ function submit() {
|
||||
<FieldError :errors="formErrors(form, 'marketplace_fee')" />
|
||||
</Field>
|
||||
<div class="flex justify-between text-base font-semibold">
|
||||
<span>Net</span>
|
||||
<span class="text-primary">Rp {{ formatRupiah(netAmount) }}</span>
|
||||
<span>Total</span>
|
||||
<span class="text-primary">Rp {{ formatRupiah(totalAmount) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ export function encodeOrderReceipt(
|
||||
summaryRows.push(['Biaya MP', order.marketplace_fee_formatted]);
|
||||
}
|
||||
|
||||
summaryRows.push(['Total', order.net_amount_formatted]);
|
||||
summaryRows.push(['Total', order.total_amount_formatted]);
|
||||
|
||||
encoder.table(
|
||||
[
|
||||
|
||||
@ -168,7 +168,7 @@ watch(
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="text-3xl font-bold tracking-tight">
|
||||
{{ summary.total_net_amount_formatted }}
|
||||
{{ summary.total_total_amount_formatted }}
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-muted-foreground">
|
||||
{{ summary.unpaid_count }} slip belum dibayar
|
||||
@ -195,9 +195,9 @@ watch(
|
||||
|
||||
<Card v-if="payrolls && pagination" class="min-w-0">
|
||||
<CardContent class="min-w-0 pt-6">
|
||||
<DataTable v-model:search="search" :columns="columns" :data="payrolls.data"
|
||||
:pagination="pagination" :pagination-links="payrolls.links" :sort="currentSort"
|
||||
@sort-change="setSort" @filters-reset="resetFilters" />
|
||||
<DataTable v-model:search="search" :columns="columns" :data="payrolls.data" :pagination="pagination"
|
||||
:pagination-links="payrolls.links" :sort="currentSort" @sort-change="setSort"
|
||||
@filters-reset="resetFilters" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@ -211,7 +211,7 @@ watch(
|
||||
:payroll="adjustingPayroll" :adjustment-types="adjustmentTypes" />
|
||||
|
||||
<ConfirmDialog v-if="canClosePeriod" v-model:open="closeConfirmOpen" title="Tutup periode gaji?"
|
||||
description="Pastikan semua gaji sudah dibayar sebelum menutup periode."
|
||||
confirm-label="Tutup Periode" cancel-label="Batal" :loading="closeProcessing" @confirm="closePeriod" />
|
||||
description="Pastikan semua gaji sudah dibayar sebelum menutup periode." confirm-label="Tutup Periode"
|
||||
cancel-label="Batal" :loading="closeProcessing" @confirm="closePeriod" />
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
@ -48,7 +48,7 @@ export type OrderListItem = {
|
||||
subtotal_formatted: string;
|
||||
discount_formatted: string;
|
||||
marketplace_fee_formatted: string;
|
||||
net_amount_formatted: string;
|
||||
total_amount_formatted: string;
|
||||
notes: string | null;
|
||||
created_at_formatted: string;
|
||||
customer?: {
|
||||
|
||||
@ -18,8 +18,8 @@ export type PayrollListItem = {
|
||||
bonus_amount_formatted: string;
|
||||
deduction_amount: number;
|
||||
deduction_amount_formatted: string;
|
||||
net_amount: number;
|
||||
net_amount_formatted: string;
|
||||
total_amount: number;
|
||||
total_amount_formatted: string;
|
||||
status: string;
|
||||
status_label: string;
|
||||
paid_at_formatted: string | null;
|
||||
@ -28,8 +28,8 @@ export type PayrollListItem = {
|
||||
};
|
||||
|
||||
export type PayrollSummary = {
|
||||
total_net_amount: number;
|
||||
total_net_amount_formatted: string;
|
||||
total_total_amount: number;
|
||||
total_total_amount_formatted: string;
|
||||
unpaid_count: number;
|
||||
paid_count: number;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user