Submit multi-company cart as one unified order and invoice.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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()
|
||||
|
||||
+38
-35
@@ -117,9 +117,9 @@ export const useOrderStore = defineStore('order', () => {
|
||||
/**
|
||||
* سفارش بدون روش تسویه ثبت میشود؛ مشتری بعد از قیمتگذاری مدیریت
|
||||
* روش تسویه را انتخاب میکند.
|
||||
* سبد چندشرکتی: برای هر شرکت یک سفارش جدا ساخته میشود.
|
||||
* اقلام همه شرکتها در یک فاکتور واحد ثبت میشوند.
|
||||
*/
|
||||
async function submitOrder(cart: Cart): Promise<Order[]> {
|
||||
async function submitOrder(cart: Cart): Promise<Order> {
|
||||
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<Order>('/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<Order>('/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<string, (typeof lists)[number][number]>()
|
||||
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,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -154,6 +154,8 @@ export interface OrderItem {
|
||||
discount?: number
|
||||
lineTotal?: number
|
||||
notes?: string
|
||||
companyId?: string
|
||||
companyName?: string
|
||||
}
|
||||
|
||||
export interface OrderStatusHistoryEntry {
|
||||
|
||||
@@ -194,7 +194,7 @@ const quickLinks = [
|
||||
{{ submitting ? 'در حال ثبت…' : 'ثبت پیشسفارش' }}
|
||||
</button>
|
||||
<p class="cart-summary-card__note">
|
||||
اقلام همه شرکتها در یک سبد هستند؛ با ثبت، برای هر شرکت یک پیشسفارش جدا ساخته میشود.
|
||||
اقلام همه شرکتها در یک سبد و یک فاکتور ثبت میشوند؛ پس از قیمتگذاری، یکبار تسویه میکنید.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ const emit = defineEmits<{
|
||||
</div>
|
||||
</div>
|
||||
<p class="cart-mobile-page__hint">
|
||||
پس از ثبت، برای هر شرکت یک پیشسفارش جداگانه ساخته میشود و مدیریت قیمتگذاری میکند.
|
||||
پس از ثبت، همه اقلام در یک پیشسفارش واحد قرار میگیرند و مدیریت قیمتگذاری میکند.
|
||||
</p>
|
||||
<BaseButton block :loading="submitting" @click="emit('checkout')">ثبت پیشسفارش</BaseButton>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,6 @@ const catalogStore = useCatalogStore()
|
||||
const bankAccounts = ref<BankAccount[]>([])
|
||||
|
||||
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) {
|
||||
|
||||
@@ -103,18 +103,18 @@ watch(destinationAccountId, () => {
|
||||
})
|
||||
|
||||
const bankAccounts = ref(
|
||||
[] as Awaited<ReturnType<typeof orderStore.getBankAccountsForCompany>>,
|
||||
[] as Awaited<ReturnType<typeof orderStore.getBankAccountsForOrder>>,
|
||||
)
|
||||
|
||||
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 = []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user