From 3ab102ddae13112e0f20c2c6a853456a5bba0641 Mon Sep 17 00:00:00 2001 From: Mahdi Date: Sat, 5 Sep 2026 11:18:37 +0330 Subject: [PATCH] Align DoListAsnad with Hamkar (4 args) and treat empty ERROR as []. Co-authored-by: Cursor --- .../integrations/tahesab/documents.service.ts | 30 +++++++++++++------ .../tahesab/tahesab-http.client.ts | 16 ++++++++++ .../integrations/tahesab/tahesab-methods.ts | 22 +++++++------- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/apps/api/src/integrations/tahesab/documents.service.ts b/apps/api/src/integrations/tahesab/documents.service.ts index f721a34..8651f78 100644 --- a/apps/api/src/integrations/tahesab/documents.service.ts +++ b/apps/api/src/integrations/tahesab/documents.service.ts @@ -12,6 +12,16 @@ import { SanadBuilders, } from './tahesab-methods'; +function normalizeShamsiYmd(input: string): string { + const m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(input.trim()); + if (!m) { + throw new BadRequestException( + 'تاریخ از/تا باید شمسی با قالب YYYY-MM-DD باشد.', + ); + } + return `${m[1]}-${m[2]!.padStart(2, '0')}-${m[3]!.padStart(2, '0')}`; +} + function asAsnadList(raw: unknown): Array> { if (!raw) return []; if (Array.isArray(raw)) return raw as Array>; @@ -66,25 +76,27 @@ export class TahesabDocumentsService { to: string, connectionId?: string, ) { - if (!/^\d{4}-\d{1,2}-\d{1,2}$/.test(from) || !/^\d{4}-\d{1,2}-\d{1,2}$/.test(to)) { - throw new BadRequestException( - 'تاریخ از/تا باید شمسی با قالب YYYY-MM-DD باشد.', - ); - } + const fromNorm = normalizeShamsiYmd(from); + const toNorm = normalizeShamsiYmd(to); const resolvedId = await this.connections.resolveConnectionId( organizationId, connectionId, ); const link = await this.requireLink(organizationId, personId, resolvedId); const { api } = await this.connections.getApi(organizationId, resolvedId); - // Count_Last = سقف تعداد سند برگشتی (۰ در نمونه گاهی خالی برمی‌گرداند) - const raw = await api.doListAsnad(500, link.moshtariCode, from, to); + // Count_Last = -1 مثل همکار (مانده ردیف‌به‌ردیف / همه در بازه) + const raw = await api.doListAsnad( + -1, + link.moshtariCode, + fromNorm, + toNorm, + ); const items = asAsnadList(raw); return { connectionId: resolvedId, moshtariCode: link.moshtariCode, - from, - to, + from: fromNorm, + to: toNorm, items, count: items.length, }; diff --git a/apps/api/src/integrations/tahesab/tahesab-http.client.ts b/apps/api/src/integrations/tahesab/tahesab-http.client.ts index 470b58c..72976bb 100644 --- a/apps/api/src/integrations/tahesab/tahesab-http.client.ts +++ b/apps/api/src/integrations/tahesab/tahesab-http.client.ts @@ -20,6 +20,11 @@ export type TahesabCallOptions = { method?: 'GET' | 'POST'; allowInsecureTls?: boolean; timeoutMs?: number; + /** + * اگر ته‌حساب با فیلد ERROR و متن منطبق جواب داد، به‌جای ۵۰۲ + * مقدار خالی ([] ) برگردان — مثل «رکوردی یافت نشد» در DoListAsnad. + */ + emptyResultOnError?: RegExp; }; function extractTahesabError(json: unknown, text: string): string { @@ -109,6 +114,17 @@ export class TahesabHttpClient { // بعضی متدها با ۲۰۰ و فیلد ERROR برمی‌گردند if (json && typeof json === 'object' && 'ERROR' in (json as object)) { const detail = extractTahesabError(json, text); + if ( + detail && + opts.emptyResultOnError && + opts.emptyResultOnError.test(detail) + ) { + this.logger.debug( + `Tahesab ${path} empty-on-error: ${detail.slice(0, 120)}`, + ); + resolve([] as T); + return; + } reject( new BadGatewayException( detail ? `ته‌حساب: ${detail}` : `خطای ته‌حساب برای ${path}`, diff --git a/apps/api/src/integrations/tahesab/tahesab-methods.ts b/apps/api/src/integrations/tahesab/tahesab-methods.ts index 232d61b..8a89629 100644 --- a/apps/api/src/integrations/tahesab/tahesab-methods.ts +++ b/apps/api/src/integrations/tahesab/tahesab-methods.ts @@ -1,5 +1,5 @@ import { randomBytes } from 'crypto'; -import type { TahesabHttpClient } from './tahesab-http.client'; +import type { TahesabHttpClient, TahesabCallOptions } from './tahesab-http.client'; export type ConnCreds = { baseUrl: string; @@ -146,6 +146,7 @@ export class TahesabApi { args?: unknown[], method?: 'GET' | 'POST', timeoutMs?: number, + extra?: Pick, ) { return this.http.call({ ...this.creds, @@ -154,6 +155,7 @@ export class TahesabApi { args, method, timeoutMs, + ...extra, }); } @@ -222,15 +224,15 @@ export class TahesabApi { fromShamsi: string, toShamsi: string, ) { - // OpenAPI: Count_Last, Moshtari_Code, AzTarikhShamsi, TaTarikhShamsi, FilterNoSanad, Mande_Jens_Felez - return this.call('DoListAsnad', 'DoListAsnad', [ - countLast, - moshtariCode, - fromShamsi, - toShamsi, - '', - 0, - ]); + // مثل همکار: فقط ۴ پارامتر (Count_Last, Code, از, تا) — پارامتر اضافه باعث خطای ته‌حساب می‌شود + return this.call( + 'DoListAsnad', + 'DoListAsnad', + [countLast, moshtariCode, fromShamsi, toShamsi], + 'POST', + 55_000, + { emptyResultOnError: /رکوردی یافت نشد/i }, + ); } doListNameSekeh() {