feat: add subtotal field to orders and include it in print receipts and UI displays
This commit is contained in:
parent
cf0d60f74b
commit
ede4831f96
@ -69,6 +69,7 @@ public function store(OrderRequest $request): RedirectResponse
|
||||
'order_number' => $orderNumber,
|
||||
'customer_name' => $validated['customer_name'],
|
||||
'cogs' => $cogs,
|
||||
'subtotal' => $totalItemsPrice,
|
||||
'discount' => $validated['discount'],
|
||||
'payment' => $validated['payment'],
|
||||
'total' => $totalItemsPrice - $validated['discount'],
|
||||
@ -148,6 +149,7 @@ public function update(OrderRequest $request, Order $order): RedirectResponse
|
||||
$order->update([
|
||||
'customer_name' => $validated['customer_name'],
|
||||
'cogs' => $cogs,
|
||||
'subtotal' => $totalItemsPrice,
|
||||
'discount' => $validated['discount'],
|
||||
'payment' => $validated['payment'],
|
||||
'total' => $totalItemsPrice - $validated['discount'],
|
||||
|
||||
@ -29,6 +29,7 @@ public function rules(): array
|
||||
{
|
||||
return [
|
||||
'customer_name' => ['required', 'string', 'max:100'],
|
||||
'subtotal' => ['required', 'integer', 'min:0'],
|
||||
'discount' => ['required', 'integer', 'min:0'],
|
||||
'payment' => ['required', 'integer', 'min:0'],
|
||||
'payment_method' => ['required', Rule::enum(PaymentMethod::class)],
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
#[Guarded(['id'])]
|
||||
#[Appends(['hpp_formatted', 'discount_formatted', 'payment_formatted', 'total_formatted'])]
|
||||
#[Appends(['hpp_formatted', 'subtotal_formatted', 'discount_formatted', 'payment_formatted', 'total_formatted'])]
|
||||
class Order extends Model
|
||||
{
|
||||
use HasFactory, LogsActivity, SoftDeletes;
|
||||
@ -27,6 +27,7 @@ protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'cogs' => 'integer',
|
||||
'subtotal' => 'integer',
|
||||
'discount' => 'integer',
|
||||
'payment' => 'integer',
|
||||
'total' => 'integer',
|
||||
@ -43,6 +44,13 @@ protected function hppFormatted(): Attribute
|
||||
);
|
||||
}
|
||||
|
||||
protected function subtotalFormatted(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => 'Rp '.number_format($this->subtotal, 0, ',', '.'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function discountFormatted(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
@ -77,7 +85,7 @@ public function items(): HasMany
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['order_number', 'customer_name', 'cogs', 'discount', 'payment', 'total', 'payment_method', 'order_status', 'order_channel'])
|
||||
->logOnly(['order_number', 'customer_name', 'cogs', 'subtotal', 'discount', 'payment', 'total', 'payment_method', 'order_status', 'order_channel'])
|
||||
->logOnlyDirty()
|
||||
->useLogName('Pesanan');
|
||||
}
|
||||
@ -96,6 +104,7 @@ public function tapActivity(Activity $activity, string $eventName)
|
||||
'order_number' => 'Nomor Order',
|
||||
'customer_name' => 'Nama Pelanggan',
|
||||
'cogs' => 'Modal',
|
||||
'subtotal' => 'Subtotal',
|
||||
'discount' => 'Diskon',
|
||||
'payment' => 'Bayar',
|
||||
'total' => 'Total',
|
||||
|
||||
@ -35,6 +35,7 @@ public function definition(): array
|
||||
'order_number' => 'ORD-'.$date->format('YmdHi').'-'.$sequence,
|
||||
'customer_name' => $this->faker->name(),
|
||||
'cogs' => 0,
|
||||
'subtotal' => 0,
|
||||
'discount' => 0,
|
||||
'payment' => 0,
|
||||
'total' => 0,
|
||||
|
||||
@ -20,6 +20,7 @@ public function up(): void
|
||||
$table->string('order_number', 30);
|
||||
$table->string('customer_name', 100);
|
||||
$table->unsignedInteger('cogs');
|
||||
$table->unsignedInteger('subtotal');
|
||||
$table->unsignedInteger('discount');
|
||||
$table->unsignedInteger('payment');
|
||||
$table->unsignedInteger('total');
|
||||
|
||||
@ -74,6 +74,7 @@ private function createOrderWithItems(Order $order, $users, $products): void
|
||||
|
||||
$order->update([
|
||||
'cogs' => $totalOrderHpp,
|
||||
'subtotal' => $totalOrderPrice,
|
||||
'discount' => $discount,
|
||||
'total' => $finalTotal,
|
||||
'payment' => $finalTotal, // Assume fully paid
|
||||
|
||||
@ -64,6 +64,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
||||
|
||||
const { data, setData, post, processing, errors, transform } = useForm({
|
||||
customer_name: '',
|
||||
subtotal: 0,
|
||||
discount: 0,
|
||||
payment: 0,
|
||||
payment_method: 'cash',
|
||||
@ -167,6 +168,7 @@ return;
|
||||
|
||||
transform((data) => ({
|
||||
...data,
|
||||
subtotal: subtotal,
|
||||
items: cartItems.map(item => ({
|
||||
product_id: item.product_id,
|
||||
qty: item.qty,
|
||||
|
||||
@ -58,8 +58,9 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
|
||||
return Array.from(map.entries()).map(([id, name]) => ({ id, name }));
|
||||
}, [products]);
|
||||
|
||||
const { data, setData, patch, processing, errors } = useForm({
|
||||
const { data, setData, patch, processing, errors, transform } = useForm({
|
||||
customer_name: order.customer_name,
|
||||
subtotal: order.subtotal,
|
||||
discount: order.discount,
|
||||
payment: order.payment,
|
||||
payment_method: order.payment_method,
|
||||
@ -187,6 +188,11 @@ return;
|
||||
return;
|
||||
}
|
||||
|
||||
transform((data) => ({
|
||||
...data,
|
||||
subtotal: subtotal,
|
||||
}));
|
||||
|
||||
patch(orderRoutes.update(order.id).url, {
|
||||
onSuccess: (response: any) => {
|
||||
toast.success(response.props.flash.success);
|
||||
|
||||
@ -59,6 +59,11 @@ export function useOrderPrint() {
|
||||
|
||||
result.line(line);
|
||||
|
||||
const subtotalLabel = 'Subtotal:';
|
||||
const subtotalVal = order.subtotal_formatted;
|
||||
const sSpaces = width - subtotalLabel.length - subtotalVal.length;
|
||||
result.line(subtotalLabel + ' '.repeat(Math.max(0, sSpaces)) + subtotalVal);
|
||||
|
||||
const discountAmount = Number(order.discount || 0);
|
||||
|
||||
if (discountAmount > 0) {
|
||||
|
||||
@ -105,7 +105,13 @@ export const getColumns = ({
|
||||
<DataTableColumnHeader column={column} title="Total" />
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-col items-end gap-1">
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="font-medium text-primary">
|
||||
{row.original.subtotal_formatted}
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
- {row.original.discount_formatted}
|
||||
</span>
|
||||
<span className="font-bold text-primary">
|
||||
{row.original.total_formatted}
|
||||
</span>
|
||||
|
||||
@ -5,6 +5,8 @@ export interface Order {
|
||||
order_number: string;
|
||||
customer_name: string;
|
||||
cogs: number;
|
||||
subtotal: number;
|
||||
subtotal_formatted: string;
|
||||
discount: number;
|
||||
payment: number;
|
||||
total: number;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user