Require review before Tahesab wallet sync and harden accounting admin UX.
Single-customer and row sync preview balances with documents before overwrite/keep; bulk sync keeps confirm. Also ship Zarin wallet sync actions, field help, and get_user cache improvements. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,21 +27,26 @@
|
||||
برای پاک کردن کد، فیلد را خالی بگذارید و ذخیره کنید.
|
||||
</p>
|
||||
<p
|
||||
v-if="provider === 'tahesab'"
|
||||
v-if="provider === 'tahesab' || provider === 'zarin'"
|
||||
class="m-0 text-xs"
|
||||
style="color: var(--admin-text-secondary)"
|
||||
>
|
||||
بعد از ذخیره کد تهحساب، اگر موجودی اپ با مانده تهحساب فرق داشته باشد از شما تصمیم گرفته میشود.
|
||||
قبل از ذخیره، اگر مانده اپ با حسابداری فرق داشته باشد از شما تأیید گرفته میشود؛ بعد اعمال میشود.
|
||||
</p>
|
||||
</div>
|
||||
</BasicModal>
|
||||
|
||||
<TahesabMandeDecisionModal
|
||||
v-model:visible="decisionVisible"
|
||||
:source-label="provider === 'zarin' ? 'زرین' : 'تهحساب'"
|
||||
:app-gold="decision?.app_gold"
|
||||
:app-cash="decision?.app_cash"
|
||||
:tahesab-gold="decision?.tahesab_gold"
|
||||
:tahesab-cash="decision?.tahesab_cash"
|
||||
:tahesab-gold="decision?.tahesab_gold ?? decision?.zarin_gold"
|
||||
:tahesab-cash="decision?.tahesab_cash ?? decision?.zarin_cash"
|
||||
:gold-delta="decision?.gold_delta"
|
||||
:rial-delta="decision?.rial_delta"
|
||||
:wallet-docs="decision?.wallet_docs"
|
||||
:tahesab-docs="decision?.tahesab_docs"
|
||||
@decide="onDecide"
|
||||
/>
|
||||
</template>
|
||||
@@ -52,9 +57,14 @@ import { message } from 'ant-design-vue'
|
||||
import BasicModal from '@/components/BasicModal.vue'
|
||||
import { updateCustomer } from '@/api/customer'
|
||||
import {
|
||||
previewCustomerWalletFromTahesab,
|
||||
syncCustomerWalletFromTahesab,
|
||||
type TahesabWalletSyncResult,
|
||||
} from '@/api/tahesab'
|
||||
import {
|
||||
previewCustomerWalletFromZarin,
|
||||
syncCustomerWalletFromZarin,
|
||||
} from '@/api/zarin'
|
||||
import type { Customer } from '@/model/customer'
|
||||
import type { AccountingProvider } from '@/utils/config'
|
||||
import { displayAccountingCode, normalizeAccountingCode } from '@/utils/accountingCode'
|
||||
@@ -76,7 +86,7 @@ const loading = ref(false)
|
||||
const code = ref('')
|
||||
const decisionVisible = ref(false)
|
||||
const decision = ref<TahesabWalletSyncResult['result'] | null>(null)
|
||||
const savedCustomerId = ref<number | null>(null)
|
||||
const pendingPayload = ref<{ customerId: number; body: Record<string, string>; nextCode: string } | null>(null)
|
||||
|
||||
const visibleProxy = computed({
|
||||
get: () => props.visible,
|
||||
@@ -103,47 +113,44 @@ function close() {
|
||||
visibleProxy.value = false
|
||||
}
|
||||
|
||||
async function maybeSyncTahesabWallet(customerId: number, previousCode: string, nextCode: string) {
|
||||
if (props.provider !== 'tahesab') return
|
||||
if (!nextCode || nextCode === previousCode) return
|
||||
|
||||
try {
|
||||
const res = await syncCustomerWalletFromTahesab(customerId, { ask_if_conflict: true })
|
||||
if (res.needs_decision || res.result?.needs_decision) {
|
||||
decision.value = res.result ?? null
|
||||
savedCustomerId.value = customerId
|
||||
decisionVisible.value = true
|
||||
return
|
||||
}
|
||||
if (res.result?.applied) {
|
||||
message.success(res.message || 'مانده تهحساب روی کیف اعمال شد')
|
||||
} else if (res.message) {
|
||||
message.info(res.message)
|
||||
}
|
||||
} catch (e) {
|
||||
// خطای همگامسازی مانع ذخیره کد نیست
|
||||
console.error(e)
|
||||
}
|
||||
async function saveCode(customerId: number, body: Record<string, string>) {
|
||||
await updateCustomer(customerId, body as Customer)
|
||||
message.success('کد حسابداری ذخیره شد.')
|
||||
emit('success')
|
||||
close()
|
||||
}
|
||||
|
||||
async function onDecide(mode: 'overwrite' | 'keep') {
|
||||
const customerId = savedCustomerId.value
|
||||
decisionVisible.value = false
|
||||
if (!customerId) return
|
||||
try {
|
||||
const res = await syncCustomerWalletFromTahesab(customerId, {
|
||||
async function applyWalletDecision(customerId: number, mode: 'overwrite' | 'keep') {
|
||||
if (props.provider === 'zarin') {
|
||||
return syncCustomerWalletFromZarin(customerId, {
|
||||
overwrite: mode === 'overwrite',
|
||||
keep: mode === 'keep',
|
||||
ask_if_conflict: false,
|
||||
})
|
||||
if (mode === 'keep') {
|
||||
message.info(res.message || 'موجودی اپ حفظ شد')
|
||||
} else {
|
||||
message.success(res.message || 'مانده تهحساب روی کیف اعمال شد')
|
||||
}
|
||||
}
|
||||
return syncCustomerWalletFromTahesab(customerId, {
|
||||
overwrite: mode === 'overwrite',
|
||||
keep: mode === 'keep',
|
||||
ask_if_conflict: false,
|
||||
})
|
||||
}
|
||||
|
||||
async function onDecide(mode: 'overwrite' | 'keep') {
|
||||
const pending = pendingPayload.value
|
||||
decisionVisible.value = false
|
||||
if (!pending) return
|
||||
try {
|
||||
loading.value = true
|
||||
await saveCode(pending.customerId, pending.body)
|
||||
const res = await applyWalletDecision(pending.customerId, mode)
|
||||
if (mode === 'keep') message.info(res.message || 'موجودی اپ حفظ شد')
|
||||
else message.success(res.message || 'مانده حسابداری روی کیف اعمال شد')
|
||||
emit('success')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
pendingPayload.value = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,13 +168,38 @@ async function submit() {
|
||||
? { pargar_account_id: normalized }
|
||||
: { moshtari_code: normalized }
|
||||
|
||||
const needsWalletAsk =
|
||||
(props.provider === 'tahesab' || props.provider === 'zarin')
|
||||
&& !!normalized
|
||||
&& normalized !== previousCode
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
await updateCustomer(props.customer.id, payload as Customer)
|
||||
message.success('کد حسابداری ذخیره شد.')
|
||||
emit('success')
|
||||
close()
|
||||
await maybeSyncTahesabWallet(props.customer.id, previousCode, normalized)
|
||||
if (needsWalletAsk) {
|
||||
try {
|
||||
const preview = props.provider === 'zarin'
|
||||
? await previewCustomerWalletFromZarin(props.customer.id, normalized)
|
||||
: await previewCustomerWalletFromTahesab(props.customer.id, normalized)
|
||||
|
||||
if (preview.needs_decision || preview.result?.needs_decision) {
|
||||
pendingPayload.value = {
|
||||
customerId: props.customer.id,
|
||||
body: payload as Record<string, string>,
|
||||
nextCode: normalized,
|
||||
}
|
||||
decision.value = preview.result ?? null
|
||||
decisionVisible.value = true
|
||||
return
|
||||
}
|
||||
if (preview.ok === false && preview.message) {
|
||||
message.warning(preview.message + ' — فقط کد ذخیره میشود')
|
||||
}
|
||||
} catch {
|
||||
message.warning('مانده حسابداری خوانده نشد — فقط کد ذخیره میشود')
|
||||
}
|
||||
}
|
||||
|
||||
await saveCode(props.customer.id, payload as Record<string, string>)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user