Fix Tahesab empty-range 502 by using a single ByCode call.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,8 +18,9 @@ import {
|
|||||||
import { normalizeIranMobile, SanadBuilders, type TahesabApi } from './tahesab-methods';
|
import { normalizeIranMobile, SanadBuilders, type TahesabApi } from './tahesab-methods';
|
||||||
|
|
||||||
const LIST_ALL_CHUNK = 2000;
|
const LIST_ALL_CHUNK = 2000;
|
||||||
const LIST_ALL_MAX_CODE = 50_000;
|
/** سقف «همه» در یک درخواست ByCode — تکهتکه باعث ۵۰۲ پروکسی میشود */
|
||||||
const LIST_ALL_EMPTY_STREAK = 3;
|
const LIST_ALL_MAX_CODE = 5_000;
|
||||||
|
const LIST_ALL_TIMEOUT_MS = 55_000;
|
||||||
|
|
||||||
function asMoshtariList(raw: unknown): Array<Record<string, unknown>> {
|
function asMoshtariList(raw: unknown): Array<Record<string, unknown>> {
|
||||||
if (!raw) return [];
|
if (!raw) return [];
|
||||||
@@ -316,21 +317,26 @@ export class TahesabPersonLinkService {
|
|||||||
return this.linkDto(link);
|
return this.linkDto(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* لیست همهٔ مشتریان در یک درخواست (بازه ۱…LIST_ALL_MAX_CODE).
|
||||||
|
* تکهتکه کردن پشتسرهم معمولاً از مهلت nginx بیشتر میشود و ۵۰۲ میدهد.
|
||||||
|
*/
|
||||||
private async listAllMoshtari(api: TahesabApi) {
|
private async listAllMoshtari(api: TahesabApi) {
|
||||||
const merged: Array<Record<string, unknown>> = [];
|
try {
|
||||||
let emptyStreak = 0;
|
return asMoshtariList(
|
||||||
for (let from = 1; from <= LIST_ALL_MAX_CODE; from += LIST_ALL_CHUNK) {
|
await api.doListMoshtariByCode(1, LIST_ALL_MAX_CODE, {
|
||||||
const to = Math.min(from + LIST_ALL_CHUNK - 1, LIST_ALL_MAX_CODE);
|
timeoutMs: LIST_ALL_TIMEOUT_MS,
|
||||||
const rows = asMoshtariList(await api.doListMoshtariByCode(from, to));
|
}),
|
||||||
if (!rows.length) {
|
);
|
||||||
emptyStreak += 1;
|
} catch (err) {
|
||||||
if (emptyStreak >= LIST_ALL_EMPTY_STREAK) break;
|
// اگر بازهٔ بزرگ سمت تهحساب رد شد، همان سقف دستی ۲۰۰۰ را یکبار امتحان کن
|
||||||
continue;
|
if (LIST_ALL_MAX_CODE <= LIST_ALL_CHUNK) throw err;
|
||||||
}
|
return asMoshtariList(
|
||||||
emptyStreak = 0;
|
await api.doListMoshtariByCode(1, LIST_ALL_CHUNK, {
|
||||||
merged.push(...rows);
|
timeoutMs: LIST_ALL_TIMEOUT_MS,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return merged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(organizationId: string, dto: SearchTahesabDto) {
|
async search(organizationId: string, dto: SearchTahesabDto) {
|
||||||
@@ -366,7 +372,8 @@ export class TahesabPersonLinkService {
|
|||||||
moshtariCode: pickCode(row),
|
moshtariCode: pickCode(row),
|
||||||
name: pickName(row),
|
name: pickName(row),
|
||||||
tel: pickTel(row),
|
tel: pickTel(row),
|
||||||
raw: row,
|
// raw فقط برای جستجوی محدود؛ در listAll حجم پاسخ را باد میکند و پروکسی را میترکاند
|
||||||
|
...(dto.listAll ? {} : { raw: row }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const codes = mapped
|
const codes = mapped
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ export class TahesabApi {
|
|||||||
bodyKey?: string,
|
bodyKey?: string,
|
||||||
args?: unknown[],
|
args?: unknown[],
|
||||||
method?: 'GET' | 'POST',
|
method?: 'GET' | 'POST',
|
||||||
|
timeoutMs?: number,
|
||||||
) {
|
) {
|
||||||
return this.http.call<T>({
|
return this.http.call<T>({
|
||||||
...this.creds,
|
...this.creds,
|
||||||
@@ -152,6 +153,7 @@ export class TahesabApi {
|
|||||||
bodyKey,
|
bodyKey,
|
||||||
args,
|
args,
|
||||||
method,
|
method,
|
||||||
|
timeoutMs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,12 +184,18 @@ export class TahesabApi {
|
|||||||
return this.call('DoEditMoshtari', 'DoEditMoshtari', args);
|
return this.call('DoEditMoshtari', 'DoEditMoshtari', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
doListMoshtariByCode(fromCode: number, toCode: number) {
|
doListMoshtariByCode(
|
||||||
|
fromCode: number,
|
||||||
|
toCode: number,
|
||||||
|
opts?: { timeoutMs?: number },
|
||||||
|
) {
|
||||||
// OpenAPI/Postman: کلید body برای ByCode دقیقاً «Dolistmoshtari» است (حساس به حروف)
|
// OpenAPI/Postman: کلید body برای ByCode دقیقاً «Dolistmoshtari» است (حساس به حروف)
|
||||||
return this.call(
|
return this.call(
|
||||||
'DoListMoshtari-ByCode',
|
'DoListMoshtari-ByCode',
|
||||||
'Dolistmoshtari',
|
'Dolistmoshtari',
|
||||||
[fromCode, toCode],
|
[fromCode, toCode],
|
||||||
|
'POST',
|
||||||
|
opts?.timeoutMs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ async function searchTahesab(mode: 'filter' | 'range' = 'filter') {
|
|||||||
const { data } = await api.post<{ results: SyncResult[] }>(
|
const { data } = await api.post<{ results: SyncResult[] }>(
|
||||||
'/integrations/tahesab/sync/search',
|
'/integrations/tahesab/sync/search',
|
||||||
body,
|
body,
|
||||||
|
{ timeout: 60_000 },
|
||||||
);
|
);
|
||||||
syncResults.value = data.results ?? [];
|
syncResults.value = data.results ?? [];
|
||||||
if (!syncResults.value.length) {
|
if (!syncResults.value.length) {
|
||||||
@@ -502,8 +503,8 @@ onMounted(load);
|
|||||||
|
|
||||||
<h3 class="subhead">۱) وارد کردن دستهای با بازهٔ کد مشتری</h3>
|
<h3 class="subhead">۱) وارد کردن دستهای با بازهٔ کد مشتری</h3>
|
||||||
<p class="muted small">
|
<p class="muted small">
|
||||||
اگر «از» و «تا» را خالی بگذارید و نمایش بازه را بزنید، همهٔ مشتریان تهحساب لیست میشوند.
|
اگر «از» و «تا» خالی باشند، مشتریان با کد ۱ تا ۵۰۰۰ از تهحساب لیست میشوند.
|
||||||
برای محدود کردن، بازه بگذارید (حداکثر ۲۰۰۰ کد در هر درخواست محدود).
|
برای کدهای بالاتر بازه را دستی بگذارید (حداکثر ۲۰۰۰ کد در هر درخواست محدود).
|
||||||
</p>
|
</p>
|
||||||
<div class="sync-grid range">
|
<div class="sync-grid range">
|
||||||
<input v-model="sync.fromCode" type="number" min="1" dir="ltr" placeholder="از کد (خالی = همه)" />
|
<input v-model="sync.fromCode" type="number" min="1" dir="ltr" placeholder="از کد (خالی = همه)" />
|
||||||
|
|||||||
Reference in New Issue
Block a user