feat(tahesab): add local status reset before resending wiped documents

Confirm and call reset-local so the pending count includes previously successful rows, then send all as usual.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-03 13:43:16 +03:30
co-authored by Cursor
parent 62a6a91455
commit 11f60f205a
4 changed files with 84 additions and 11 deletions
+8
View File
@@ -101,6 +101,14 @@ export const stopTahesabDocSync = async () =>
'/admin/tahesab/doc-sync/stop'
)
export const resetTahesabLocalDocs = async () =>
await useAxios.post<{
ok: boolean
message: string
cleared: number
summary: TahesabPendingSummary
}>('/admin/tahesab/doc-sync/reset-local')
export const startTahesabCustomerOutbound = async () =>
await useAxios.post<{ ok: boolean; message: string; doc_sync: TahesabDocSyncState }>(
'/admin/tahesab/customer-sync/outbound/start'
@@ -7,24 +7,38 @@
<p class="mb-0 mt-1 text-xs leading-relaxed text-gray-500">
با یک کلیک همهٔ سفارش‌ها و شارژهای جاافتاده یکی‌یکی و با فاصله به ته‌حساب می‌روند.
بعد از سندها، مشتریان پنلِ بدون کد هم همان‌جا ثبت می‌شوند. پیشرفت را می‌توانید کوچک کنید.
اگر سندها در ته‌حساب پاک شده، اول وضعیت محلی را بازنشانی کنید.
</p>
</div>
<a-button
type="primary"
class="!w-full shrink-0 sm:!w-auto"
:loading="store.starting || store.active"
:disabled="store.active"
@click="onStart"
>
{{ store.active ? 'در حال ارسال…' : 'ارسال همه سندها' }}
</a-button>
<div class="flex w-full shrink-0 flex-col gap-2 sm:w-auto">
<a-button
type="primary"
class="!w-full sm:!w-auto"
:loading="store.starting || store.active"
:disabled="store.active || store.resetting"
@click="onStart"
>
{{ store.active ? 'در حال ارسال…' : 'ارسال همه سندها' }}
</a-button>
<a-button
class="!w-full sm:!w-auto"
:loading="store.resetting"
:disabled="store.active"
@click="onReset"
>
بازنشانی وضعیت محلی
</a-button>
</div>
</div>
</template>
<script setup lang="ts">
import { message } from 'ant-design-vue'
import { createVNode } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { useTahesabDocSyncStore } from '@/store/tahesabDocSyncStore'
const emit = defineEmits<{ refreshed: [] }>()
const store = useTahesabDocSyncStore()
async function onStart() {
@@ -34,4 +48,31 @@ async function onStart() {
message.error(e?.response?.data?.message || e?.message || 'شروع ارسال ناموفق بود')
}
}
function onReset() {
Modal.confirm({
title: 'بازنشانی وضعیت محلی؟',
icon: createVNode(ExclamationCircleOutlined),
content:
'سندهایی که پنل آن‌ها را موفق می‌داند دوباره در صف ارسال می‌آیند. خودِ ته‌حساب عوض نمی‌شود. کد مشتری پنل دست نمی‌خورد.',
okText: 'بازنشانی کن',
cancelText: 'انصراف',
centered: true,
onOk: runReset,
})
}
async function runReset() {
try {
const res = await store.resetLocal()
if (!res) return
message.success(res.message || 'وضعیت محلی به‌روز شد')
if (res.summary?.total) {
message.info(`${res.summary.total} سند در صف ارسال است — حالا ارسال همه را بزنید`)
}
emit('refreshed')
} catch (e: any) {
message.error(e?.response?.data?.message || e?.message || 'بازنشانی ناموفق بود')
}
}
</script>
@@ -16,7 +16,7 @@
</a-button>
</template>
<TahesabDocSyncBox v-if="!customerId" />
<TahesabDocSyncBox v-if="!customerId" @refreshed="onDocSyncRefreshed" />
<div
v-if="(pending?.total ?? 0) > 0"
@@ -398,6 +398,11 @@ async function loadPending() {
}
}
async function onDocSyncRefreshed() {
await loadPending()
if (docsView.value === 'failed') await loadFailedDocs()
}
async function loadFailedDocs() {
failedLoading.value = true
try {
+19
View File
@@ -6,6 +6,7 @@ import {
startTahesabCustomerInbound,
startTahesabCustomerOutbound,
stopTahesabDocSync,
resetTahesabLocalDocs,
type TahesabDocSyncState,
} from '@/api/tahesab'
@@ -38,6 +39,7 @@ export const useTahesabDocSyncStore = defineStore('tahesabDocSync', () => {
const visible = ref(false)
const minimized = ref(false)
const starting = ref(false)
const resetting = ref(false)
const message = ref('')
let timer: ReturnType<typeof setInterval> | null = null
@@ -188,11 +190,27 @@ export const useTahesabDocSyncStore = defineStore('tahesabDocSync', () => {
minimized.value = false
}
async function resetLocal() {
if (resetting.value || state.value.running) return null
resetting.value = true
try {
const res = await resetTahesabLocalDocs()
message.value = res.message || ''
apply(res.summary?.doc_sync)
visible.value = false
minimized.value = false
return res
} finally {
resetting.value = false
}
}
return {
state,
visible,
minimized,
starting,
resetting,
message,
active,
finished,
@@ -204,6 +222,7 @@ export const useTahesabDocSyncStore = defineStore('tahesabDocSync', () => {
start,
startOutbound,
startInbound,
resetLocal,
stop,
minimize,
expand,