From 93d677fa9df2912fc9778cb1dda30996a980a5a6 Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Sun, 8 Nov 2026 11:58:05 +0330 Subject: [PATCH] Add preparing tab, clarify order status actions and stage banners --- src/composables/useOrdersPage.ts | 11 +- src/types/index.ts | 1 + src/utils/orderStatus.ts | 14 ++ src/views/orders/OrderPricingView.vue | 63 ++++- .../orders/components/OrderDetailContent.vue | 221 +++++++++++++++++- 5 files changed, 299 insertions(+), 11 deletions(-) diff --git a/src/composables/useOrdersPage.ts b/src/composables/useOrdersPage.ts index a642443..e450326 100644 --- a/src/composables/useOrdersPage.ts +++ b/src/composables/useOrdersPage.ts @@ -15,7 +15,7 @@ export function useOrdersPage() { const companies = ref([]) const customers = ref([]) const orderList = ref([]) - const activeTab = ref('all') + const activeTab = ref(typeof route.query.tab === 'string' && route.query.tab.trim() ? route.query.tab.trim() : 'all') const selectedOrderId = ref('') const searchQuery = ref('') const showAddModal = ref(false) @@ -140,6 +140,15 @@ export function useOrdersPage() { }, ) + watch( + () => route.query.tab, + (tab) => { + if (typeof tab === 'string' && tab.trim()) { + activeTab.value = tab.trim() + } + }, + ) + function selectOrder(order: Order, openDetail = false) { selectedOrderId.value = order.id if (openDetail) { diff --git a/src/types/index.ts b/src/types/index.ts index c8d8590..f156c26 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -7,6 +7,7 @@ export type OrderStatus = | 'needs_correction' | 'check_correction' | 'final_approval' + | 'preparing' | 'shipped' | 'delivered' | 'cancelled' diff --git a/src/utils/orderStatus.ts b/src/utils/orderStatus.ts index 1da7c83..af3b9ac 100644 --- a/src/utils/orderStatus.ts +++ b/src/utils/orderStatus.ts @@ -13,6 +13,7 @@ export const ORDER_STATUS_META: Record = { needs_correction: { label: 'نیاز به اصلاح', tone: 'danger' }, check_correction: { label: 'نیاز به اصلاح چک', tone: 'warning' }, final_approval: { label: 'تأیید نهایی', tone: 'success' }, + preparing: { label: 'در حال آماده‌سازی', tone: 'info' }, shipped: { label: 'ارسال شده', tone: 'info' }, delivered: { label: 'تحویل شده', tone: 'delivered' }, cancelled: { label: 'لغو شده', tone: 'neutral' }, @@ -74,6 +75,18 @@ export function canPriceOrder(order: { return PRE_INVOICE_ADMIN_STATUSES.includes(order.status) } +/** فاکتور صادر شده ولی هنوز تسویه تکمیل نشده و ادمین می‌تواند در صورت نیاز قیمت را بازبینی کند */ +export function canEditInvoice(order: { + status: OrderStatus + rawStatus?: RawOrderStatus +}): boolean { + const raw = order.rawStatus + if (raw) { + return raw === 'awaiting_settlement' || raw === 'awaiting_settlement_fix' + } + return order.status === 'awaiting_customer' +} + export const ORDER_TABS = [ { key: 'all', label: 'همه' }, { key: 'pending_review', label: 'در انتظار بررسی' }, @@ -83,6 +96,7 @@ export const ORDER_TABS = [ { key: 'check_correction', label: 'اصلاح چک' }, { key: 'needs_correction', label: 'نیاز به اصلاح' }, { key: 'final_approval', label: 'تأیید نهایی' }, + { key: 'preparing', label: 'آماده‌سازی' }, { key: 'shipped', label: 'ارسال شده' }, { key: 'delivered', label: 'تحویل شده' }, ] as const diff --git a/src/views/orders/OrderPricingView.vue b/src/views/orders/OrderPricingView.vue index 1d4e1e1..8b5e79d 100644 --- a/src/views/orders/OrderPricingView.vue +++ b/src/views/orders/OrderPricingView.vue @@ -55,7 +55,7 @@ const invoiceSent = computed(() => : false, ) -const canSendInvoice = computed(() => !!order.value?.finalAmount && !invoiceSent.value) +const canSendInvoice = computed(() => !!order.value?.finalAmount) async function loadOrder() { loading.value = true @@ -185,10 +185,13 @@ async function sendInvoice() { return } + const isAlreadySent = invoiceSent.value const ok = await confirm({ - title: 'ارسال فاکتور برای مشتری', - message: `فاکتور ${formatCurrency(order.value.finalAmount)} برای مشتری ارسال می‌شود و او روش تسویه را انتخاب می‌کند. ادامه می‌دهید؟`, - confirmLabel: 'ارسال فاکتور', + title: isAlreadySent ? 'به‌روزرسانی فاکتور برای مشتری' : 'ارسال فاکتور برای مشتری', + message: isAlreadySent + ? `فاکتور به‌روزشده با مبلغ ${formatCurrency(order.value.finalAmount)} برای مشتری ارسال می‌شود. ادامه می‌دهید؟` + : `فاکتور ${formatCurrency(order.value.finalAmount)} برای مشتری ارسال می‌شود و او امکان پرداخت/ثبت چک را خواهد داشت. ادامه می‌دهید؟`, + confirmLabel: isAlreadySent ? 'ارسال مجدد فاکتور' : 'ارسال فاکتور', cancelLabel: 'انصراف', }) if (!ok) return @@ -200,7 +203,7 @@ async function sendInvoice() { note: customerNote.value.trim() || undefined, }) order.value = updated - toast.success('فاکتور برای مشتری ارسال شد.') + toast.success(isAlreadySent ? 'فاکتور با موفقیت به‌روزرسانی شد.' : 'فاکتور برای مشتری ارسال شد.') } catch (err) { toast.error(err instanceof ApiError ? err.message : 'ارسال فاکتور انجام نشد.') } finally { @@ -231,7 +234,7 @@ async function sendInvoice() { :disabled="!canSendInvoice || sending || saving" @click="sendInvoice" > - {{ sending ? 'در حال ارسال…' : 'ارسال فاکتور برای مشتری' }} + {{ sending ? 'در حال ارسال…' : invoiceSent ? 'به‌روزرسانی و ارسال مجدد فاکتور' : 'ارسال فاکتور برای مشتری' }}