Fix checkout order submit payload and cash settlement UX.
Drop non-whitelisted fields that caused 400 on POST /orders, prevent double submit on checks, and only show cash success after create succeeds. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+39
-9
@@ -115,21 +115,36 @@ export const useOrderStore = defineStore('order', () => {
|
||||
throw new Error('سبد خرید با سرور همگام نیست. لطفاً دوباره محصولات را به سبد اضافه کنید.')
|
||||
}
|
||||
|
||||
const companyItems = cart.items.filter((item) => item.companyId === companyId)
|
||||
const itemsForOrder = companyItems.length ? companyItems : cart.items
|
||||
|
||||
const body = {
|
||||
companyId,
|
||||
settlementType,
|
||||
settlementMethod: settlementType,
|
||||
checkMode: settlementType === 'check' ? (checkMode ?? 'full') : undefined,
|
||||
notes: cart.notes,
|
||||
items: cart.items.map((item) => ({
|
||||
items: itemsForOrder.map((item) => ({
|
||||
productId: item.productId,
|
||||
meterage: item.meterage,
|
||||
requestedMeterage: item.meterage,
|
||||
notes: item.notes,
|
||||
})),
|
||||
checks:
|
||||
settlementType === 'check' && checks
|
||||
? checks.map(({ id: _id, ...rest }) => rest)
|
||||
? checks.map((c) => ({
|
||||
amount: c.amount,
|
||||
dueDate: c.dueDate,
|
||||
sayadId: c.sayadId,
|
||||
checkNumber: c.checkNumber,
|
||||
ownerNationalId: c.ownerNationalId,
|
||||
ownerFirstName: c.ownerFirstName,
|
||||
ownerLastName: c.ownerLastName,
|
||||
bankName: c.bankName,
|
||||
branchName: c.branchName,
|
||||
frontImage: c.frontImage,
|
||||
backImage: c.backImage,
|
||||
notes: c.notes,
|
||||
mode: c.mode,
|
||||
}))
|
||||
: undefined,
|
||||
}
|
||||
|
||||
@@ -154,7 +169,7 @@ export const useOrderStore = defineStore('order', () => {
|
||||
receipt: Omit<CashPaymentReceipt, 'id' | 'submittedAt'>,
|
||||
) {
|
||||
try {
|
||||
const order = await apiRequest<Order>(`/orders/${orderId}/cash-receipt`, {
|
||||
await apiRequest(`/orders/${orderId}/cash-receipt`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
amount: receipt.amount,
|
||||
@@ -166,9 +181,10 @@ export const useOrderStore = defineStore('order', () => {
|
||||
notes: receipt.notes,
|
||||
},
|
||||
})
|
||||
const idx = orders.value.findIndex((o) => o.id === orderId)
|
||||
if (idx >= 0) orders.value[idx] = order
|
||||
else orders.value.unshift(order)
|
||||
const order = await fetchOrder(orderId)
|
||||
if (!order) {
|
||||
throw new Error('رسید ثبت شد ولی دریافت سفارش ناموفق بود.')
|
||||
}
|
||||
return order
|
||||
} catch (e) {
|
||||
throw new Error(e instanceof ApiError ? e.message : 'ثبت رسید ناموفق بود.')
|
||||
@@ -180,7 +196,21 @@ export const useOrderStore = defineStore('order', () => {
|
||||
const order = await apiRequest<Order>(`/orders/${orderId}/checks`, {
|
||||
method: 'PATCH',
|
||||
body: {
|
||||
checks: checks.map(({ id: _id, ...rest }) => rest),
|
||||
checks: checks.map((c) => ({
|
||||
amount: c.amount,
|
||||
dueDate: c.dueDate,
|
||||
sayadId: c.sayadId,
|
||||
checkNumber: c.checkNumber,
|
||||
ownerNationalId: c.ownerNationalId,
|
||||
ownerFirstName: c.ownerFirstName,
|
||||
ownerLastName: c.ownerLastName,
|
||||
bankName: c.bankName,
|
||||
branchName: c.branchName,
|
||||
frontImage: c.frontImage,
|
||||
backImage: c.backImage,
|
||||
notes: c.notes,
|
||||
mode: c.mode,
|
||||
})),
|
||||
},
|
||||
})
|
||||
const idx = orders.value.findIndex((o) => o.id === orderId)
|
||||
|
||||
@@ -105,8 +105,8 @@ async function registerReceipt() {
|
||||
<div class="cash-page__scroll page__scroll">
|
||||
<FormErrorBanner :message="formError" />
|
||||
|
||||
<div class="cash-page__success">
|
||||
<IconSuccessCircle :size="56" />
|
||||
<div class="cash-page__success" :class="{ 'cash-page__success--done': createdOrder }">
|
||||
<IconSuccessCircle v-if="createdOrder" :size="56" />
|
||||
<p class="cash-page__success-title">
|
||||
{{ createdOrder ? 'فاکتور شما ثبت شد.' : 'آماده ثبت فاکتور نقدی' }}
|
||||
</p>
|
||||
@@ -154,8 +154,8 @@ async function registerReceipt() {
|
||||
<p class="desktop-page__subtitle">{{ expiryMessage }}</p>
|
||||
</header>
|
||||
|
||||
<div class="cash-page__success">
|
||||
<IconSuccessCircle :size="56" />
|
||||
<div class="cash-page__success" :class="{ 'cash-page__success--done': createdOrder }">
|
||||
<IconSuccessCircle v-if="createdOrder" :size="56" />
|
||||
<p class="cash-page__success-title">
|
||||
{{ createdOrder ? 'فاکتور شما ثبت شد.' : 'آماده ثبت فاکتور نقدی' }}
|
||||
</p>
|
||||
@@ -228,6 +228,10 @@ async function registerReceipt() {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.cash-page__success--done .cash-page__success-title {
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ const cartStore = useCartStore()
|
||||
const orderStore = useOrderStore()
|
||||
const authStore = useAuthStore()
|
||||
const formError = ref('')
|
||||
const submitting = ref(false)
|
||||
|
||||
const isCheckout = computed(() => route.name === 'check-list')
|
||||
|
||||
@@ -90,7 +91,9 @@ function toggleMenu(id: string) {
|
||||
|
||||
async function submitOrder() {
|
||||
if (!authStore.user || !cartStore.activeCart || checks.value.length === 0) return
|
||||
if (submitting.value) return
|
||||
formError.value = ''
|
||||
submitting.value = true
|
||||
|
||||
try {
|
||||
const order = await orderStore.submitOrder(
|
||||
@@ -104,6 +107,8 @@ async function submitOrder() {
|
||||
router.replace(`/orders/${order.id}/success`)
|
||||
} catch (e) {
|
||||
formError.value = e instanceof Error ? e.message : 'ثبت سفارش ناموفق بود.'
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -194,7 +199,12 @@ async function submitOrder() {
|
||||
</div>
|
||||
|
||||
<div v-if="isCheckout && orderStore.draftChecks.length > 0" class="check-list-page__footer">
|
||||
<BaseButton block :disabled="checks.length === 0" @click="submitOrder">
|
||||
<BaseButton
|
||||
block
|
||||
:disabled="checks.length === 0"
|
||||
:loading="submitting"
|
||||
@click="submitOrder"
|
||||
>
|
||||
ارسال برای بررسی
|
||||
</BaseButton>
|
||||
</div>
|
||||
@@ -269,7 +279,12 @@ async function submitOrder() {
|
||||
<strong>{{ toPersianDigits(String(rass.rassDays)) }} روز</strong>
|
||||
</div>
|
||||
<div v-if="isCheckout && orderStore.draftChecks.length > 0" class="desktop-summary-panel__action">
|
||||
<BaseButton block :disabled="checks.length === 0" @click="submitOrder">
|
||||
<BaseButton
|
||||
block
|
||||
:disabled="checks.length === 0"
|
||||
:loading="submitting"
|
||||
@click="submitOrder"
|
||||
>
|
||||
ارسال برای بررسی
|
||||
</BaseButton>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user