feat: update OrderService and frontend components to automatically set order status to completed for cashiers; adjust payment and marketing fields accordingly; enhance tests to verify new behavior
This commit is contained in:
parent
02fb2045d2
commit
352599bf00
@ -393,8 +393,10 @@ public function create(array $validated, User $user): Order
|
|||||||
if ($user->hasRole('cashier')) {
|
if ($user->hasRole('cashier')) {
|
||||||
$validated['channel'] = 'store';
|
$validated['channel'] = 'store';
|
||||||
$validated['price_type'] = 'retail';
|
$validated['price_type'] = 'retail';
|
||||||
$validated['payment_type'] = 'cash';
|
$validated['payment_type'] = $validated['payment_type'] ?? 'cash';
|
||||||
|
$validated['status'] = OrderStatus::COMPLETED->value;
|
||||||
unset($validated['customer_id']);
|
unset($validated['customer_id']);
|
||||||
|
unset($validated['marketing_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$order = $this->runInTransaction(
|
$order = $this->runInTransaction(
|
||||||
|
|||||||
@ -35,7 +35,7 @@ defineProps<{
|
|||||||
canComplete: boolean;
|
canComplete: boolean;
|
||||||
canCreate: boolean;
|
canCreate: boolean;
|
||||||
cartEmpty: boolean;
|
cartEmpty: boolean;
|
||||||
submitLabel: string;
|
isCashierUser: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const printAfterSave = defineModel<boolean>('printAfterSave', { required: true });
|
const printAfterSave = defineModel<boolean>('printAfterSave', { required: true });
|
||||||
@ -70,7 +70,7 @@ const isUploading = computed(() => photoState.value.pendingUploads > 0);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Field v-if="canComplete">
|
<Field v-if="canComplete && !isCashierUser">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<Switch id="status-completed" :model-value="form.status === OrderStatus.COMPLETED"
|
<Switch id="status-completed" :model-value="form.status === OrderStatus.COMPLETED"
|
||||||
@update:model-value="form.status = $event ? OrderStatus.COMPLETED : OrderStatus.PENDING" />
|
@update:model-value="form.status = $event ? OrderStatus.COMPLETED : OrderStatus.PENDING" />
|
||||||
|
|||||||
@ -84,7 +84,7 @@ const form = useForm({
|
|||||||
discount: '',
|
discount: '',
|
||||||
nego_price: '',
|
nego_price: '',
|
||||||
notes: '',
|
notes: '',
|
||||||
status: OrderStatus.PENDING as string,
|
status: (isCashierUser.value ? OrderStatus.COMPLETED : OrderStatus.PENDING) as string,
|
||||||
});
|
});
|
||||||
|
|
||||||
const isStoreChannel = computed(() => form.channel === 'store');
|
const isStoreChannel = computed(() => form.channel === 'store');
|
||||||
@ -95,7 +95,7 @@ const showPhotoInput = computed(() =>
|
|||||||
|
|
||||||
const customerFormOpen = ref(false);
|
const customerFormOpen = ref(false);
|
||||||
const cartDetailOpen = ref(false);
|
const cartDetailOpen = ref(false);
|
||||||
const printAfterSave = ref(false);
|
const printAfterSave = ref(isCashierUser.value);
|
||||||
const selectedPaperSize = ref<'58mm' | '80mm'>(PaperSize.MM_80);
|
const selectedPaperSize = ref<'58mm' | '80mm'>(PaperSize.MM_80);
|
||||||
const photoState = ref<MediaUploadState>(createMediaUploadState());
|
const photoState = ref<MediaUploadState>(createMediaUploadState());
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ function buildFormData(): FormData {
|
|||||||
if (isCashierUser.value) {
|
if (isCashierUser.value) {
|
||||||
formData.append('channel', 'store');
|
formData.append('channel', 'store');
|
||||||
formData.append('price_type', 'retail');
|
formData.append('price_type', 'retail');
|
||||||
formData.append('payment_type', OrderPaymentType.CASH);
|
formData.append('payment_type', form.payment_type);
|
||||||
} else {
|
} else {
|
||||||
formData.append('channel', form.channel);
|
formData.append('channel', form.channel);
|
||||||
formData.append('price_type', form.price_type);
|
formData.append('price_type', form.price_type);
|
||||||
@ -227,13 +227,18 @@ function buildFormData(): FormData {
|
|||||||
formData.append('discount', parseRupiah(form.discount));
|
formData.append('discount', parseRupiah(form.discount));
|
||||||
formData.append('nego_price', parseRupiah(form.nego_price));
|
formData.append('nego_price', parseRupiah(form.nego_price));
|
||||||
formData.append('notes', form.notes);
|
formData.append('notes', form.notes);
|
||||||
formData.append('status', form.status);
|
|
||||||
|
if (isCashierUser.value) {
|
||||||
|
formData.append('status', OrderStatus.COMPLETED);
|
||||||
|
} else {
|
||||||
|
formData.append('status', form.status);
|
||||||
|
}
|
||||||
|
|
||||||
if (showPhotoInput.value) {
|
if (showPhotoInput.value) {
|
||||||
appendRootPhotosToFormData(formData, photoState.value);
|
appendRootPhotosToFormData(formData, photoState.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCreateMode.value && printAfterSave.value) {
|
if (isCreateMode.value && (isCashierUser.value || printAfterSave.value)) {
|
||||||
formData.append('print', '1');
|
formData.append('print', '1');
|
||||||
formData.append('paper_size', selectedPaperSize.value);
|
formData.append('paper_size', selectedPaperSize.value);
|
||||||
}
|
}
|
||||||
@ -340,6 +345,7 @@ function submit() {
|
|||||||
:can-create="can('orders.create')"
|
:can-create="can('orders.create')"
|
||||||
:cart-empty="cart.length === 0"
|
:cart-empty="cart.length === 0"
|
||||||
:submit-label="submitLabel"
|
:submit-label="submitLabel"
|
||||||
|
:is-cashier-user="isCashierUser"
|
||||||
/>
|
/>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
|
|||||||
@ -107,7 +107,7 @@ const emit = defineEmits<{
|
|||||||
<FieldError :errors="formErrors(form, 'shopee_order_id')" />
|
<FieldError :errors="formErrors(form, 'shopee_order_id')" />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field v-if="!isCashierUser">
|
<Field>
|
||||||
<FieldLabel for="payment_type" required>Tipe Pembayaran</FieldLabel>
|
<FieldLabel for="payment_type" required>Tipe Pembayaran</FieldLabel>
|
||||||
<Select v-model="form.payment_type" :disabled="isMarketplaceChannel">
|
<Select v-model="form.payment_type" :disabled="isMarketplaceChannel">
|
||||||
<SelectTrigger id="payment_type" class="w-full">
|
<SelectTrigger id="payment_type" class="w-full">
|
||||||
@ -163,7 +163,7 @@ const emit = defineEmits<{
|
|||||||
<FieldError :errors="formErrors(form, 'customer_id')" />
|
<FieldError :errors="formErrors(form, 'customer_id')" />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field>
|
<Field v-if="!isCashierUser">
|
||||||
<FieldLabel for="marketing">Marketing</FieldLabel>
|
<FieldLabel for="marketing">Marketing</FieldLabel>
|
||||||
<Select v-model="form.marketing_id" :disabled="isMarketingUser">
|
<Select v-model="form.marketing_id" :disabled="isMarketingUser">
|
||||||
<SelectTrigger id="marketing" class="w-full">
|
<SelectTrigger id="marketing" class="w-full">
|
||||||
|
|||||||
@ -248,6 +248,36 @@ function setupOrderDraftItems(User $user): ProductVariant
|
|||||||
|
|
||||||
expect($variant->fresh()->stock)->toBe($initialStock - 5);
|
expect($variant->fresh()->stock)->toBe($initialStock - 5);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('cashier creates order automatically sets status to completed and unsets marketing and customer', function () {
|
||||||
|
$user = User::factory()->create();
|
||||||
|
$user->assignRole('cashier');
|
||||||
|
$user->givePermissionTo(PermissionEnum::ORDERS_CREATE->value);
|
||||||
|
$user->forgetCachedPermissions();
|
||||||
|
|
||||||
|
setupOrderDraftItems($user);
|
||||||
|
|
||||||
|
$marketing = User::factory()->create();
|
||||||
|
$customer = Customer::factory()->create();
|
||||||
|
|
||||||
|
$this->actingAs($user)
|
||||||
|
->post(route('admin.manage.orders.store'), [
|
||||||
|
'customer_id' => $customer->id,
|
||||||
|
'marketing_id' => $marketing->id,
|
||||||
|
'channel' => OrderChannel::STORE->value,
|
||||||
|
'price_type' => PriceType::RETAIL->value,
|
||||||
|
'payment_type' => PaymentType::CASH->value,
|
||||||
|
'status' => OrderStatus::PENDING->value,
|
||||||
|
'discount' => 0,
|
||||||
|
])
|
||||||
|
->assertRedirect(route('admin.manage.orders.index'));
|
||||||
|
|
||||||
|
$order = Order::query()->latest()->first();
|
||||||
|
expect($order)->not->toBeNull();
|
||||||
|
expect($order->status)->toBe(OrderStatus::COMPLETED);
|
||||||
|
expect($order->marketing_id)->toBeNull();
|
||||||
|
expect($order->customer_id)->toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ─── Show ─────────────────────────────────────────────────
|
// ─── Show ─────────────────────────────────────────────────
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user