From 9ef381f00e31fae1125a5c0e992cfebdb85e5cc0 Mon Sep 17 00:00:00 2001 From: adonis Date: Sat, 5 Sep 2026 22:30:58 +0330 Subject: [PATCH] feat(tahesab): three-way mande decision UI including push to Tahesab Clarify overwrite vs keep vs push-to-tahesab, warn when app balance is zero, and update colleague wait-callback help text. Co-authored-by: Cursor --- src/api/tahesab.ts | 9 +- .../components/TahesabWalletBulkSync.vue | 18 +- .../menuPages/configuration/settingTypes.ts | 2 +- .../CustomerAccountingCodeModal.vue | 11 +- .../components/TahesabMandeDecisionModal.vue | 185 +++++++++++++++--- src/pages/menuPages/customers/base/index.vue | 25 ++- 6 files changed, 208 insertions(+), 42 deletions(-) diff --git a/src/api/tahesab.ts b/src/api/tahesab.ts index 0f23573..9a08fe5 100644 --- a/src/api/tahesab.ts +++ b/src/api/tahesab.ts @@ -254,13 +254,20 @@ export interface TahesabWalletSyncResult { /** همگام‌سازی مانده یک مشتری با ته‌حساب */ export const syncCustomerWalletFromTahesab = async ( customerId: number, - opts?: { overwrite?: boolean; keep?: boolean; ask_if_conflict?: boolean; always_ask?: boolean } + opts?: { + overwrite?: boolean + keep?: boolean + push_to_tahesab?: boolean + ask_if_conflict?: boolean + always_ask?: boolean + } ) => await useAxios.post( `/admin/customer/${customerId}/tahesab/sync-wallet`, { overwrite: opts?.overwrite ?? false, keep: opts?.keep ?? false, + push_to_tahesab: opts?.push_to_tahesab ?? false, ask_if_conflict: opts?.ask_if_conflict ?? true, always_ask: opts?.always_ask ?? false, } diff --git a/src/pages/menuPages/accounting/components/TahesabWalletBulkSync.vue b/src/pages/menuPages/accounting/components/TahesabWalletBulkSync.vue index e343a85..2be99ce 100644 --- a/src/pages/menuPages/accounting/components/TahesabWalletBulkSync.vue +++ b/src/pages/menuPages/accounting/components/TahesabWalletBulkSync.vue @@ -7,7 +7,7 @@

- همگام تکی: اول سندها و اختلاف را می‌بینید، بعد تأیید می‌کنید. دو مانده جمع نمی‌شوند. + همگام تکی: اول سندها و اختلاف را می‌بینید، بعد یکی از سه مسیر را تأیید می‌کنید (ته‌حساب→اپ، اپ→ته‌حساب حتی اگر اپ صفر باشد، یا نگه داشتن). دو مانده جمع نمی‌شوند. همگام همه فقط کیف خالی را می‌نشاند؛ تداخل برای تصمیم دستی می‌ماند.

@@ -154,6 +154,7 @@ ([]) const decisions = ref([]) const decidingId = ref(null) -const decidingMode = ref<'overwrite' | 'keep' | null>(null) +const decidingMode = ref<'overwrite' | 'keep' | 'push' | null>(null) const search = ref('') const page = ref(1) @@ -209,7 +210,7 @@ const listTotal = ref(0) const listLoading = ref(false) const rows = ref([]) const syncingId = ref(null) -const syncingMode = ref<'ask' | 'overwrite' | 'keep' | null>(null) +const syncingMode = ref<'ask' | 'overwrite' | 'keep' | 'push' | null>(null) const decisionVisible = ref(false) const decisionCustomerId = ref(null) const decisionResult = ref(null) @@ -321,7 +322,7 @@ async function openReview(customerId: number) { } } -async function onReviewDecide(mode: 'overwrite' | 'keep') { +async function onReviewDecide(mode: 'overwrite' | 'keep' | 'push') { const customerId = decisionCustomerId.value decisionVisible.value = false if (!customerId) return @@ -337,22 +338,25 @@ function dismissResult() { showDetails.value = false } -async function applyDecision(customerId: number, mode: 'overwrite' | 'keep') { +async function applyDecision(customerId: number, mode: 'overwrite' | 'keep' | 'push') { decidingId.value = customerId decidingMode.value = mode try { const res = await syncCustomerWalletFromTahesab(customerId, { overwrite: mode === 'overwrite', keep: mode === 'keep', + push_to_tahesab: mode === 'push', ask_if_conflict: false, }) decisions.value = decisions.value.filter(d => d.id !== customerId) needsDecision.value = Math.max(0, decisions.value.length) if (mode === 'keep') message.info(res.message || 'موجودی اپ حفظ شد') + else if (mode === 'push') message.success(res.message || 'مانده اپ روی ته‌حساب اعمال شد') else message.success(res.message || 'مانده ته‌حساب اعمال شد') await loadList() - } catch { - message.error('اعمال تصمیم ناموفق بود') + } catch (e: unknown) { + const data = (e as { response?: { data?: { message?: string } } })?.response?.data + message.error(data?.message || 'اعمال تصمیم ناموفق بود') } finally { decidingId.value = null decidingMode.value = null diff --git a/src/pages/menuPages/configuration/settingTypes.ts b/src/pages/menuPages/configuration/settingTypes.ts index bb43926..cfc6cd0 100644 --- a/src/pages/menuPages/configuration/settingTypes.ts +++ b/src/pages/menuPages/configuration/settingTypes.ts @@ -884,7 +884,7 @@ const KEY_HELP_FALLBACK: Record = { montzar_open_sell: 'وضعیت واقعی از سرویس خارجی خوانده می‌شود. روشن: ثبت سفارش فروش از طریق قیمت همکار مجاز است. خاموش: ثبت سفارش فروش از طریق قیمت همکار غیرفعال است.', montzar_order_wait_callback: - 'روشن (پیش‌فرض): بعد از ارسال سفارش به همکار، تا کالبک وضعیت (تأیید=۲ / رد=۴ یا ۶) یا استعلام مسیر وضعیت صبر می‌شود و کیف ثبت نمی‌شود. خاموش: مثل قبل با همان پاسخ HTTP همکار سفارش قطعی می‌شود.', + 'با منبع قیمت همکار، سفارش همیشه تا کالبک یا استعلام وضعیت در انتظار می‌ماند و کیف بعد از تأیید ثبت می‌شود. خاموش بودن این سوییچ دیگر مسیر قطعی بلافاصله را باز نمی‌کند. در رد همکار، SMS به ادمین‌های دارای ارسال پیامک می‌رود.', montzar_order_status_path: 'مسیر GET روی دامنه همکار (montzar_base_url) برای استعلام وضعیت اگر کالبک نرسید. پیش‌فرض /server/customer/order — با شماره سفارش همکار می‌شود /server/customer/order/40000.', montzar_closed: diff --git a/src/pages/menuPages/customers/base/components/CustomerAccountingCodeModal.vue b/src/pages/menuPages/customers/base/components/CustomerAccountingCodeModal.vue index c18b5c4..6af90e8 100644 --- a/src/pages/menuPages/customers/base/components/CustomerAccountingCodeModal.vue +++ b/src/pages/menuPages/customers/base/components/CustomerAccountingCodeModal.vue @@ -39,6 +39,7 @@ ) { close() } -async function applyWalletDecision(customerId: number, mode: 'overwrite' | 'keep') { +async function applyWalletDecision(customerId: number, mode: 'overwrite' | 'keep' | 'push') { if (props.provider === 'zarin') { + if (mode === 'push') { + message.warning('اعمال مانده اپ روی زرین در این نسخه پشتیبانی نمی‌شود') + return { ok: false, message: 'پشتیبانی نمی‌شود' } + } return syncCustomerWalletFromZarin(customerId, { overwrite: mode === 'overwrite', keep: mode === 'keep', @@ -131,11 +136,12 @@ async function applyWalletDecision(customerId: number, mode: 'overwrite' | 'keep return syncCustomerWalletFromTahesab(customerId, { overwrite: mode === 'overwrite', keep: mode === 'keep', + push_to_tahesab: mode === 'push', ask_if_conflict: false, }) } -async function onDecide(mode: 'overwrite' | 'keep') { +async function onDecide(mode: 'overwrite' | 'keep' | 'push') { const pending = pendingPayload.value decisionVisible.value = false if (!pending) return @@ -144,6 +150,7 @@ async function onDecide(mode: 'overwrite' | 'keep') { await saveCode(pending.customerId, pending.body) const res = await applyWalletDecision(pending.customerId, mode) if (mode === 'keep') message.info(res.message || 'موجودی اپ حفظ شد') + else if (mode === 'push') message.success(res.message || 'مانده اپ روی ته‌حساب اعمال شد') else message.success(res.message || 'مانده حسابداری روی کیف اعمال شد') emit('success') } catch (e) { diff --git a/src/pages/menuPages/customers/base/components/TahesabMandeDecisionModal.vue b/src/pages/menuPages/customers/base/components/TahesabMandeDecisionModal.vue index 287dc6c..2d7c79b 100644 --- a/src/pages/menuPages/customers/base/components/TahesabMandeDecisionModal.vue +++ b/src/pages/menuPages/customers/base/components/TahesabMandeDecisionModal.vue @@ -1,16 +1,24 @@