From bc35c4f88740d4f55a01a89b2e828a42cc302ba3 Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Sat, 15 Aug 2026 08:52:50 +0200 Subject: [PATCH] Submit multi-company cart as one unified order and invoice. Co-authored-by: Cursor --- src/composables/useCartPage.ts | 12 +-- src/stores/order.ts | 73 ++++++++++--------- src/types/index.ts | 2 + src/views/cart/components/DesktopCartPage.vue | 2 +- src/views/cart/components/MobileCartPage.vue | 2 +- src/views/checkout/CashSettlementView.vue | 16 ++-- src/views/orders/OrderDetailView.vue | 10 +-- 7 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/composables/useCartPage.ts b/src/composables/useCartPage.ts index ecfdaf5..be892b9 100644 --- a/src/composables/useCartPage.ts +++ b/src/composables/useCartPage.ts @@ -46,17 +46,9 @@ export function useCartPage() { submitError.value = 'سبد خرید خالی است یا با سرور همگام نشد.' return } - const created = await orderStore.submitOrder(cartStore.activeCart) + const order = await orderStore.submitOrder(cartStore.activeCart) await cartStore.hydrate() - if (created.length === 1) { - router.replace(`/orders/${created[0]!.id}/success`) - return - } - // چند شرکت → چند سفارش؛ به لیست سفارش‌ها برو - router.replace({ - path: '/orders', - query: { submitted: String(created.length) }, - }) + router.replace(`/orders/${order.id}/success`) } catch (e) { submitError.value = e instanceof Error ? e.message : 'ثبت سفارش ناموفق بود.' await cartStore.hydrate() diff --git a/src/stores/order.ts b/src/stores/order.ts index 3fe71bf..ec30562 100644 --- a/src/stores/order.ts +++ b/src/stores/order.ts @@ -117,9 +117,9 @@ export const useOrderStore = defineStore('order', () => { /** * سفارش بدون روش تسویه ثبت می‌شود؛ مشتری بعد از قیمت‌گذاری مدیریت * روش تسویه را انتخاب می‌کند. - * سبد چندشرکتی: برای هر شرکت یک سفارش جدا ساخته می‌شود. + * اقلام همه شرکت‌ها در یک فاکتور واحد ثبت می‌شوند. */ - async function submitOrder(cart: Cart): Promise { + async function submitOrder(cart: Cart): Promise { if (!cart.items.length) { throw new Error('سبد خرید خالی است.') } @@ -134,43 +134,25 @@ export const useOrderStore = defineStore('order', () => { throw new Error('شرکت سبد مشخص نیست. سبد را خالی کنید و دوباره اضافه کنید.') } - const createdOrders: Order[] = [] try { - for (const companyId of companyIds) { - const itemsForOrder = cart.items.filter((item) => item.companyId === companyId) - if (!itemsForOrder.length) continue - - const order = await apiRequest('/orders', { - method: 'POST', - body: { - companyId, - notes: cart.notes, - items: itemsForOrder.map((item) => ({ - productId: item.productId, - meterage: Number(item.meterage), - notes: item.notes, - })), - }, - }) - orders.value.unshift(order) - createdOrders.push(order) - } + const order = await apiRequest('/orders', { + method: 'POST', + body: { + companyId: companyIds[0], + notes: cart.notes, + items: cart.items.map((item) => ({ + productId: item.productId, + meterage: Number(item.meterage), + notes: item.notes, + })), + }, + }) + orders.value.unshift(order) + clearCheckDraft() + return order } catch (e) { - if (createdOrders.length) { - // بخشی ثبت شده؛ سفارش‌های موفق را نگه می‌داریم و خطا را با توضیح برمی‌گردانیم - clearCheckDraft() - const names = createdOrders.map((o) => o.orderNumber).join('، ') - throw new Error( - e instanceof ApiError - ? `${e.message} (سفارش‌های ثبت‌شده: ${names})` - : `ثبت بخشی از سفارش‌ها ناموفق بود. ثبت‌شده: ${names}`, - ) - } throw new Error(e instanceof ApiError ? e.message : 'ثبت سفارش ناموفق بود.') } - - clearCheckDraft() - return createdOrders } /** انتخاب روش تسویه پس از صدور فاکتور. */ @@ -256,6 +238,26 @@ export const useOrderStore = defineStore('order', () => { } } + async function getBankAccountsForOrder(order: Order) { + const companyIds = [ + ...new Set( + [ + order.companyId, + ...order.items.map((item) => item.companyId).filter(Boolean), + ].filter(Boolean) as string[], + ), + ] + const catalog = useCatalogStore() + const lists = await Promise.all(companyIds.map((id) => catalog.loadBankAccounts(id))) + const byId = new Map() + for (const list of lists) { + for (const account of list) { + byId.set(account.id, account) + } + } + return [...byId.values()] + } + async function getBankAccountsForCompany(companyId: string) { return useCatalogStore().loadBankAccounts(companyId) } @@ -284,6 +286,7 @@ export const useOrderStore = defineStore('order', () => { hydrate, resetLocal, fetchOrder, + getBankAccountsForOrder, getBankAccountsForCompany, } }) diff --git a/src/types/index.ts b/src/types/index.ts index 86f403b..ef88877 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -154,6 +154,8 @@ export interface OrderItem { discount?: number lineTotal?: number notes?: string + companyId?: string + companyName?: string } export interface OrderStatusHistoryEntry { diff --git a/src/views/cart/components/DesktopCartPage.vue b/src/views/cart/components/DesktopCartPage.vue index cdbdc0f..0b4ac62 100644 --- a/src/views/cart/components/DesktopCartPage.vue +++ b/src/views/cart/components/DesktopCartPage.vue @@ -194,7 +194,7 @@ const quickLinks = [ {{ submitting ? 'در حال ثبت…' : 'ثبت پیش‌سفارش' }}

- اقلام همه شرکت‌ها در یک سبد هستند؛ با ثبت، برای هر شرکت یک پیش‌سفارش جدا ساخته می‌شود. + اقلام همه شرکت‌ها در یک سبد و یک فاکتور ثبت می‌شوند؛ پس از قیمت‌گذاری، یک‌بار تسویه می‌کنید.

diff --git a/src/views/cart/components/MobileCartPage.vue b/src/views/cart/components/MobileCartPage.vue index de4e25b..777150b 100644 --- a/src/views/cart/components/MobileCartPage.vue +++ b/src/views/cart/components/MobileCartPage.vue @@ -100,7 +100,7 @@ const emit = defineEmits<{

- پس از ثبت، برای هر شرکت یک پیش‌سفارش جداگانه ساخته می‌شود و مدیریت قیمت‌گذاری می‌کند. + پس از ثبت، همه اقلام در یک پیش‌سفارش واحد قرار می‌گیرند و مدیریت قیمت‌گذاری می‌کند.

ثبت پیش‌سفارش diff --git a/src/views/checkout/CashSettlementView.vue b/src/views/checkout/CashSettlementView.vue index 21c3d68..63fbdcd 100644 --- a/src/views/checkout/CashSettlementView.vue +++ b/src/views/checkout/CashSettlementView.vue @@ -16,7 +16,6 @@ const catalogStore = useCatalogStore() const bankAccounts = ref([]) const { orderId, order } = useRequirePricedOrder() -const companyId = computed(() => order.value?.companyId ?? '') const companyName = computed(() => order.value?.companyName ?? '') watch( @@ -28,14 +27,14 @@ watch( ) watch( - companyId, + () => order.value?.id, async (id) => { - if (!id) { + if (!id || !order.value) { bankAccounts.value = [] return } - if (!catalogStore.getCompany(id)) await catalogStore.loadCompanies() - bankAccounts.value = await catalogStore.loadBankAccounts(id) + if (!catalogStore.companies.length) await catalogStore.loadCompanies() + bankAccounts.value = await orderStore.getBankAccountsForOrder(order.value) }, { immediate: true }, ) @@ -51,9 +50,10 @@ const expiryMessage = computed(() => { }) const accountsSectionTitle = computed(() => { - const company = catalogStore.getCompany(companyId.value) - const name = (company?.name || companyName.value).replace(/^شرکت\s+/u, '') - return `شماره حساب‌های شرکت ${name}` + const name = companyName.value.replace(/^شرکت\s+/u, '') + return name + ? `شماره حساب‌های واریز — ${name}` + : 'شماره حساب‌های واریز' }) function formatCardNumber(value: string) { diff --git a/src/views/orders/OrderDetailView.vue b/src/views/orders/OrderDetailView.vue index 04f9948..2b789df 100644 --- a/src/views/orders/OrderDetailView.vue +++ b/src/views/orders/OrderDetailView.vue @@ -103,18 +103,18 @@ watch(destinationAccountId, () => { }) const bankAccounts = ref( - [] as Awaited>, + [] as Awaited>, ) watch( - () => order.value?.companyId, - async (companyId) => { - if (!companyId) { + () => order.value?.id, + async (id) => { + if (!id || !order.value) { bankAccounts.value = [] return } try { - bankAccounts.value = await orderStore.getBankAccountsForCompany(companyId) + bankAccounts.value = await orderStore.getBankAccountsForOrder(order.value) } catch { bankAccounts.value = [] }