diff --git a/.env.example b/.env.example index b50d788..6e99349 100644 --- a/.env.example +++ b/.env.example @@ -20,4 +20,8 @@ SMS_SENDER= # SMS_OTP_TEMPLATE=کد ورود پرتال منتو: {code} # SMS_TIMEOUT_MS=20000 +# رمزنگاری توکن‌های اتصال حسابداری (ته‌حساب) — ۳۲ بایت به‌صورت hex (۶۴ کاراکتر) +# مثال ساخت: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +INTEGRATIONS_ENCRYPTION_KEY= + # Production: see deploy/.env.production.example and deploy/DEPLOY.md diff --git a/apps/api/prisma/migrations/20260904180000_tahesab_accounting/migration.sql b/apps/api/prisma/migrations/20260904180000_tahesab_accounting/migration.sql new file mode 100644 index 0000000..fe16123 --- /dev/null +++ b/apps/api/prisma/migrations/20260904180000_tahesab_accounting/migration.sql @@ -0,0 +1,156 @@ +-- CreateTable +CREATE TABLE "AccountingConnection" ( + "id" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'tahesab', + "label" TEXT NOT NULL, + "baseUrl" TEXT NOT NULL, + "dbName" TEXT NOT NULL, + "tokenCiphertext" TEXT NOT NULL, + "tokenIv" TEXT NOT NULL, + "tokenTag" TEXT NOT NULL, + "tokenLast4" TEXT NOT NULL DEFAULT '', + "enabled" BOOLEAN NOT NULL DEFAULT true, + "isDefault" BOOLEAN NOT NULL DEFAULT false, + "allowInsecureTls" BOOLEAN NOT NULL DEFAULT false, + "lastHealthAt" TIMESTAMP(3), + "lastHealthOk" BOOLEAN, + "lastError" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "AccountingConnection_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "PersonAccountingLink" ( + "id" TEXT NOT NULL, + "personId" TEXT NOT NULL, + "connectionId" TEXT NOT NULL, + "moshtariCode" INTEGER NOT NULL, + "matchMethod" TEXT NOT NULL, + "linkedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "lastBalanceSyncedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "PersonAccountingLink_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "AccountingDocumentLog" ( + "id" TEXT NOT NULL, + "connectionId" TEXT NOT NULL, + "personId" TEXT, + "docType" TEXT NOT NULL, + "factorCode" TEXT NOT NULL, + "requestPayload" JSONB NOT NULL, + "responsePayload" JSONB, + "status" TEXT NOT NULL DEFAULT 'pending', + "tahesabOk" TEXT, + "tahesabFactorId" INTEGER, + "errorMessage" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "AccountingDocumentLog_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "AccountingBalanceCache" ( + "id" TEXT NOT NULL, + "linkId" TEXT NOT NULL, + "connectionId" TEXT NOT NULL, + "goldBalance" DOUBLE PRECISION, + "rialBalance" DOUBLE PRECISION, + "currencyBalance" DOUBLE PRECISION, + "totalGoldEquiv" DOUBLE PRECISION, + "mandehDetail" JSONB NOT NULL DEFAULT '[]', + "rawResponse" JSONB, + "fetchedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "AccountingBalanceCache_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "AccountingSyncJob" ( + "id" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + "connectionId" TEXT, + "kind" TEXT NOT NULL, + "status" TEXT NOT NULL DEFAULT 'pending', + "request" JSONB NOT NULL DEFAULT '{}', + "result" JSONB, + "errorMessage" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "AccountingSyncJob_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "AccountingConnection_organizationId_enabled_idx" ON "AccountingConnection"("organizationId", "enabled"); + +-- CreateIndex +CREATE INDEX "AccountingConnection_organizationId_isDefault_idx" ON "AccountingConnection"("organizationId", "isDefault"); + +-- CreateIndex +CREATE UNIQUE INDEX "AccountingConnection_organizationId_baseUrl_dbName_key" ON "AccountingConnection"("organizationId", "baseUrl", "dbName"); + +-- CreateIndex +CREATE INDEX "PersonAccountingLink_personId_idx" ON "PersonAccountingLink"("personId"); + +-- CreateIndex +CREATE INDEX "PersonAccountingLink_connectionId_idx" ON "PersonAccountingLink"("connectionId"); + +-- CreateIndex +CREATE UNIQUE INDEX "PersonAccountingLink_personId_connectionId_key" ON "PersonAccountingLink"("personId", "connectionId"); + +-- CreateIndex +CREATE UNIQUE INDEX "PersonAccountingLink_connectionId_moshtariCode_key" ON "PersonAccountingLink"("connectionId", "moshtariCode"); + +-- CreateIndex +CREATE INDEX "AccountingDocumentLog_connectionId_status_idx" ON "AccountingDocumentLog"("connectionId", "status"); + +-- CreateIndex +CREATE INDEX "AccountingDocumentLog_personId_idx" ON "AccountingDocumentLog"("personId"); + +-- CreateIndex +CREATE INDEX "AccountingDocumentLog_docType_idx" ON "AccountingDocumentLog"("docType"); + +-- CreateIndex +CREATE UNIQUE INDEX "AccountingDocumentLog_connectionId_factorCode_key" ON "AccountingDocumentLog"("connectionId", "factorCode"); + +-- CreateIndex +CREATE UNIQUE INDEX "AccountingBalanceCache_linkId_key" ON "AccountingBalanceCache"("linkId"); + +-- CreateIndex +CREATE INDEX "AccountingBalanceCache_connectionId_idx" ON "AccountingBalanceCache"("connectionId"); + +-- CreateIndex +CREATE INDEX "AccountingSyncJob_organizationId_createdAt_idx" ON "AccountingSyncJob"("organizationId", "createdAt"); + +-- AddForeignKey +ALTER TABLE "AccountingConnection" ADD CONSTRAINT "AccountingConnection_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PersonAccountingLink" ADD CONSTRAINT "PersonAccountingLink_personId_fkey" FOREIGN KEY ("personId") REFERENCES "Person"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PersonAccountingLink" ADD CONSTRAINT "PersonAccountingLink_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "AccountingConnection"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AccountingDocumentLog" ADD CONSTRAINT "AccountingDocumentLog_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "AccountingConnection"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AccountingDocumentLog" ADD CONSTRAINT "AccountingDocumentLog_personId_fkey" FOREIGN KEY ("personId") REFERENCES "Person"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AccountingBalanceCache" ADD CONSTRAINT "AccountingBalanceCache_linkId_fkey" FOREIGN KEY ("linkId") REFERENCES "PersonAccountingLink"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AccountingBalanceCache" ADD CONSTRAINT "AccountingBalanceCache_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "AccountingConnection"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "AccountingSyncJob" ADD CONSTRAINT "AccountingSyncJob_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 39a5d90..baf5a95 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -162,9 +162,11 @@ model Organization { projectBoards ProjectBoard[] projectCards ProjectCard[] loyaltyTiers LoyaltyTier[] - automationRules AutomationRule[] - memoryItems MemoryItem[] - noteAiSuggestions NoteAiSuggestion[] + automationRules AutomationRule[] + memoryItems MemoryItem[] + noteAiSuggestions NoteAiSuggestion[] + accountingConnections AccountingConnection[] + accountingSyncJobs AccountingSyncJob[] } model User { @@ -257,9 +259,11 @@ model Person { owner User? @relation("PersonOwner", fields: [ownerId], references: [id], onDelete: SetNull) tickets Ticket[] projectCards ProjectCard[] - memoryItems MemoryItem[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + memoryItems MemoryItem[] + accountingLinks PersonAccountingLink[] + accountingDocuments AccountingDocumentLog[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@index([organizationId]) @@index([organizationId, email]) @@ -929,3 +933,122 @@ model AutomationRule { @@index([organizationId, isActive, trigger]) } + +/// اتصال به نرم‌افزار حسابداری خارجی (ته‌حساب) — چند اتصال/DB به‌ازای هر سازمان +model AccountingConnection { + id String @id @default(cuid()) + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + /// فعلاً فقط tahesab + provider String @default("tahesab") + label String + baseUrl String + dbName String + /// AES-256-GCM ciphertext (base64) + tokenCiphertext String + tokenIv String + tokenTag String + /// چهار کاراکتر آخر توکن برای نمایش ماسک‌شده + tokenLast4 String @default("") + enabled Boolean @default(true) + isDefault Boolean @default(false) + /// اگر true باشد verify SSL نادیده گرفته می‌شود (فقط برای نصب‌های داخلی با گواهی خودامضا) + allowInsecureTls Boolean @default(false) + lastHealthAt DateTime? + lastHealthOk Boolean? + lastError String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + personLinks PersonAccountingLink[] + documentLogs AccountingDocumentLog[] + balanceCaches AccountingBalanceCache[] + + @@unique([organizationId, baseUrl, dbName]) + @@index([organizationId, enabled]) + @@index([organizationId, isDefault]) +} + +model PersonAccountingLink { + id String @id @default(cuid()) + personId String + person Person @relation(fields: [personId], references: [id], onDelete: Cascade) + connectionId String + connection AccountingConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) + /// کد مشتری در ته‌حساب (Moshtari_Code) + moshtariCode Int + /// manual | mobile | name | created + matchMethod String + linkedAt DateTime @default(now()) + lastBalanceSyncedAt DateTime? + balanceCache AccountingBalanceCache? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([personId, connectionId]) + @@unique([connectionId, moshtariCode]) + @@index([personId]) + @@index([connectionId]) +} + +model AccountingDocumentLog { + id String @id @default(cuid()) + connectionId String + connection AccountingConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) + personId String? + person Person? @relation(fields: [personId], references: [id], onDelete: SetNull) + /// مثلاً DoNewSanadBuySaleGOLD + docType String + /// کد یکتای ≥۲۰ کاراکتر — idempotency + factorCode String + requestPayload Json + responsePayload Json? + /// pending | success | failed + status String @default("pending") + tahesabOk String? + tahesabFactorId Int? + errorMessage String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([connectionId, factorCode]) + @@index([connectionId, status]) + @@index([personId]) + @@index([docType]) +} + +model AccountingBalanceCache { + id String @id @default(cuid()) + linkId String @unique + link PersonAccountingLink @relation(fields: [linkId], references: [id], onDelete: Cascade) + connectionId String + connection AccountingConnection @relation(fields: [connectionId], references: [id], onDelete: Cascade) + goldBalance Float? + rialBalance Float? + currencyBalance Float? + /// مانده هم‌ارز طلا (MandeyeKolBeTALA) در صورت وجود + totalGoldEquiv Float? + /// جزئیات گروه‌بندی‌شده برای UI + mandehDetail Json @default("[]") + rawResponse Json? + fetchedAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([connectionId]) +} + +model AccountingSyncJob { + id String @id @default(cuid()) + organizationId String + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + connectionId String? + /// search | import | match + kind String + status String @default("pending") + request Json @default("{}") + result Json? + errorMessage String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([organizationId, createdAt]) +} diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 484d61d..b3388cd 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -26,6 +26,7 @@ import { LoyaltyModule } from './loyalty/loyalty.module'; import { AutomationsModule } from './automations/automations.module'; import { AiModule } from './ai/ai.module'; import { MemoryModule } from './memory/memory.module'; +import { TahesabModule } from './integrations/tahesab/tahesab.module'; @Module({ imports: [ @@ -59,6 +60,7 @@ import { MemoryModule } from './memory/memory.module'; LoyaltyModule, AutomationsModule, MemoryModule, + TahesabModule, ], }) export class AppModule {} diff --git a/apps/api/src/integrations/tahesab/__tests__/tahesab-unit.check.ts b/apps/api/src/integrations/tahesab/__tests__/tahesab-unit.check.ts new file mode 100644 index 0000000..1208ef1 --- /dev/null +++ b/apps/api/src/integrations/tahesab/__tests__/tahesab-unit.check.ts @@ -0,0 +1,128 @@ +import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'; +import { + assertFactorCode, + buildFactorCode, + FACTOR_CODE_MIN_LEN, + normalizeIranMobile, + normalizeMandehResponse, + SanadBuilders, +} from '../tahesab-methods'; + +function assert(cond: unknown, msg: string): asserts cond { + if (!cond) throw new Error(msg); +} + +function testCryptoRoundtrip() { + const key = randomBytes(32); + const plain = 'test-tahesab-token-secret-value'; + const iv = randomBytes(12); + const cipher = createCipheriv('aes-256-gcm', key, iv); + const enc = Buffer.concat([cipher.update(plain, 'utf8'), cipher.final()]); + const tag = cipher.getAuthTag(); + const decipher = createDecipheriv('aes-256-gcm', key, iv); + decipher.setAuthTag(tag); + const out = Buffer.concat([ + decipher.update(enc), + decipher.final(), + ]).toString('utf8'); + assert(out === plain, 'crypto roundtrip failed'); +} + +function testFactorCode() { + const code = buildFactorCode('crm'); + assert(code.length >= FACTOR_CODE_MIN_LEN, 'factor code too short'); + assertFactorCode(code); + let threw = false; + try { + assertFactorCode('short'); + } catch { + threw = true; + } + assert(threw, 'short factor code should throw'); +} + +function testMobile() { + assert(normalizeIranMobile('09121234567') === '9121234567', 'mobile 09'); + assert(normalizeIranMobile('989121234567') === '9121234567', 'mobile 98'); + assert(normalizeIranMobile('9121234567') === '9121234567', 'mobile bare'); +} + +function testMandehNormalize() { + const raw = { + MandeHesab: [ + { + MandeyeVazni: 12.5, + MandeyeMali: -1000, + MandeyeKolBePool: 0, + MandeyeKolBeTALA: 12.5, + details: [ + { + Name: 'طلا', + Value1: 12.5, + Value2: null, + Value3: null, + Value4: null, + }, + { + Name: 'ریال', + Value1: null, + Value2: null, + Value3: null, + Value4: -1000, + }, + ], + }, + ], + }; + const n = normalizeMandehResponse(raw); + assert(n.goldBalance === 12.5, 'gold'); + assert(n.rialBalance === -1000, 'rial'); + assert(n.mandehDetail.length === 2, 'detail count'); + assert(n.mandehDetail[1]!.values[0]!.status === 'بس', 'debtor status'); +} + +function testSanadBuilders() { + const fc = buildFactorCode('crm'); + const gold = SanadBuilders.buySaleGold({ + moshtariCode: 1, + year: 1405, + month: 1, + day: 1, + vazn: 1, + ayar: 750, + buyOrSale: 0, + mazaneh: 100, + mazanehIsGeram: 0, + isAbshode: 1, + mablaghKol: 1000, + sharh: 't', + factorCode: fc, + }); + assert(gold.length >= 20, 'gold args length'); + assert(gold[17] === fc, 'factor at index 17'); + + const bank = SanadBuilders.vkhBank({ + moshtariCode: 1, + year: 1405, + month: 1, + day: 1, + isDaryaftOrPardakht: 1, + mablagh: 5000, + sharh: 't', + nameBank: 'سامان', + codeRahgiri: '1', + factorCode: fc, + }); + assert(bank[12] === fc, 'bank factor index'); +} + +function main() { + testCryptoRoundtrip(); + testFactorCode(); + testMobile(); + testMandehNormalize(); + testSanadBuilders(); + console.log('tahesab unit checks: OK'); +} + +main(); diff --git a/apps/api/src/integrations/tahesab/balance.service.ts b/apps/api/src/integrations/tahesab/balance.service.ts new file mode 100644 index 0000000..3d2dc2f --- /dev/null +++ b/apps/api/src/integrations/tahesab/balance.service.ts @@ -0,0 +1,132 @@ +import { + BadRequestException, + Injectable, + NotFoundException, +} from '@nestjs/common'; +import { Prisma } from '@prisma/client'; +import { PrismaService } from '../../prisma/prisma.service'; +import { TahesabConnectionsService } from './connections.service'; +import { normalizeMandehResponse } from './tahesab-methods'; + +@Injectable() +export class TahesabBalanceService { + constructor( + private readonly prisma: PrismaService, + private readonly connections: TahesabConnectionsService, + ) {} + + async getAssets( + organizationId: string, + personId: string, + connectionId?: string, + ) { + const person = await this.prisma.person.findFirst({ + where: { id: personId, organizationId }, + }); + if (!person) throw new NotFoundException('شخص یافت نشد.'); + + const resolvedId = await this.connections.resolveConnectionId( + organizationId, + connectionId, + ); + + const link = await this.prisma.personAccountingLink.findFirst({ + where: { personId, connectionId: resolvedId }, + include: { + connection: { + select: { id: true, label: true, dbName: true, isDefault: true }, + }, + balanceCache: true, + }, + }); + if (!link) { + throw new BadRequestException( + 'این شخص به اتصال ته‌حساب لینک نشده است. ابتدا تطبیق یا ثبت در ته‌حساب را انجام دهید.', + ); + } + + const { api } = await this.connections.getApi(organizationId, resolvedId); + const raw = await api.getMandeHesabByCode(link.moshtariCode); + const normalized = normalizeMandehResponse(raw); + + const cache = await this.prisma.accountingBalanceCache.upsert({ + where: { linkId: link.id }, + create: { + linkId: link.id, + connectionId: resolvedId, + goldBalance: normalized.goldBalance, + rialBalance: normalized.rialBalance, + currencyBalance: normalized.currencyBalance, + totalGoldEquiv: normalized.totalGoldEquiv, + mandehDetail: normalized.mandehDetail as unknown as Prisma.InputJsonValue, + rawResponse: normalized.raw as Prisma.InputJsonValue, + fetchedAt: new Date(), + }, + update: { + goldBalance: normalized.goldBalance, + rialBalance: normalized.rialBalance, + currencyBalance: normalized.currencyBalance, + totalGoldEquiv: normalized.totalGoldEquiv, + mandehDetail: normalized.mandehDetail as unknown as Prisma.InputJsonValue, + rawResponse: normalized.raw as Prisma.InputJsonValue, + fetchedAt: new Date(), + }, + }); + + await this.prisma.personAccountingLink.update({ + where: { id: link.id }, + data: { lastBalanceSyncedAt: cache.fetchedAt }, + }); + + return { + connectionId: resolvedId, + connectionLabel: link.connection.label, + dbName: link.connection.dbName, + moshtariCode: link.moshtariCode, + goldBalance: normalized.goldBalance, + rialBalance: normalized.rialBalance, + currencyBalance: normalized.currencyBalance, + totalGoldEquiv: normalized.totalGoldEquiv, + mandehDetail: normalized.mandehDetail, + fetchedAt: cache.fetchedAt.toISOString(), + }; + } + + async getCachedOrFetch( + organizationId: string, + personId: string, + connectionId?: string, + refresh = true, + ) { + if (refresh) { + return this.getAssets(organizationId, personId, connectionId); + } + const resolvedId = await this.connections.resolveConnectionId( + organizationId, + connectionId, + ); + const link = await this.prisma.personAccountingLink.findFirst({ + where: { personId, connectionId: resolvedId }, + include: { + connection: { select: { label: true, dbName: true } }, + balanceCache: true, + }, + }); + if (!link?.balanceCache) { + return this.getAssets(organizationId, personId, connectionId); + } + const c = link.balanceCache; + return { + connectionId: resolvedId, + connectionLabel: link.connection.label, + dbName: link.connection.dbName, + moshtariCode: link.moshtariCode, + goldBalance: c.goldBalance, + rialBalance: c.rialBalance, + currencyBalance: c.currencyBalance, + totalGoldEquiv: c.totalGoldEquiv, + mandehDetail: c.mandehDetail, + fetchedAt: c.fetchedAt.toISOString(), + }; + } +} diff --git a/apps/api/src/integrations/tahesab/connections.service.ts b/apps/api/src/integrations/tahesab/connections.service.ts new file mode 100644 index 0000000..185eb42 --- /dev/null +++ b/apps/api/src/integrations/tahesab/connections.service.ts @@ -0,0 +1,282 @@ +import { + BadRequestException, + ConflictException, + Injectable, + NotFoundException, +} from '@nestjs/common'; +import { PrismaService } from '../../prisma/prisma.service'; +import { TahesabCryptoService } from './tahesab-crypto.service'; +import { TahesabHttpClient } from './tahesab-http.client'; +import { TahesabApi } from './tahesab-methods'; +import { + CreateTahesabConnectionDto, + UpdateTahesabConnectionDto, +} from './dto'; + +function normalizeBaseUrl(url: string): string { + let u = url.trim().replace(/\/+$/, ''); + if (!/^https?:\/\//i.test(u)) { + throw new BadRequestException('baseUrl باید با http:// یا https:// شروع شود.'); + } + return u; +} + +@Injectable() +export class TahesabConnectionsService { + constructor( + private readonly prisma: PrismaService, + private readonly crypto: TahesabCryptoService, + private readonly http: TahesabHttpClient, + ) {} + + private toDto(row: { + id: string; + organizationId: string; + provider: string; + label: string; + baseUrl: string; + dbName: string; + tokenLast4: string; + enabled: boolean; + isDefault: boolean; + allowInsecureTls: boolean; + lastHealthAt: Date | null; + lastHealthOk: boolean | null; + lastError: string | null; + createdAt: Date; + updatedAt: Date; + }) { + return { + id: row.id, + organizationId: row.organizationId, + provider: row.provider, + label: row.label, + baseUrl: row.baseUrl, + dbName: row.dbName, + tokenMasked: row.tokenLast4 ? `••••••${row.tokenLast4}` : '••••', + enabled: row.enabled, + isDefault: row.isDefault, + allowInsecureTls: row.allowInsecureTls, + lastHealthAt: row.lastHealthAt?.toISOString() ?? null, + lastHealthOk: row.lastHealthOk, + lastError: row.lastError, + createdAt: row.createdAt.toISOString(), + updatedAt: row.updatedAt.toISOString(), + }; + } + + async list(organizationId: string) { + const rows = await this.prisma.accountingConnection.findMany({ + where: { organizationId, provider: 'tahesab' }, + orderBy: [{ isDefault: 'desc' }, { createdAt: 'asc' }], + }); + return rows.map((r) => this.toDto(r)); + } + + async getOrThrow(organizationId: string, id: string) { + const row = await this.prisma.accountingConnection.findFirst({ + where: { id, organizationId, provider: 'tahesab' }, + }); + if (!row) throw new NotFoundException('اتصال ته‌حساب یافت نشد.'); + return row; + } + + async getApi(organizationId: string, connectionId: string) { + const row = await this.getOrThrow(organizationId, connectionId); + if (!row.enabled) { + throw new BadRequestException('این اتصال غیرفعال است.'); + } + const token = this.crypto.decrypt({ + ciphertext: row.tokenCiphertext, + iv: row.tokenIv, + tag: row.tokenTag, + }); + return { + row, + api: new TahesabApi(this.http, { + baseUrl: row.baseUrl, + token, + dbName: row.dbName, + allowInsecureTls: row.allowInsecureTls, + }), + }; + } + + async resolveConnectionId( + organizationId: string, + connectionId?: string | null, + ) { + if (connectionId) { + await this.getOrThrow(organizationId, connectionId); + return connectionId; + } + const def = await this.prisma.accountingConnection.findFirst({ + where: { organizationId, provider: 'tahesab', enabled: true, isDefault: true }, + }); + if (def) return def.id; + const any = await this.prisma.accountingConnection.findFirst({ + where: { organizationId, provider: 'tahesab', enabled: true }, + orderBy: { createdAt: 'asc' }, + }); + if (!any) { + throw new BadRequestException( + 'هیچ اتصال فعالی به ته‌حساب تعریف نشده است. از تنظیمات یک اتصال اضافه کنید.', + ); + } + return any.id; + } + + private async clearOtherDefaults(organizationId: string, exceptId?: string) { + await this.prisma.accountingConnection.updateMany({ + where: { + organizationId, + provider: 'tahesab', + ...(exceptId ? { id: { not: exceptId } } : {}), + }, + data: { isDefault: false }, + }); + } + + async create(organizationId: string, dto: CreateTahesabConnectionDto) { + const baseUrl = normalizeBaseUrl(dto.baseUrl); + const existing = await this.prisma.accountingConnection.findFirst({ + where: { organizationId, baseUrl, dbName: dto.dbName.trim() }, + }); + if (existing) { + throw new ConflictException( + 'اتصالی با همین آدرس و نام دیتابیس از قبل وجود دارد.', + ); + } + + const count = await this.prisma.accountingConnection.count({ + where: { organizationId, provider: 'tahesab' }, + }); + const makeDefault = dto.isDefault === true || count === 0; + if (makeDefault) await this.clearOtherDefaults(organizationId); + + const enc = this.crypto.encrypt(dto.token.trim()); + const row = await this.prisma.accountingConnection.create({ + data: { + organizationId, + provider: 'tahesab', + label: dto.label.trim(), + baseUrl, + dbName: dto.dbName.trim(), + tokenCiphertext: enc.ciphertext, + tokenIv: enc.iv, + tokenTag: enc.tag, + tokenLast4: this.crypto.last4(dto.token), + enabled: dto.enabled ?? true, + isDefault: makeDefault, + allowInsecureTls: dto.allowInsecureTls ?? false, + }, + }); + return this.toDto(row); + } + + async update( + organizationId: string, + id: string, + dto: UpdateTahesabConnectionDto, + ) { + const row = await this.getOrThrow(organizationId, id); + const baseUrl = dto.baseUrl ? normalizeBaseUrl(dto.baseUrl) : row.baseUrl; + const dbName = dto.dbName?.trim() ?? row.dbName; + + if (baseUrl !== row.baseUrl || dbName !== row.dbName) { + const clash = await this.prisma.accountingConnection.findFirst({ + where: { + organizationId, + baseUrl, + dbName, + id: { not: id }, + }, + }); + if (clash) { + throw new ConflictException( + 'اتصالی با همین آدرس و نام دیتابیس از قبل وجود دارد.', + ); + } + } + + if (dto.isDefault === true) await this.clearOtherDefaults(organizationId, id); + + let enc = { + ciphertext: row.tokenCiphertext, + iv: row.tokenIv, + tag: row.tokenTag, + }; + let tokenLast4 = row.tokenLast4; + if (dto.token?.trim()) { + enc = this.crypto.encrypt(dto.token.trim()); + tokenLast4 = this.crypto.last4(dto.token); + } + + const updated = await this.prisma.accountingConnection.update({ + where: { id }, + data: { + label: dto.label?.trim() ?? row.label, + baseUrl, + dbName, + tokenCiphertext: enc.ciphertext, + tokenIv: enc.iv, + tokenTag: enc.tag, + tokenLast4, + enabled: dto.enabled ?? row.enabled, + isDefault: dto.isDefault === true ? true : dto.isDefault === false ? false : row.isDefault, + allowInsecureTls: dto.allowInsecureTls ?? row.allowInsecureTls, + }, + }); + return this.toDto(updated); + } + + async remove(organizationId: string, id: string) { + const row = await this.getOrThrow(organizationId, id); + await this.prisma.accountingConnection.delete({ where: { id: row.id } }); + if (row.isDefault) { + const next = await this.prisma.accountingConnection.findFirst({ + where: { organizationId, provider: 'tahesab', enabled: true }, + orderBy: { createdAt: 'asc' }, + }); + if (next) { + await this.prisma.accountingConnection.update({ + where: { id: next.id }, + data: { isDefault: true }, + }); + } + } + return { ok: true }; + } + + async test(organizationId: string, id: string) { + const { row, api } = await this.getApi(organizationId, id); + try { + let result: unknown; + try { + result = await api.checkHealthSsl(); + } catch { + result = await api.checkHealthNoSsl(); + } + const updated = await this.prisma.accountingConnection.update({ + where: { id: row.id }, + data: { + lastHealthAt: new Date(), + lastHealthOk: true, + lastError: null, + }, + }); + return { ok: true, connection: this.toDto(updated), health: result }; + } catch (err) { + const message = (err as Error).message ?? 'خطای ناشناخته'; + const updated = await this.prisma.accountingConnection.update({ + where: { id: row.id }, + data: { + lastHealthAt: new Date(), + lastHealthOk: false, + lastError: message.slice(0, 500), + }, + }); + return { ok: false, connection: this.toDto(updated), error: message }; + } + } +} diff --git a/apps/api/src/integrations/tahesab/documents.service.ts b/apps/api/src/integrations/tahesab/documents.service.ts new file mode 100644 index 0000000..cb1be53 --- /dev/null +++ b/apps/api/src/integrations/tahesab/documents.service.ts @@ -0,0 +1,386 @@ +import { Prisma } from '@prisma/client'; +import { + BadRequestException, + Injectable, + NotFoundException, +} from '@nestjs/common'; +import { PrismaService } from '../../prisma/prisma.service'; +import { TahesabConnectionsService } from './connections.service'; +import { PushSanadDto } from './dto'; +import { + buildFactorCode, + SanadBuilders, +} from './tahesab-methods'; + +function asAsnadList(raw: unknown): Array> { + if (!raw) return []; + if (Array.isArray(raw)) return raw as Array>; + if (typeof raw === 'object') { + return Object.values(raw as Record).filter( + (v) => v && typeof v === 'object', + ) as Array>; + } + return []; +} + +@Injectable() +export class TahesabDocumentsService { + constructor( + private readonly prisma: PrismaService, + private readonly connections: TahesabConnectionsService, + ) {} + + private async requireLink( + organizationId: string, + personId: string, + connectionId: string, + ) { + const person = await this.prisma.person.findFirst({ + where: { id: personId, organizationId }, + }); + if (!person) throw new NotFoundException('شخص یافت نشد.'); + const link = await this.prisma.personAccountingLink.findFirst({ + where: { personId, connectionId }, + }); + if (!link) { + throw new BadRequestException( + 'شخص به این اتصال ته‌حساب لینک نشده است.', + ); + } + return link; + } + + async listAsnad( + organizationId: string, + personId: string, + from: string, + 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 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 = -1 برای مانده ردیف‌به‌ردیف مثل همکار + const raw = await api.doListAsnad(-1, link.moshtariCode, from, to); + const items = asAsnadList(raw); + return { + connectionId: resolvedId, + moshtariCode: link.moshtariCode, + from, + to, + items, + count: items.length, + }; + } + + async listLookups(organizationId: string, connectionId?: string) { + const resolvedId = await this.connections.resolveConnectionId( + organizationId, + connectionId, + ); + const { api } = await this.connections.getApi(organizationId, resolvedId); + const [sekeh, arz, banks] = await Promise.all([ + api.doListNameSekeh().catch(() => []), + api.doListNameArz().catch(() => []), + api.doListHesabBanki().catch(() => []), + ]); + return { connectionId: resolvedId, sekeh, arz, banks }; + } + + async pushSanad( + organizationId: string, + personId: string, + dto: PushSanadDto, + ) { + const link = await this.requireLink( + organizationId, + personId, + dto.connectionId, + ); + const factorCode = dto.factorCode?.trim() || buildFactorCode('crm'); + + const existing = await this.prisma.accountingDocumentLog.findUnique({ + where: { + connectionId_factorCode: { + connectionId: dto.connectionId, + factorCode, + }, + }, + }); + if (existing?.status === 'success') { + return { + idempotent: true, + log: this.logDto(existing), + response: existing.responsePayload, + }; + } + + const { api } = await this.connections.getApi( + organizationId, + dto.connectionId, + ); + + const code = link.moshtariCode; + const sharh = dto.sharh ?? ''; + let docTypeApi = ''; + let args: unknown[] = []; + + switch (dto.docType) { + case 'buy_sale_gold': { + if (dto.vazn == null || dto.ayar == null || dto.mazaneh == null || dto.mablaghKol == null || dto.buyOrSale == null) { + throw new BadRequestException( + 'برای خرید/فروش آبشده: vazn، ayar، mazaneh، mablaghKol، buyOrSale الزامی است.', + ); + } + docTypeApi = 'DoNewSanadBuySaleGOLD'; + args = SanadBuilders.buySaleGold({ + moshtariCode: code, + year: dto.year, + month: dto.month, + day: dto.day, + vazn: dto.vazn, + ayar: dto.ayar, + buyOrSale: dto.buyOrSale, + mazaneh: dto.mazaneh, + mazanehIsGeram: dto.mazanehIsGeram ?? 0, + isAbshode: dto.isAbshode ?? 1, + mablaghKol: dto.mablaghKol, + sharh, + factorCode, + havalehBeMcode: dto.havalehBeMcode, + jensFelez: dto.jensFelez, + }); + break; + } + case 'buy_sale_sekeh': { + if ( + dto.vazn == null || + dto.ayar == null || + dto.count == null || + !dto.nameSekeh || + dto.buyOrSale == null || + dto.mazaneh == null || + dto.mablaghKol == null + ) { + throw new BadRequestException( + 'برای خرید/فروش سکه فیلدهای وزن، عیار، تعداد، نام سکه، خرید/فروش، مظنه و مبلغ کل الزامی است.', + ); + } + docTypeApi = 'DoNewSanadBuySaleSEKEH'; + args = SanadBuilders.buySaleSekeh({ + moshtariCode: code, + year: dto.year, + month: dto.month, + day: dto.day, + vazn: dto.vazn, + ayar: dto.ayar, + count: dto.count, + nameSekeh: dto.nameSekeh, + buyOrSale: dto.buyOrSale, + mazaneh: dto.mazaneh, + mablaghKol: dto.mablaghKol, + sharh, + factorCode, + jensFelez: dto.jensFelez, + arzName: dto.arzName, + }); + break; + } + case 'talab_bedehi': { + if (dto.isBedehiOrTalab == null || dto.mablagh == null) { + throw new BadRequestException( + 'برای طلب/بدهی: isBedehiOrTalab و mablagh الزامی است.', + ); + } + docTypeApi = 'DoNewSanadTalabBedehi'; + args = SanadBuilders.talabBedehi({ + moshtariCode: code, + year: dto.year, + month: dto.month, + day: dto.day, + isBedehiOrTalab: dto.isBedehiOrTalab, + mablagh: dto.mablagh, + sharh, + baabat: dto.baabat ?? 'CRM', + vazn: dto.vazn ?? 0, + factorCode, + havalehBeMcode: dto.havalehBeMcode, + jensFelez: dto.jensFelez, + arzName: dto.arzName, + }); + break; + } + case 'vkh_gold': { + if ( + dto.vazn == null || + dto.ayar == null || + dto.isVoroodOrKhorooj == null + ) { + throw new BadRequestException( + 'برای واریز/خروج طلا: vazn، ayar، isVoroodOrKhorooj الزامی است.', + ); + } + docTypeApi = 'DoNewSanadVKHGOLD'; + args = SanadBuilders.vkhGold({ + moshtariCode: code, + year: dto.year, + month: dto.month, + day: dto.day, + vazn: dto.vazn, + ayar: dto.ayar, + angNumber: dto.angNumber ?? '0', + nameAz: dto.nameAz ?? '', + isVoroodOrKhorooj: dto.isVoroodOrKhorooj, + isAbshode: dto.isAbshode ?? 1, + sharh, + factorCode, + }); + break; + } + case 'vkh_bank': { + if ( + dto.isDaryaftOrPardakht == null || + dto.mablagh == null || + !dto.nameBank + ) { + throw new BadRequestException( + 'برای واریز/خروج بانکی: isDaryaftOrPardakht، mablagh و nameBank الزامی است.', + ); + } + docTypeApi = 'DoNewSanadVKHBank'; + args = SanadBuilders.vkhBank({ + moshtariCode: code, + year: dto.year, + month: dto.month, + day: dto.day, + isDaryaftOrPardakht: dto.isDaryaftOrPardakht, + mablagh: dto.mablagh, + sharh, + nameBank: dto.nameBank, + codeRahgiri: dto.codeRahgiri ?? '', + factorCode, + }); + break; + } + default: + throw new BadRequestException('نوع سند نامعتبر است.'); + } + + const requestPayload = { [docTypeApi]: args } as Prisma.InputJsonValue; + + const log = existing + ? await this.prisma.accountingDocumentLog.update({ + where: { id: existing.id }, + data: { + docType: docTypeApi, + requestPayload, + status: 'pending', + errorMessage: null, + personId, + }, + }) + : await this.prisma.accountingDocumentLog.create({ + data: { + connectionId: dto.connectionId, + personId, + docType: docTypeApi, + factorCode, + requestPayload, + status: 'pending', + }, + }); + + try { + let response: unknown; + switch (dto.docType) { + case 'buy_sale_gold': + response = await api.doNewSanadBuySaleGold(args); + break; + case 'buy_sale_sekeh': + response = await api.doNewSanadBuySaleSekeh(args); + break; + case 'talab_bedehi': + response = await api.doNewSanadTalabBedehi(args); + break; + case 'vkh_gold': + response = await api.doNewSanadVkhGold(args); + break; + case 'vkh_bank': + response = await api.doNewSanadVkhBank(args); + break; + } + + const resObj = (response ?? {}) as Record; + const okVal = resObj.OK ?? resObj.Factor_Code; + if (okVal === undefined || okVal === null || okVal === '') { + throw new BadRequestException( + 'ته‌حساب پاسخ موفق معتبر برنگرداند: ' + JSON.stringify(response), + ); + } + + const updated = await this.prisma.accountingDocumentLog.update({ + where: { id: log.id }, + data: { + status: 'success', + responsePayload: response as Prisma.InputJsonValue, + tahesabOk: String(okVal), + tahesabFactorId: + typeof resObj.ID === 'number' ? resObj.ID : undefined, + errorMessage: null, + }, + }); + + return { + idempotent: false, + log: this.logDto(updated), + response, + }; + } catch (err) { + const message = (err as Error).message ?? 'خطای ناشناخته'; + await this.prisma.accountingDocumentLog.update({ + where: { id: log.id }, + data: { + status: 'failed', + errorMessage: message.slice(0, 1000), + }, + }); + throw err; + } + } + + private logDto(log: { + id: string; + connectionId: string; + personId: string | null; + docType: string; + factorCode: string; + status: string; + tahesabOk: string | null; + tahesabFactorId: number | null; + errorMessage: string | null; + createdAt: Date; + updatedAt: Date; + }) { + return { + id: log.id, + connectionId: log.connectionId, + personId: log.personId, + docType: log.docType, + factorCode: log.factorCode, + status: log.status, + tahesabOk: log.tahesabOk, + tahesabFactorId: log.tahesabFactorId, + errorMessage: log.errorMessage, + createdAt: log.createdAt.toISOString(), + updatedAt: log.updatedAt.toISOString(), + }; + } +} diff --git a/apps/api/src/integrations/tahesab/dto.ts b/apps/api/src/integrations/tahesab/dto.ts new file mode 100644 index 0000000..0719a1e --- /dev/null +++ b/apps/api/src/integrations/tahesab/dto.ts @@ -0,0 +1,290 @@ +import { + IsBoolean, + IsIn, + IsInt, + IsNumber, + IsOptional, + IsString, + IsUrl, + MaxLength, + Min, + MinLength, + ValidateNested, +} from 'class-validator'; +import { Type } from 'class-transformer'; + +export class CreateTahesabConnectionDto { + @IsString() + @MinLength(1) + @MaxLength(120) + label!: string; + + @IsString() + @MinLength(8) + @MaxLength(500) + baseUrl!: string; + + @IsString() + @MinLength(1) + @MaxLength(120) + dbName!: string; + + @IsString() + @MinLength(8) + @MaxLength(2000) + token!: string; + + @IsOptional() + @IsBoolean() + enabled?: boolean; + + @IsOptional() + @IsBoolean() + isDefault?: boolean; + + @IsOptional() + @IsBoolean() + allowInsecureTls?: boolean; +} + +export class UpdateTahesabConnectionDto { + @IsOptional() + @IsString() + @MinLength(1) + @MaxLength(120) + label?: string; + + @IsOptional() + @IsString() + @MinLength(8) + @MaxLength(500) + baseUrl?: string; + + @IsOptional() + @IsString() + @MinLength(1) + @MaxLength(120) + dbName?: string; + + @IsOptional() + @IsString() + @MinLength(8) + @MaxLength(2000) + token?: string; + + @IsOptional() + @IsBoolean() + enabled?: boolean; + + @IsOptional() + @IsBoolean() + isDefault?: boolean; + + @IsOptional() + @IsBoolean() + allowInsecureTls?: boolean; +} + +export class ManualLinkDto { + @IsString() + connectionId!: string; + + @IsInt() + @Min(1) + moshtariCode!: number; +} + +export class MatchPersonDto { + @IsString() + connectionId!: string; + + /** اگر true باشد و دقیقاً یک نتیجه باشد، لینک می‌شود */ + @IsOptional() + @IsBoolean() + autoLinkIfUnique?: boolean; +} + +export class CreateInTahesabDto { + @IsString() + connectionId!: string; + + @IsOptional() + @IsString() + groupName?: string; + + @IsOptional() + @IsInt() + jensFelez?: number; +} + +export class ImportFromTahesabDto { + @IsString() + connectionId!: string; + + @IsInt() + @Min(1) + moshtariCode!: number; + + /** اگر داده شود به این شخص لینک می‌شود؛ وگرنه شخص جدید ساخته می‌شود */ + @IsOptional() + @IsString() + personId?: string; +} + +export class SearchTahesabDto { + @IsString() + connectionId!: string; + + @IsOptional() + @IsString() + phone?: string; + + @IsOptional() + @IsString() + name?: string; + + @IsOptional() + @IsInt() + moshtariCode?: number; +} + +export class ListAsnadQueryDto { + @IsOptional() + @IsString() + connectionId?: string; + + /** تاریخ شمسی YYYY-MM-DD */ + @IsString() + from!: string; + + @IsString() + to!: string; +} + +const SANAD_TYPES = [ + 'buy_sale_gold', + 'buy_sale_sekeh', + 'talab_bedehi', + 'vkh_gold', + 'vkh_bank', +] as const; + +export class PushSanadDto { + @IsString() + connectionId!: string; + + @IsIn(SANAD_TYPES) + docType!: (typeof SANAD_TYPES)[number]; + + @IsInt() + year!: number; + + @IsInt() + @Min(1) + month!: number; + + @IsInt() + @Min(1) + day!: number; + + @IsOptional() + @IsString() + @MaxLength(500) + sharh?: string; + + // gold / sekeh / vkh gold + @IsOptional() + @IsNumber() + vazn?: number; + + @IsOptional() + @IsNumber() + ayar?: number; + + @IsOptional() + @IsIn([0, 1]) + buyOrSale?: 0 | 1; + + @IsOptional() + @IsNumber() + mazaneh?: number; + + @IsOptional() + @IsIn([0, 1]) + mazanehIsGeram?: 0 | 1; + + @IsOptional() + @IsIn([0, 1]) + isAbshode?: 0 | 1; + + @IsOptional() + @IsNumber() + mablaghKol?: number; + + @IsOptional() + @IsNumber() + count?: number; + + @IsOptional() + @IsString() + nameSekeh?: string; + + @IsOptional() + @IsIn([0, 1]) + isBedehiOrTalab?: 0 | 1; + + @IsOptional() + @IsNumber() + mablagh?: number; + + @IsOptional() + @IsString() + baabat?: string; + + @IsOptional() + @IsInt() + havalehBeMcode?: number; + + @IsOptional() + @IsString() + angNumber?: string; + + @IsOptional() + @IsString() + nameAz?: string; + + @IsOptional() + @IsIn([0, 1]) + isVoroodOrKhorooj?: 0 | 1; + + @IsOptional() + @IsIn([0, 1]) + isDaryaftOrPardakht?: 0 | 1; + + @IsOptional() + @IsString() + nameBank?: string; + + @IsOptional() + @IsString() + codeRahgiri?: string; + + @IsOptional() + @IsInt() + jensFelez?: number; + + @IsOptional() + @IsString() + arzName?: string; + + /** اگر ارسال شود و قبلاً success بوده، همان پاسخ برمی‌گردد (retry امن) */ + @IsOptional() + @IsString() + @MinLength(20) + factorCode?: string; +} + +// silence unused import warnings for ValidateNested/Type if unused +void ValidateNested; +void Type; +void IsUrl; diff --git a/apps/api/src/integrations/tahesab/person-link.service.ts b/apps/api/src/integrations/tahesab/person-link.service.ts new file mode 100644 index 0000000..66c7460 --- /dev/null +++ b/apps/api/src/integrations/tahesab/person-link.service.ts @@ -0,0 +1,438 @@ +import { + BadRequestException, + ConflictException, + Injectable, + NotFoundException, +} from '@nestjs/common'; +import { Prisma } from '@prisma/client'; +import { PrismaService } from '../../prisma/prisma.service'; +import { TahesabConnectionsService } from './connections.service'; +import { + CreateInTahesabDto, + ImportFromTahesabDto, + ManualLinkDto, + MatchPersonDto, + SearchTahesabDto, +} from './dto'; +import { normalizeIranMobile, SanadBuilders } from './tahesab-methods'; + +function asMoshtariList(raw: unknown): Array> { + if (!raw) return []; + if (Array.isArray(raw)) return raw as Array>; + if (typeof raw === 'object') { + const obj = raw as Record; + // پاسخ گاهی دیکشنری با کلید عددی است + const vals = Object.values(obj); + if (vals.every((v) => v && typeof v === 'object')) { + return vals as Array>; + } + } + return []; +} + +function pickCode(row: Record): number | null { + const c = + row.Moshtari_Code ?? + row.Code ?? + row.MCode ?? + row.code ?? + row.moshtari_code; + const n = Number(c); + return Number.isFinite(n) ? n : null; +} + +function pickName(row: Record): string { + return String( + row.Moshtari_Name ?? row.Name ?? row.name ?? row.FullName ?? '', + ); +} + +function pickTel(row: Record): string { + return String(row.Tel ?? row.Phone ?? row.Mobile ?? row.tel ?? ''); +} + +@Injectable() +export class TahesabPersonLinkService { + constructor( + private readonly prisma: PrismaService, + private readonly connections: TahesabConnectionsService, + ) {} + + private async getPerson(organizationId: string, personId: string) { + const person = await this.prisma.person.findFirst({ + where: { id: personId, organizationId }, + }); + if (!person) throw new NotFoundException('شخص یافت نشد.'); + return person; + } + + private linkDto(link: { + id: string; + personId: string; + connectionId: string; + moshtariCode: number; + matchMethod: string; + linkedAt: Date; + lastBalanceSyncedAt: Date | null; + connection?: { label: string; dbName: string; isDefault: boolean }; + }) { + return { + id: link.id, + personId: link.personId, + connectionId: link.connectionId, + moshtariCode: link.moshtariCode, + matchMethod: link.matchMethod, + linkedAt: link.linkedAt.toISOString(), + lastBalanceSyncedAt: link.lastBalanceSyncedAt?.toISOString() ?? null, + connectionLabel: link.connection?.label, + dbName: link.connection?.dbName, + isDefaultConnection: link.connection?.isDefault, + }; + } + + async listLinks(organizationId: string, personId: string) { + await this.getPerson(organizationId, personId); + const links = await this.prisma.personAccountingLink.findMany({ + where: { + personId, + connection: { organizationId, provider: 'tahesab' }, + }, + include: { + connection: { select: { label: true, dbName: true, isDefault: true } }, + }, + orderBy: { linkedAt: 'desc' }, + }); + return links.map((l) => this.linkDto(l)); + } + + async manualLink( + organizationId: string, + personId: string, + dto: ManualLinkDto, + ) { + await this.getPerson(organizationId, personId); + await this.connections.getOrThrow(organizationId, dto.connectionId); + + const clash = await this.prisma.personAccountingLink.findFirst({ + where: { + connectionId: dto.connectionId, + moshtariCode: dto.moshtariCode, + personId: { not: personId }, + }, + }); + if (clash) { + throw new ConflictException( + 'این کد مشتری ته‌حساب قبلاً به شخص دیگری لینک شده است.', + ); + } + + const link = await this.prisma.personAccountingLink.upsert({ + where: { + personId_connectionId: { + personId, + connectionId: dto.connectionId, + }, + }, + create: { + personId, + connectionId: dto.connectionId, + moshtariCode: dto.moshtariCode, + matchMethod: 'manual', + }, + update: { + moshtariCode: dto.moshtariCode, + matchMethod: 'manual', + linkedAt: new Date(), + }, + include: { + connection: { select: { label: true, dbName: true, isDefault: true } }, + }, + }); + return this.linkDto(link); + } + + async unlink( + organizationId: string, + personId: string, + connectionId: string, + ) { + await this.getPerson(organizationId, personId); + const link = await this.prisma.personAccountingLink.findFirst({ + where: { + personId, + connectionId, + connection: { organizationId }, + }, + }); + if (!link) throw new NotFoundException('لینک یافت نشد.'); + await this.prisma.personAccountingLink.delete({ where: { id: link.id } }); + return { ok: true }; + } + + async match( + organizationId: string, + personId: string, + dto: MatchPersonDto, + ) { + const person = await this.getPerson(organizationId, personId); + const { api } = await this.connections.getApi( + organizationId, + dto.connectionId, + ); + + const candidates: Array<{ + moshtariCode: number; + name: string; + tel: string; + matchBy: 'mobile' | 'name'; + raw: Record; + }> = []; + + const mobile = normalizeIranMobile(person.mobile ?? person.phone); + if (mobile) { + const raw = await api.doListMoshtariByPhone(mobile); + for (const row of asMoshtariList(raw)) { + const code = pickCode(row); + if (code == null) continue; + candidates.push({ + moshtariCode: code, + name: pickName(row), + tel: pickTel(row), + matchBy: 'mobile', + raw: row, + }); + } + } + + if (candidates.length === 0) { + const name = `${person.firstName} ${person.lastName}`.trim(); + if (name) { + const raw = await api.doListMoshtariByName(name); + for (const row of asMoshtariList(raw)) { + const code = pickCode(row); + if (code == null) continue; + candidates.push({ + moshtariCode: code, + name: pickName(row), + tel: pickTel(row), + matchBy: 'name', + raw: row, + }); + } + } + } + + // unique by code + const uniq = new Map(); + for (const c of candidates) uniq.set(c.moshtariCode, c); + const list = [...uniq.values()]; + + if (dto.autoLinkIfUnique && list.length === 1) { + const only = list[0]!; + const link = await this.manualLink(organizationId, personId, { + connectionId: dto.connectionId, + moshtariCode: only.moshtariCode, + }); + // override match method + const updated = await this.prisma.personAccountingLink.update({ + where: { id: link.id }, + data: { matchMethod: only.matchBy }, + include: { + connection: { + select: { label: true, dbName: true, isDefault: true }, + }, + }, + }); + return { + status: 'linked' as const, + candidates: list, + link: this.linkDto(updated), + }; + } + + if (list.length === 0) { + return { status: 'none' as const, candidates: list, link: null }; + } + if (list.length === 1) { + return { status: 'unique' as const, candidates: list, link: null }; + } + return { status: 'ambiguous' as const, candidates: list, link: null }; + } + + async createInTahesab( + organizationId: string, + personId: string, + dto: CreateInTahesabDto, + ) { + const person = await this.getPerson(organizationId, personId); + const existing = await this.prisma.personAccountingLink.findFirst({ + where: { personId, connectionId: dto.connectionId }, + }); + if (existing) { + throw new ConflictException( + 'این شخص از قبل به این اتصال لینک شده است.', + ); + } + + const { api } = await this.connections.getApi( + organizationId, + dto.connectionId, + ); + const tel = + normalizeIranMobile(person.mobile ?? person.phone) ?? + person.mobile ?? + person.phone ?? + ''; + const args = SanadBuilders.newMoshtari({ + name: `${person.firstName} ${person.lastName}`.trim(), + groupName: dto.groupName ?? 'CRM', + tel, + jensFelez: dto.jensFelez ?? 0, + }); + const res = await api.doNewMoshtari(args); + const code = Number(res?.OK); + if (!Number.isFinite(code) || code <= 0) { + throw new BadRequestException( + 'ته‌حساب کد مشتری معتبر برنگرداند. پاسخ: ' + JSON.stringify(res), + ); + } + + const link = await this.prisma.personAccountingLink.create({ + data: { + personId, + connectionId: dto.connectionId, + moshtariCode: code, + matchMethod: 'created', + }, + include: { + connection: { select: { label: true, dbName: true, isDefault: true } }, + }, + }); + return this.linkDto(link); + } + + async search(organizationId: string, dto: SearchTahesabDto) { + const { api } = await this.connections.getApi( + organizationId, + dto.connectionId, + ); + let raw: unknown = []; + if (dto.moshtariCode) { + raw = await api.doListMoshtariByCode(dto.moshtariCode, dto.moshtariCode); + } else if (dto.phone) { + const m = normalizeIranMobile(dto.phone) ?? dto.phone; + raw = await api.doListMoshtariByPhone(m); + } else if (dto.name?.trim()) { + raw = await api.doListMoshtariByName(dto.name.trim()); + } else { + throw new BadRequestException('یکی از phone، name یا moshtariCode لازم است.'); + } + + const results = asMoshtariList(raw).map((row) => ({ + moshtariCode: pickCode(row), + name: pickName(row), + tel: pickTel(row), + raw: row, + })); + + await this.prisma.accountingSyncJob.create({ + data: { + organizationId, + connectionId: dto.connectionId, + kind: 'search', + status: 'success', + request: dto as unknown as Prisma.InputJsonValue, + result: { count: results.length } as Prisma.InputJsonValue, + }, + }); + + return { results }; + } + + async importFromTahesab( + organizationId: string, + dto: ImportFromTahesabDto, + ) { + const clash = await this.prisma.personAccountingLink.findFirst({ + where: { + connectionId: dto.connectionId, + moshtariCode: dto.moshtariCode, + }, + include: { person: true }, + }); + if (clash && (!dto.personId || clash.personId !== dto.personId)) { + throw new ConflictException( + `این کد ته‌حساب قبلاً به «${clash.person.firstName} ${clash.person.lastName}» لینک شده است.`, + ); + } + + const { api } = await this.connections.getApi( + organizationId, + dto.connectionId, + ); + const raw = await api.doListMoshtariByCode( + dto.moshtariCode, + dto.moshtariCode, + ); + const rows = asMoshtariList(raw); + const row = rows[0] ?? {}; + const name = pickName(row) || `مشتری ته‌حساب ${dto.moshtariCode}`; + const tel = pickTel(row); + const parts = name.trim().split(/\s+/); + const firstName = parts[0] || name; + const lastName = parts.slice(1).join(' ') || '—'; + + let personId = dto.personId; + if (personId) { + await this.getPerson(organizationId, personId); + } else { + const created = await this.prisma.person.create({ + data: { + organizationId, + firstName, + lastName, + mobile: tel || null, + phone: tel || null, + notes: `واردشده از ته‌حساب (کد ${dto.moshtariCode})`, + }, + }); + personId = created.id; + } + + const link = await this.prisma.personAccountingLink.upsert({ + where: { + personId_connectionId: { + personId, + connectionId: dto.connectionId, + }, + }, + create: { + personId, + connectionId: dto.connectionId, + moshtariCode: dto.moshtariCode, + matchMethod: 'manual', + }, + update: { + moshtariCode: dto.moshtariCode, + matchMethod: 'manual', + linkedAt: new Date(), + }, + include: { + connection: { select: { label: true, dbName: true, isDefault: true } }, + }, + }); + + await this.prisma.accountingSyncJob.create({ + data: { + organizationId, + connectionId: dto.connectionId, + kind: 'import', + status: 'success', + request: dto as unknown as Prisma.InputJsonValue, + result: { personId, linkId: link.id } as Prisma.InputJsonValue, + }, + }); + + return { personId, link: this.linkDto(link) }; + } +} diff --git a/apps/api/src/integrations/tahesab/tahesab-crypto.service.ts b/apps/api/src/integrations/tahesab/tahesab-crypto.service.ts new file mode 100644 index 0000000..981a731 --- /dev/null +++ b/apps/api/src/integrations/tahesab/tahesab-crypto.service.ts @@ -0,0 +1,68 @@ +import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'; +import { Injectable, ServiceUnavailableException } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +export type EncryptedSecret = { + ciphertext: string; + iv: string; + tag: string; +}; + +@Injectable() +export class TahesabCryptoService { + constructor(private readonly config: ConfigService) {} + + private getKey(): Buffer { + const raw = this.config.get('INTEGRATIONS_ENCRYPTION_KEY')?.trim(); + if (!raw) { + throw new ServiceUnavailableException( + 'INTEGRATIONS_ENCRYPTION_KEY تنظیم نشده است. بدون این کلید ذخیره توکن ته‌حساب ممکن نیست.', + ); + } + if (/^[0-9a-fA-F]{64}$/.test(raw)) { + return Buffer.from(raw, 'hex'); + } + const b64 = Buffer.from(raw, 'base64'); + if (b64.length === 32) return b64; + throw new ServiceUnavailableException( + 'INTEGRATIONS_ENCRYPTION_KEY باید ۳۲ بایت باشد (۶۴ کاراکتر hex یا base64 معادل).', + ); + } + + encrypt(plain: string): EncryptedSecret { + const iv = randomBytes(12); + const cipher = createCipheriv('aes-256-gcm', this.getKey(), iv); + const enc = Buffer.concat([cipher.update(plain, 'utf8'), cipher.final()]); + const tag = cipher.getAuthTag(); + return { + ciphertext: enc.toString('base64'), + iv: iv.toString('base64'), + tag: tag.toString('base64'), + }; + } + + decrypt(secret: EncryptedSecret): string { + const decipher = createDecipheriv( + 'aes-256-gcm', + this.getKey(), + Buffer.from(secret.iv, 'base64'), + ); + decipher.setAuthTag(Buffer.from(secret.tag, 'base64')); + const dec = Buffer.concat([ + decipher.update(Buffer.from(secret.ciphertext, 'base64')), + decipher.final(), + ]); + return dec.toString('utf8'); + } + + maskToken(token: string): string { + const t = token.trim(); + if (t.length <= 4) return '••••'; + return `••••••${t.slice(-4)}`; + } + + last4(token: string): string { + const t = token.trim(); + return t.length <= 4 ? t : t.slice(-4); + } +} diff --git a/apps/api/src/integrations/tahesab/tahesab-http.client.ts b/apps/api/src/integrations/tahesab/tahesab-http.client.ts new file mode 100644 index 0000000..b0887f4 --- /dev/null +++ b/apps/api/src/integrations/tahesab/tahesab-http.client.ts @@ -0,0 +1,122 @@ +import * as http from 'http'; +import * as https from 'https'; +import { URL } from 'url'; +import { + BadGatewayException, + Injectable, + Logger, + RequestTimeoutException, +} from '@nestjs/common'; + +export type TahesabCallOptions = { + baseUrl: string; + token: string; + dbName: string; + /** مسیر OpenAPI مثل DoNewMoshtari یا CheckHealth-SSL */ + path: string; + /** کلید body؛ اگر خالی باشد فقط GET بدون body */ + bodyKey?: string; + args?: unknown[]; + method?: 'GET' | 'POST'; + allowInsecureTls?: boolean; + timeoutMs?: number; +}; + +@Injectable() +export class TahesabHttpClient { + private readonly logger = new Logger(TahesabHttpClient.name); + + async call(opts: TahesabCallOptions): Promise { + const base = opts.baseUrl.replace(/\/+$/, ''); + const path = opts.path.replace(/^\/+/, ''); + const url = new URL(`${base}/${path}`); + const method = opts.method ?? (opts.bodyKey ? 'POST' : 'GET'); + const timeoutMs = opts.timeoutMs ?? 30_000; + + const headers: Record = { + Authorization: `Bearer ${opts.token}`, + DBname: opts.dbName, + DBName: opts.dbName, + Accept: 'application/json', + Host: url.host, + }; + + let body: string | undefined; + if (method === 'POST' && opts.bodyKey) { + headers['Content-Type'] = 'application/json'; + body = JSON.stringify({ [opts.bodyKey]: opts.args ?? [] }); + headers['Content-Length'] = Buffer.byteLength(body).toString(); + } + + const isHttps = url.protocol === 'https:'; + const lib = isHttps ? https : http; + const agent = + isHttps && opts.allowInsecureTls + ? new https.Agent({ rejectUnauthorized: false }) + : undefined; + + return new Promise((resolve, reject) => { + const req = lib.request( + { + protocol: url.protocol, + hostname: url.hostname, + port: url.port || (isHttps ? 443 : 80), + path: `${url.pathname}${url.search}`, + method, + headers, + timeout: timeoutMs, + agent, + }, + (res) => { + const chunks: Buffer[] = []; + res.on('data', (c) => chunks.push(c)); + res.on('end', () => { + const text = Buffer.concat(chunks).toString('utf8'); + let json: unknown = null; + if (text) { + try { + json = JSON.parse(text); + } catch { + json = { raw: text }; + } + } + const status = res.statusCode ?? 0; + if (status < 200 || status >= 300) { + this.logger.warn( + `Tahesab ${method} ${path} → ${status}: ${text.slice(0, 400)}`, + ); + reject( + new BadGatewayException( + `پاسخ نامعتبر ته‌حساب (${status}) برای ${path}`, + ), + ); + return; + } + resolve(json as T); + }); + }, + ); + + req.on('timeout', () => { + req.destroy(); + reject( + new RequestTimeoutException( + `مهلت اتصال به ته‌حساب برای ${path} به پایان رسید.`, + ), + ); + }); + + req.on('error', (err) => { + this.logger.error(`Tahesab call failed: ${path}`, err); + reject( + new BadGatewayException( + `اتصال به ته‌حساب ناموفق بود: ${err.message}`, + ), + ); + }); + + if (body) req.write(body); + req.end(); + }); + } +} diff --git a/apps/api/src/integrations/tahesab/tahesab-methods.ts b/apps/api/src/integrations/tahesab/tahesab-methods.ts new file mode 100644 index 0000000..22702ad --- /dev/null +++ b/apps/api/src/integrations/tahesab/tahesab-methods.ts @@ -0,0 +1,480 @@ +import { randomBytes } from 'crypto'; +import type { TahesabHttpClient } from './tahesab-http.client'; + +export type ConnCreds = { + baseUrl: string; + token: string; + dbName: string; + allowInsecureTls?: boolean; +}; + +/** حداقل طول Factor_Code طبق مستندات ته‌حساب */ +export const FACTOR_CODE_MIN_LEN = 20; + +export function buildFactorCode(prefix = 'crm'): string { + const stamp = Date.now().toString(36); + const rand = randomBytes(12).toString('hex'); + const code = `${prefix}${stamp}${rand}`; + return code.length >= FACTOR_CODE_MIN_LEN + ? code + : code.padEnd(FACTOR_CODE_MIN_LEN, '0'); +} + +export function assertFactorCode(code: string): void { + if (!code || code.trim().length < FACTOR_CODE_MIN_LEN) { + throw new Error( + `Factor_Code باید حداقل ${FACTOR_CODE_MIN_LEN} کاراکتر باشد.`, + ); + } +} + +/** نرمال‌سازی موبایل ایران برای جستجو در ته‌حساب */ +export function normalizeIranMobile(input: string | null | undefined): string | null { + if (!input) return null; + let d = input.replace(/[^\d]/g, ''); + if (d.startsWith('98') && d.length >= 12) d = d.slice(2); + if (d.startsWith('0') && d.length >= 11) d = d.slice(1); + if (d.length < 10) return null; + return d; +} + +export type MandehValue = { + amount: string | number; + unit: string; + status: 'بس' | 'بد'; +}; + +export type MandehDetailItem = { + Name: string; + values: MandehValue[]; +}; + +export type NormalizedAssets = { + goldBalance: number | null; + rialBalance: number | null; + currencyBalance: number | null; + totalGoldEquiv: number | null; + mandehDetail: MandehDetailItem[]; + raw: unknown; +}; + +function num(v: unknown): number | null { + if (v === null || v === undefined || v === '') return null; + const n = Number(v); + return Number.isFinite(n) ? n : null; +} + +function detailStatus(amount: number): 'بس' | 'بد' { + return amount < 0 ? 'بس' : 'بد'; +} + +/** نرمال‌سازی پاسخ getmandehesabbycode مثل همکار */ +export function normalizeMandehResponse(raw: unknown): NormalizedAssets { + const root = raw as { + MandeHesab?: Array>; + }; + const row = root?.MandeHesab?.[0]; + if (!row) { + return { + goldBalance: null, + rialBalance: null, + currencyBalance: null, + totalGoldEquiv: null, + mandehDetail: [], + raw, + }; + } + + const details = Array.isArray(row.details) ? row.details : []; + const mandehDetail: MandehDetailItem[] = details.map((item) => { + const it = item as Record; + const values: MandehValue[] = []; + if (it.Value1 !== null && it.Value1 !== undefined) { + const a = Number(it.Value1); + values.push({ + amount: it.Value1 as string | number, + unit: 'گرم', + status: detailStatus(a), + }); + } + if (it.Value2 !== null && it.Value2 !== undefined) { + const a = Number(it.Value2); + values.push({ + amount: it.Value2 as string | number, + unit: 'عدد', + status: detailStatus(a), + }); + } + if (it.Value3 !== null && it.Value3 !== undefined) { + const a = Number(it.Value3); + values.push({ + amount: it.Value3 as string | number, + unit: 'ارز', + status: detailStatus(a), + }); + } + if (it.Value4 !== null && it.Value4 !== undefined) { + const a = Number(it.Value4); + values.push({ + amount: it.Value4 as string | number, + unit: 'ریال', + status: detailStatus(a), + }); + } + return { Name: String(it.Name ?? ''), values }; + }); + + return { + goldBalance: num(row.MandeyeVazni), + rialBalance: num(row.MandeyeMali), + currencyBalance: num(row.MandeyeKolBePool), + totalGoldEquiv: num(row.MandeyeKolBeTALA), + mandehDetail, + raw, + }; +} + +export class TahesabApi { + constructor( + private readonly http: TahesabHttpClient, + private readonly creds: ConnCreds, + ) {} + + private call( + path: string, + bodyKey?: string, + args?: unknown[], + method?: 'GET' | 'POST', + ) { + return this.http.call({ + ...this.creds, + path, + bodyKey, + args, + method, + }); + } + + checkHealthSsl() { + return this.call<{ Status?: string; Api_Status?: string }>( + 'CheckHealth-SSL', + undefined, + undefined, + 'GET', + ); + } + + checkHealthNoSsl() { + return this.call<{ Status?: string; Api_Status?: string }>( + 'CheckHealth-No-SSL', + undefined, + undefined, + 'GET', + ); + } + + /** ثبت مشتری — پاسخ { OK: moshtariCode } */ + doNewMoshtari(args: unknown[]) { + return this.call<{ OK?: number }>('DoNewMoshtari', 'DoNewMoshtari', args); + } + + doEditMoshtari(args: unknown[]) { + return this.call('DoEditMoshtari', 'DoEditMoshtari', args); + } + + doListMoshtariByCode(fromCode: number, toCode: number) { + return this.call( + 'DoListMoshtari-ByCode', + 'DoListMoshtari', + [fromCode, toCode], + ); + } + + doListMoshtariByPhone(phone: string | number) { + return this.call('DoListMoshtari-ByPhone', 'DoListMoshtari', [phone]); + } + + doListMoshtariByName(name: string) { + return this.call('DoListMoshtari-ByName', 'DoListMoshtari', [name]); + } + + /** body key حساس به حروف کوچک مثل همکار */ + getMandeHesabByCode(moshtariCode: number | string) { + return this.call( + 'GetMandeHesabByCode', + 'getmandehesabbycode', + [String(moshtariCode)], + ); + } + + doListAsnad( + countLast: number, + moshtariCode: number, + fromShamsi: string, + toShamsi: string, + ) { + return this.call('DoListAsnad', 'DoListAsnad', [ + countLast, + moshtariCode, + fromShamsi, + toShamsi, + ]); + } + + doListNameSekeh() { + return this.call('DoListNameSekeh', 'DoListNameSekeh', []); + } + + doListNameArz() { + return this.call('DoListNameARZ', 'DoListNameARZ', []); + } + + doListHesabBanki() { + return this.call('DoListHesabBanki', 'DoListHesabBanki', []); + } + + doNewSanadBuySaleGold(args: unknown[]) { + return this.call('DoNewSanadBuySaleGOLD', 'DoNewSanadBuySaleGOLD', args); + } + + doNewSanadBuySaleSekeh(args: unknown[]) { + return this.call('DoNewSanadBuySaleSEKEH', 'DoNewSanadBuySaleSEKEH', args); + } + + doNewSanadTalabBedehi(args: unknown[]) { + return this.call('DoNewSanadTalabBedehi', 'DoNewSanadTalabBedehi', args); + } + + doNewSanadVkhGold(args: unknown[]) { + return this.call('DoNewSanadVKHGOLD', 'DoNewSanadVKHGOLD', args); + } + + doNewSanadVkhBank(args: unknown[]) { + return this.call('DoNewSanadVKHBank', 'DoNewSanadVKHBank', args); + } +} + +/** سازنده‌های آرایه سند — ترتیب پارامترها قفل‌شده با OpenAPI/همکار */ +export const SanadBuilders = { + buySaleGold(p: { + moshtariCode: number; + year: number; + month: number; + day: number; + vazn: number; + ayar: number; + buyOrSale: 0 | 1; + mazaneh: number; + mazanehIsGeram: 0 | 1; + isAbshode: 0 | 1; + mablaghKol: number; + sharh: string; + factorCode: string; + havalehBeMcode?: number; + jensFelez?: number; + zamanTasvie?: string; + }): unknown[] { + assertFactorCode(p.factorCode); + return [ + 1, + p.moshtariCode, + -1, + 1, + p.year, + p.month, + p.day, + p.vazn, + p.ayar, + 123456, + 'Reygiri', + p.buyOrSale, + p.mazaneh, + p.mazanehIsGeram, + p.isAbshode, + p.mablaghKol, + p.sharh, + p.factorCode, + p.havalehBeMcode ?? -1, + -1, + p.jensFelez ?? 0, + p.zamanTasvie ?? '', + ]; + }, + + buySaleSekeh(p: { + moshtariCode: number; + year: number; + month: number; + day: number; + vazn: number; + ayar: number; + count: number; + nameSekeh: string; + buyOrSale: 0 | 1; + mazaneh: number; + mablaghKol: number; + sharh: string; + factorCode: string; + jensFelez?: number; + arzName?: string; + }): unknown[] { + assertFactorCode(p.factorCode); + return [ + 1, + p.moshtariCode, + -1, + 1, + p.year, + p.month, + p.day, + p.vazn, + p.ayar, + p.count, + p.nameSekeh, + p.buyOrSale, + p.mazaneh, + p.mablaghKol, + p.sharh, + p.factorCode, + -1, + -1, + p.jensFelez ?? 0, + p.arzName ?? 'IRR', + ]; + }, + + /** قرارداد همکار HavalehTahesabService */ + talabBedehi(p: { + moshtariCode: number; + year: number; + month: number; + day: number; + isBedehiOrTalab: 0 | 1; + mablagh: number; + sharh: string; + baabat: string; + vazn: number; + factorCode: string; + havalehBeMcode?: number; + jensFelez?: number; + arzName?: string; + }): unknown[] { + assertFactorCode(p.factorCode); + return [ + 1, + p.moshtariCode, + -1, + 0, + p.year, + p.month, + p.day, + p.isBedehiOrTalab, + p.mablagh, + p.sharh, + p.baabat, + p.vazn, + p.factorCode, + p.havalehBeMcode ?? -1, + 0, + p.jensFelez ?? 0, + p.arzName ?? 'ریال', + ]; + }, + + vkhGold(p: { + moshtariCode: number; + year: number; + month: number; + day: number; + vazn: number; + ayar: number; + angNumber: string | number; + nameAz: string; + isVoroodOrKhorooj: 0 | 1; + isAbshode: 0 | 1; + sharh: string; + factorCode: string; + isSharti?: boolean; + }): unknown[] { + assertFactorCode(p.factorCode); + return [ + 1, + p.moshtariCode, + -1, + 1, + p.year, + p.month, + p.day, + p.vazn, + p.ayar, + p.angNumber, + p.nameAz, + p.isVoroodOrKhorooj, + p.isAbshode, + p.sharh, + p.factorCode, + -1, + -1, + 0, + p.isSharti ?? false, + ]; + }, + + vkhBank(p: { + moshtariCode: number; + year: number; + month: number; + day: number; + isDaryaftOrPardakht: 0 | 1; + mablagh: number; + sharh: string; + nameBank: string; + codeRahgiri: string; + factorCode: string; + }): unknown[] { + assertFactorCode(p.factorCode); + return [ + 1, + p.moshtariCode, + -1, + 1, + p.year, + p.month, + p.day, + p.isDaryaftOrPardakht, + p.mablagh, + p.sharh, + p.nameBank, + p.codeRahgiri, + p.factorCode, + -1, + 0, + ]; + }, + + newMoshtari(p: { + name: string; + groupName?: string; + tel?: string; + address?: string; + codeMeli?: string; + tarikhTavalod?: string; + moaref?: string; + codeMoaref?: string; + moshtariCode?: number; + jensFelez?: number; + }): unknown[] { + return [ + p.name, + p.groupName ?? 'CRM', + p.tel ?? '', + p.address ?? '', + p.codeMeli ?? '', + p.tarikhTavalod ?? '', + p.moaref ?? '', + p.codeMoaref ?? '-1', + p.moshtariCode ?? -1, + p.jensFelez ?? 0, + ]; + }, +}; diff --git a/apps/api/src/integrations/tahesab/tahesab.controller.ts b/apps/api/src/integrations/tahesab/tahesab.controller.ts new file mode 100644 index 0000000..458c745 --- /dev/null +++ b/apps/api/src/integrations/tahesab/tahesab.controller.ts @@ -0,0 +1,203 @@ +import { + Body, + Controller, + Delete, + Get, + Param, + Patch, + Post, + Query, + UseGuards, +} from '@nestjs/common'; +import { JwtAuthGuard } from '../../auth/jwt-auth.guard'; +import { CurrentUser } from '../../auth/current-user.decorator'; +import { Roles } from '../../auth/roles.decorator'; +import { RolesGuard } from '../../auth/roles.guard'; +import { TahesabConnectionsService } from './connections.service'; +import { TahesabPersonLinkService } from './person-link.service'; +import { TahesabBalanceService } from './balance.service'; +import { TahesabDocumentsService } from './documents.service'; +import { + CreateInTahesabDto, + CreateTahesabConnectionDto, + ImportFromTahesabDto, + ManualLinkDto, + MatchPersonDto, + PushSanadDto, + SearchTahesabDto, + UpdateTahesabConnectionDto, +} from './dto'; + +@Controller('integrations/tahesab') +@UseGuards(JwtAuthGuard, RolesGuard) +export class TahesabController { + constructor( + private readonly connections: TahesabConnectionsService, + private readonly links: TahesabPersonLinkService, + private readonly balance: TahesabBalanceService, + private readonly documents: TahesabDocumentsService, + ) {} + + // —— Connections —— + /** لیست اتصالات برای انتخاب در پروفایل (بدون توکن خام) */ + @Get('connections/public') + listPublicConnections(@CurrentUser() user: { organizationId: string }) { + return this.connections.list(user.organizationId); + } + + @Get('connections') + @Roles('owner', 'admin') + listConnections(@CurrentUser() user: { organizationId: string }) { + return this.connections.list(user.organizationId); + } + + @Post('connections') + @Roles('owner', 'admin') + createConnection( + @CurrentUser() user: { organizationId: string }, + @Body() dto: CreateTahesabConnectionDto, + ) { + return this.connections.create(user.organizationId, dto); + } + + @Patch('connections/:id') + @Roles('owner', 'admin') + updateConnection( + @CurrentUser() user: { organizationId: string }, + @Param('id') id: string, + @Body() dto: UpdateTahesabConnectionDto, + ) { + return this.connections.update(user.organizationId, id, dto); + } + + @Delete('connections/:id') + @Roles('owner', 'admin') + removeConnection( + @CurrentUser() user: { organizationId: string }, + @Param('id') id: string, + ) { + return this.connections.remove(user.organizationId, id); + } + + @Post('connections/:id/test') + @Roles('owner', 'admin') + testConnection( + @CurrentUser() user: { organizationId: string }, + @Param('id') id: string, + ) { + return this.connections.test(user.organizationId, id); + } + + // —— Person links (all authenticated CRM users in org) —— + @Get('people/:personId/links') + listLinks( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + ) { + return this.links.listLinks(user.organizationId, personId); + } + + @Post('people/:personId/links') + manualLink( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Body() dto: ManualLinkDto, + ) { + return this.links.manualLink(user.organizationId, personId, dto); + } + + @Delete('people/:personId/links/:connectionId') + unlink( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Param('connectionId') connectionId: string, + ) { + return this.links.unlink(user.organizationId, personId, connectionId); + } + + @Post('people/:personId/match') + match( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Body() dto: MatchPersonDto, + ) { + return this.links.match(user.organizationId, personId, dto); + } + + @Post('people/:personId/create-in-tahesab') + createInTahesab( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Body() dto: CreateInTahesabDto, + ) { + return this.links.createInTahesab(user.organizationId, personId, dto); + } + + @Get('people/:personId/assets') + getAssets( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Query('connectionId') connectionId?: string, + @Query('refresh') refresh?: string, + ) { + return this.balance.getCachedOrFetch( + user.organizationId, + personId, + connectionId, + refresh !== '0', + ); + } + + @Get('people/:personId/asnad') + listAsnad( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Query('from') from: string, + @Query('to') to: string, + @Query('connectionId') connectionId?: string, + ) { + return this.documents.listAsnad( + user.organizationId, + personId, + from, + to, + connectionId, + ); + } + + @Get('lookups') + lookups( + @CurrentUser() user: { organizationId: string }, + @Query('connectionId') connectionId?: string, + ) { + return this.documents.listLookups(user.organizationId, connectionId); + } + + @Post('people/:personId/sanad') + @Roles('owner', 'admin', 'sales') + pushSanad( + @CurrentUser() user: { organizationId: string }, + @Param('personId') personId: string, + @Body() dto: PushSanadDto, + ) { + return this.documents.pushSanad(user.organizationId, personId, dto); + } + + @Post('sync/search') + @Roles('owner', 'admin', 'sales') + search( + @CurrentUser() user: { organizationId: string }, + @Body() dto: SearchTahesabDto, + ) { + return this.links.search(user.organizationId, dto); + } + + @Post('sync/import') + @Roles('owner', 'admin', 'sales') + importFromTahesab( + @CurrentUser() user: { organizationId: string }, + @Body() dto: ImportFromTahesabDto, + ) { + return this.links.importFromTahesab(user.organizationId, dto); + } +} diff --git a/apps/api/src/integrations/tahesab/tahesab.module.ts b/apps/api/src/integrations/tahesab/tahesab.module.ts new file mode 100644 index 0000000..d5b85fb --- /dev/null +++ b/apps/api/src/integrations/tahesab/tahesab.module.ts @@ -0,0 +1,29 @@ +import { Module } from '@nestjs/common'; +import { AuthModule } from '../../auth/auth.module'; +import { TahesabCryptoService } from './tahesab-crypto.service'; +import { TahesabHttpClient } from './tahesab-http.client'; +import { TahesabConnectionsService } from './connections.service'; +import { TahesabPersonLinkService } from './person-link.service'; +import { TahesabBalanceService } from './balance.service'; +import { TahesabDocumentsService } from './documents.service'; +import { TahesabController } from './tahesab.controller'; + +@Module({ + imports: [AuthModule], + controllers: [TahesabController], + providers: [ + TahesabCryptoService, + TahesabHttpClient, + TahesabConnectionsService, + TahesabPersonLinkService, + TahesabBalanceService, + TahesabDocumentsService, + ], + exports: [ + TahesabConnectionsService, + TahesabPersonLinkService, + TahesabBalanceService, + TahesabDocumentsService, + ], +}) +export class TahesabModule {} diff --git a/apps/web/src/components/person-assets/PersonAssetsPanel.vue b/apps/web/src/components/person-assets/PersonAssetsPanel.vue new file mode 100644 index 0000000..3f10e9c --- /dev/null +++ b/apps/web/src/components/person-assets/PersonAssetsPanel.vue @@ -0,0 +1,868 @@ + + + + + diff --git a/apps/web/src/layouts/AppLayout.vue b/apps/web/src/layouts/AppLayout.vue index b2874bc..ef00e69 100644 --- a/apps/web/src/layouts/AppLayout.vue +++ b/apps/web/src/layouts/AppLayout.vue @@ -42,6 +42,7 @@ const settingsPaths = [ '/settings/custom-fields', '/settings/products', '/settings/currencies', + '/settings/tahesab', '/settings/faq', ]; @@ -327,6 +328,7 @@ onUnmounted(() => { فرم‌ساز سرنخ فیلدهای سفارشی ارزها + ته‌حساب FAQ diff --git a/apps/web/src/lib/tahesab.ts b/apps/web/src/lib/tahesab.ts new file mode 100644 index 0000000..a72d6bd --- /dev/null +++ b/apps/web/src/lib/tahesab.ts @@ -0,0 +1,8 @@ +/** برچسب انواع سند ته‌حساب — کپی runtime برای Vite (بدون named export از shared) */ +export const TAHSAB_SANAD_LABELS: Record = { + buy_sale_gold: 'خرید/فروش آبشده', + buy_sale_sekeh: 'خرید/فروش سکه', + talab_bedehi: 'طلب/بدهی', + vkh_gold: 'واریز/خروج طلا', + vkh_bank: 'واریز/خروج بانکی', +}; diff --git a/apps/web/src/router/index.ts b/apps/web/src/router/index.ts index 88b0304..26f09ae 100644 --- a/apps/web/src/router/index.ts +++ b/apps/web/src/router/index.ts @@ -204,6 +204,12 @@ export const router = createRouter({ component: () => import('@/views/CurrencySettingsView.vue'), meta: { roles: ['owner', 'admin'] as UserRole[] }, }, + { + path: 'settings/tahesab', + name: 'tahesab-settings', + component: () => import('@/views/TahesabSettingsView.vue'), + meta: { roles: ['owner', 'admin'] as UserRole[] }, + }, { path: 'settings/faq', name: 'faq-settings', diff --git a/apps/web/src/views/PersonProfileView.vue b/apps/web/src/views/PersonProfileView.vue index 52fd512..dc21633 100644 --- a/apps/web/src/views/PersonProfileView.vue +++ b/apps/web/src/views/PersonProfileView.vue @@ -21,6 +21,7 @@ import MentoMemoryPanel from '@/components/MentoMemoryPanel.vue'; import AskMentoPanel from '@/components/AskMentoPanel.vue'; import ProfileEmptyState from '@/components/person-profile/ProfileEmptyState.vue'; import ProfileMoreMenu from '@/components/person-profile/ProfileMoreMenu.vue'; +import PersonAssetsPanel from '@/components/person-assets/PersonAssetsPanel.vue'; import type { ProfileMoreItem } from '@/components/person-profile/ProfileMoreMenu.vue'; import type { ActivityDto, @@ -40,7 +41,7 @@ import type { } from '@mento/shared'; import { PERSON_MOOD_LABELS } from '@/lib/person-mood'; -type TabKey = 'activities' | 'deals' | 'cards' | 'info'; +type TabKey = 'activities' | 'deals' | 'cards' | 'assets' | 'info'; type TimelineTone = 'call' | 'quote' | 'note' | 'meeting' | 'task'; type HistoryFilter = 'all' | TimelineTone; @@ -65,6 +66,7 @@ const TABS: Array<{ key: TabKey; label: string }> = [ { key: 'activities', label: 'فعالیت‌ها' }, { key: 'deals', label: 'معاملات' }, { key: 'cards', label: 'کارت‌ها' }, + { key: 'assets', label: 'دارایی' }, { key: 'info', label: 'اطلاعات' }, ]; @@ -345,7 +347,13 @@ function formatSize(bytes: number) { function readTab() { const q = route.query.tab; - if (q === 'activities' || q === 'deals' || q === 'cards' || q === 'info') { + if ( + q === 'activities' || + q === 'deals' || + q === 'cards' || + q === 'assets' || + q === 'info' + ) { tab.value = q; } else { tab.value = 'activities'; @@ -803,6 +811,10 @@ watch(() => route.query.tab, readTab, { immediate: true }); +
+ +
+
diff --git a/apps/web/src/views/TahesabSettingsView.vue b/apps/web/src/views/TahesabSettingsView.vue new file mode 100644 index 0000000..3f88921 --- /dev/null +++ b/apps/web/src/views/TahesabSettingsView.vue @@ -0,0 +1,502 @@ + + + + + diff --git a/deploy/.env.production.example b/deploy/.env.production.example index 9261044..df4e9eb 100644 --- a/deploy/.env.production.example +++ b/deploy/.env.production.example @@ -39,3 +39,6 @@ STT_ENABLED=true STT_URL=http://127.0.0.1:3040 STT_INTERNAL_TOKEN=change-me-stt-internal-token STT_TIMEOUT_MS=60000 + +# رمزنگاری توکن‌های اتصال حسابداری (ته‌حساب) — ۳۲ بایت hex (۶۴ کاراکتر) +INTEGRATIONS_ENCRYPTION_KEY=change-me-64-hex-chars-use-openssl-rand-hex-32 diff --git a/deploy/DEPLOY.md b/deploy/DEPLOY.md index ff05056..17e0573 100644 --- a/deploy/DEPLOY.md +++ b/deploy/DEPLOY.md @@ -65,6 +65,7 @@ nano apps/api/.env | `CORS_ORIGIN` | `https://crm.montzar.ir` | | `SMS_*` | همان ترِز مونتایم | | `PORTAL_SHOW_OTP` | در production حتماً `false` | +| `INTEGRATIONS_ENCRYPTION_KEY` | ۶۴ کاراکتر hex برای رمز توکن ته‌حساب (`openssl rand -hex 32`) | نمونهٔ اتصال: diff --git a/docs/integrations/tahesab-openapi.json b/docs/integrations/tahesab-openapi.json new file mode 100644 index 0000000..1ee6b77 --- /dev/null +++ b/docs/integrations/tahesab-openapi.json @@ -0,0 +1,9373 @@ +Source URL: https://tahesab.ir/APiDoc/openapi.json +Title: openapi.json + +{ + "openapi": "3.1.0", + "info": { + "title": "Tahesab APi", + "version": "", + "description": "## **مستندات وب سرویس**\n\n**(نسخه 10.1405.05.29)**\n\n**(**[تغییرات نسخه جدید APi](https://tahesab.ir/Changelog-APi)**)**\n\nبرای فعال سازی وب سرویس، برنامه ی ته حساب را باز نمایید، منوی پرونده، وب سرویس APi را انتخاب نمایید.\n\nوب سرویس بر روی سیستم شخصی، سرور مجازی یا ابری شما نصب و راه اندازی می شود و از لحاظ فنی نیازی به شرکت ته حساب در هیچ مرحله ای ندارد. (ته حساب به صورت کاملا Self-Hosted ارایه می شود)\n\nسرور تست به صورت پیش فرض در این مستندات فعال می باشد و می توانید تست های خود را در همین بخش انجام دهید.\n\nهر در خواست نیاز به هدر DBname و Authorization: Bearer دارد.\n\nپارامتر DBname برای انتخاب دیتابیس (محیط) مورد نظر جهت اتصال می باشد. (DB برای اکسس و TahesabDB برای SQL Server)\n\nپورت پیش فرض https (8081) و http (9550) می باشد.\n\nChangelog: [https://tahesab.ir/Changelog-APi](https://tahesab.ir/Changelog-APi) \nTelegram: [@Tahesab](https://t.me/Tahesab) \nOnline Chat: [https://s.tahesab.ir](https://s.tahesab.ir) \nTel: +9890000995" + }, + "servers": [ + { + "url": "{protocol}://{host}", + "variables": { + "protocol": { + "default": "https" + }, + "host": { + "default": "api-test.tahesab.ir" + } + } + } + ], + "tags": [ + { + "name": "راهنمای پارامتر ها", + "description": "### توضیح پارامتر ها\n\n| پارامتر | نوع و مقدار نمونه | توضیح |\n| --- | --- | --- |\n| `GID` | `integer` — `1` | کد گروه حساب. |\n| `Moshtari_Code` | `integer` — `1` | کد حساب/مشتری. در ثبت مشتری جدید اگر `-1` ارسال شود کد حساب خودکار ساخته می‌شود. |\n| `Moshtari_Name` | `string` — `نام مشتری` | نام حساب/مشتری یا فیلتر نام. |\n| `GroupName` | `string` — `بنکدار` | نام گروه حساب. |\n| `Tel` | `string` — `9121790179` | شماره تلفن/موبایل. |\n| `Address` | `string` — `خیابان استاد نجات الهی` | آدرس. |\n| `CodeMeli` | `string` — `00112312311` | کد ملی. |\n| `Tarikh_Tavalod` | `string` — `1366-12-04` | تاریخ تولد. |\n| `Moaref` | `string` — `نام` | نام معرف. |\n| `Code_Moaref` | `string` — `1` | `-1` |\n| `Jens_Felez` | `integer` — `0` | نوع جنس فلز: `0=طلا`، `1=پلاتین`، `2=نقره`. |\n| `From_Code` | `integer` — `1` | کد حساب شروع بازه. |\n| `To_Code` | `integer` — `500` | کد حساب پایان بازه. |\n| `BaEhtesabSekeh` | `integer` — `0` | اگر `0` ارسال شود سکه در تراز محاسبه نمی‌شود و اگر `1` ارسال شود محاسبه می‌شود. |\n| `Sabte_Kol_Or_Movaghat_1_0` | `integer` — `0` | برای ثبت کل عدد `1` و برای ثبت موقت عدد `0` را وارد نمایید. |\n| `Factor_Number` | `integer` — `1` | شماره سند/فاکتور؛ اگر `-1` ارسال شود شماره به‌صورت خودکار ساخته می‌شود. |\n| `Radif_Number` | `integer` — `1` | شماره ردیف سند؛ معمولاً عدد `1` ارسال می‌شود. |\n| `Shamsi_Year` | `integer` — `1405` | سال تاریخ سند به شمسی. |\n| `Shamsi_Month` | `integer` — `3` | ماه تاریخ سند به شمسی؛ طبق مستندات بدون صفر ابتدایی ارسال شود. |\n| `Shamsi_Day` | `integer` — `1` | روز تاریخ سند به شمسی؛ طبق مستندات بدون صفر ابتدایی ارسال شود. |\n| `Sharh` | `string` — `شرح` | شرح سند یا توضیح ردیف. |\n| `Factor_Code` | `string` — `A121321....` | کد غیرتکراری سند؛ حداقل ۲۰ کاراکتر. اگر `-1` ارسال شود کد فاکتور خودکار ساخته می‌شود. |\n| `MultiRadif` | `integer` — `-1` | اگر `1` ارسال شود و `Factor_Code` یکسان باشد، چند ردیف در یک سند ثبت می‌شود. |\n| `Vazn` | `decimal` — `12.63` | وزن کالا/طلا/سکه/شمش. |\n| `Ayar` | `decimal` — `750` | عیار مجاز مانند `900`. |\n| `Ang_Number` | `string` — `123456` | شماره انگ آبشده. |\n| `Name_az` | `string` — `نام آزمایشگاه` | نام آزمایشگاه/ری‌گیری. |\n| `IsVoroodOrKhorooj_0_1` | `integer` — `0` | اگر `0` وارد شود نوع سند دریافتی/ورود و اگر `1` وارد شود پرداختی/خروج است. |\n| `IsMotefaregheOrAbshode_0_1` | `integer` — `1` | اگر `0` ارسال شود متفرقه و اگر `1` ارسال شود آبشده است. |\n| `HavalehBe_Mcode` | `integer` — `-1` | کد حسابی که سند قرار است به آن حواله شود؛ در صورت عدم حواله، `-1` ارسال شود. |\n| `BuyOrSale_0_1` | `integer` — `0` | برای همه متدها `1=خرید` و `0=فروش` است؛ در `DoNewSanadBuySaleEtiket` استثنا دارد. |\n| `Mazaneh` | `decimal` — `107900000` | مظنه/نرخ مورد استفاده در سند. |\n| `MazanehIsMesghalOrGeram_0_1` | `integer` — `0` | اگر `0` ارسال شود مظنه هر مثقال و اگر `1` ارسال شود قیمت هر گرم است. |\n| `MablaghKol` | `decimal` — `10000000` | مبلغ کل سند/معامله. |\n| `Zaman_Tasvie` | `string` — `1405-02-30` | زمان/تاریخ تسویه با قالب تاریخ شمسی. |\n| `ArzName` | `string` — `USD` | نام ارز مورد استفاده در سند یا فیلتر. |\n| `Count` | `decimal` — `2` | تعداد کالا/سکه/شمش/کارساخته. |\n| `Name_Sekeh` | `string` — `SEKEHName` | نام سکه. |\n| `Is_BedehieMa_TalabeMa_0_1` | `integer` — `0` | نوع سند طلب/بدهی سکه. |\n| `Name_Shemsh` | `string` — `ShemshName` | نام شمش. |\n| `Name_Kar` | `string` — `مدال` | نام کار ساخته. |\n| `OjratTedadiOrGerami_0_1` | `integer` — `1` | اگر اجرت هر عدد است `0` و اگر اجرت هر گرم است `1` ارسال شود. |\n| `Darsad_Maliat` | `decimal` — `10` | درصد مالیات/ارزش افزوده. |\n| `MeghdarMaliat` | `decimal` — `1500000` | مقدار محاسبه‌شده کل مالیات. |\n| `Darsad_Sood` | `decimal` — `7` | درصد سود. |\n| `Darsad_Talayee` | `decimal` — `15` | درصد طلایی یا درصد مرتبط با محاسبات کارساخته/اتیکت. |\n| `IsMarjoo_1_0` | `integer` — `1` | وضعیت مرجوعی کالا. |\n| `PoolSang` | `decimal` — `15000000` | مبلغ سنگ. |\n| `PictureFileName` | `string` — `—` | نام فایل تصویر؛ مثال `a1.jpg`. |\n| `Ojrat` | `decimal` — `6000000` | مقدار اجرت. |\n| `Shenase` | `integer` — `1` | شناسه کار اتیکت. |\n| `IsDayaftAzMoshtariOrPardakhtBeMoshtari_0_1` | `integer` — `1` | نوع عملیات بانکی: دریافت از مشتری به بانک یا پرداخت به مشتری از بانک. |\n| `Name_Bank` | `string` — `سامان` | نام حساب بانکی. |\n| `Code_Rahgiri` | `string` — `100` | کد رهگیری/پیگیری عملیات بانکی. |\n| `IsBedehiOrTalab_0_1` | `integer` — `0` | نوع سند طلب/بدهی. |\n| `Baabat` | `string` — `Baabat` | بابت/موضوع طلب یا بدهی. |\n| `IsMaBeMoshtariOrMoshtariBeMa_0_1` | `integer` — `0` | نوع تخفیف: تخفیف ما به مشتری یا مشتری به ما. |\n| `MeghdarArz` | `decimal` — `1000` | مقدار/تعداد ارز در سند ارزی. |\n| `ArzName_Tasvie` | `string` — `EUR` | نام ارز تسویه/طرف مقابل در سند ارزی. |\n| `File_Name` | `string` — `Camera.jpg` | نام فایل تصویر اتیکت. |\n| `Code_List` | `array of strings` — `[\"1\", \"9\", \"10\"]` | لیستی از شناسه‌های کار؛ متد می‌تواند یک یا چند شناسه را در آرایه دریافت کند. |\n| `WithPhoto_1_0` | `integer` — `0` | اگر `1` ارسال شود لیست اتیکت‌ها با تصویر برگشت داده می‌شود؛ اگر `0` ارسال شود بدون تصویر. |\n| `Code_Kar_String` | `string` — `KC1` | کد کار به‌صورت رشته برای فیلتر لیست اتیکت. |\n| `Count_Last` | `integer` — `0` | تعداد اسناد به ترتیب تاریخ از آخر؛ برای ایجاد مانده ردیف‌به‌ردیف `-1` ارسال شود. |\n| `AzTarikhShamsi` | `string` — `1400-12-15` | فیلتر از تاریخ شمسی. |\n| `TaTarikhShamsi` | `string` — `1405-02-30` | فیلتر تا تاریخ شمسی. |\n| `FilterNoSanad` | `string` — `ورود آبشده` | فیلتر نوع سند؛ مثلاً ورود وجه نقد یا خروج کارساخته. |\n| `EPC_List` | `array of strings` — `[\"E123456789123456\"]` | لیست تگ‌های RFID/EPC. |\n| `No` | `integer` — `0` | نوع موجودی آبشده/متفرقه در لیست موجودی. |\n| `Code` | `integer` — `3` | شناسه کار. |\n| `Baabat` | `string` — `قبض برق` | بابت سند قید می‌شود. |\n| `Shomare_Posht_Cheq` | `integer` — `شماره پشت چک` | اگر `-1` ارسال شود خودکار محاسبه می‌شود. |\n| `Mande_Jens_Felez` | `integer` — `نمایش مانده جنس فلز` | مثلاً اگر عدد `2` ارسال شود، مانده نقره حساب می‌شود؛ اگر عدد `0` ارسال شود، مانده طلا محاسبه می‌شود. |\n| `IsSharti` | `boolean` — `شرطی` | در صورتی که `true` وارد شود عیار طلا شرطی ثبت می‌شود؛ فقط در ورود و خروج آبشده. |\n| `Bishtar_Az_Vazn` | `decimal` — `بیشتر از وزن` | برای فیلتر وزن‌های بیشتر از مقدار مشخص‌شده. |\n| `Kamtar_Az_Vazn` | `decimal` — `کمتر از وزن` | برای فیلتر وزن‌های کمتر از مقدار مشخص‌شده. |" + }, + { + "name": "سند تکراری", + "description": "#### **جهت جلوگیری از ثبت تکراری یک سند حتما پارامتر Factor_Code را ارسال نمایید.**\n\n#### (کد فاکتور باید **حداقل 20 کارکتر باشد. در صورتی که کمتر از این تعداد کارکتر ارسال شود، اعمال نمی شود.)**\n\n#### پارامتر (Factor_Number) شماره سند می باشد." + }, + { + "name": "Health", + "description": "" + }, + { + "name": "List", + "description": "این بخش شامل متد های دریافت انواع لیست ها می باشد." + }, + { + "name": "Hesab-Moshtari", + "description": "این بخش شامل متد های مربوط به حساب و مشتری می باشد." + }, + { + "name": "Sanad", + "description": "این بخش شامل متد هایی برای ثبت انواع اسناد می باشد." + }, + { + "name": "RFID", + "description": "این بخش شامل متد های مربوط به ارتباط با دستگاه ها و تگ های RFID می باشد." + }, + { + "name": "Etiket", + "description": "این بخش شامل متد هایی برای اتیکت می باشد." + }, + { + "name": "TarazMojoodi", + "description": "این بخش شامل متد هایی برای دریافت موجود و تراز می باشد." + } + ], + "paths": { + "/CheckHealth-SSL": { + "get": { + "summary": "CheckHealth (SSL)", + "tags": [ + "Health" + ], + "responses": { + "200": { + "description": "CheckHealth (SSL)", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Status": { + "type": "string" + }, + "Api_Status": { + "type": "string" + }, + "DB_Status": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "Status": "OK", + "Api_Status": "OK", + "DB_Status": "OK", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "18", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "4448", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "[::1]:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "0:0:0:0:0:0:0:1", + "UserIP2": "0:0:0:0:0:0:0:1", + "UserPort": "64407", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:01:18", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "10", + "Count_UnSuccess_Request": "5", + "Last_Request": "2026-08-05 16:02:49" + } + } + } + } + }, + "description": "از این متد برای بررسی سلامت وب سرویس با SSL استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "CheckHealth": { + "type": "array", + "items": [] + } + } + }, + "example": { + "CheckHealth": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "CheckHealth": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"CheckHealth\": []\n}\n```" + } + } + }, + "/CheckHealth-No-SSL": { + "get": { + "summary": "CheckHealth (No-SSL)", + "tags": [ + "Health" + ], + "responses": { + "200": { + "description": "CheckHealth", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Status": { + "type": "string" + }, + "Api_Status": { + "type": "string" + }, + "DB_Status": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "Status": "OK", + "Api_Status": "OK", + "DB_Status": "OK", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "18", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "1", + "SSLVersion": "UNKNOWN", + "SSLCipher": "UNKNOWN", + "SSLCipherBits": "0", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "18000", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "[::1]:8082", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "0:0:0:0:0:0:0:1", + "UserIP2": "0:0:0:0:0:0:0:1", + "UserPort": "64355", + "TahesabVersion": "10.1405.5.11", + "DBType": "SQL Server", + "DBName": "tahesabdb", + "ServerDBVersion": "Microsoft SQL Server 17.00.1125", + "ClientDBVersion": "19.4.0001.0", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:00:11", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "3", + "Count_UnSuccess_Request": "0", + "Last_Request": "2026-08-05 16:01:42" + } + } + } + } + }, + "description": "از این متد برای بررسی سلامت وب سرویس بدون SSL استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ] + } + }, + "/DoListNameMohit": { + "post": { + "summary": "DoListNameMohit", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListNameMohit", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + } + } + } + }, + "example": [ + { + "Name": "DB" + }, + { + "Name": "DB1" + }, + { + "Name": "DB2" + }, + { + "Name": "DB4" + } + ] + } + } + } + }, + "description": "از این متد برای دریافت لیست نام محیط ها استفاده می شود. (برای ارسال DBName در Header)\n\n### پارامترهای Body\n\nاین درخواست نیازی به DBName در Header ندارد.\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListNameMohit": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListNameMohit": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListNameMohit": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListNameMohit\": []\n}\n```" + } + } + }, + "/DoListNameARZ": { + "post": { + "summary": "DoListNameARZ", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListNameARZ", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Latin": { + "type": "string" + } + } + } + }, + "example": [ + { + "Name": "دلار", + "Latin": "USD" + }, + { + "Name": "درهم", + "Latin": "DRH" + } + ] + } + } + } + }, + "description": "از این متد برای دریافت لیست ارز ها استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListNameARZ": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListNameARZ": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListNameARZ": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListNameARZ\": []\n}\n```" + } + } + }, + "/DoListNameReygiri": { + "post": { + "summary": "DoListNameReygiri", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListNameReygiri", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Tel1": { + "type": "string" + }, + "Tel2": { + "type": "string" + }, + "Tel3": { + "type": "string" + }, + "Tel4": { + "type": "string" + } + } + } + }, + "example": [ + { + "Name": "آخرت تبريز", + "Tel1": "04135232596", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آذربايجان تبريز", + "Tel1": "04135535746", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آذرگلد اهواز", + "Tel1": "06132235743", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آذين تهران", + "Tel1": "02133994199", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آرمان تهران", + "Tel1": "02133925305", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آروين دزفول", + "Tel1": "06142231232", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آريا تهران", + "Tel1": "02133964641", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آريا قيدار زنجان", + "Tel1": "02434227180", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آرين آناليزاردبيل", + "Tel1": "04533362517", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آسيا تبريز", + "Tel1": "04135266971", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آسيا تهران", + "Tel1": "02155156026", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آقانژاد اردبيل", + "Tel1": "04532791600", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آلا پيرانشهر", + "Tel1": "04444220475", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "آلتين مرند", + "Tel1": "04142273288", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اتحاد اصفهان", + "Tel1": "03132227553", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اتحاد زنجان", + "Tel1": "02433321549", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اثني عشرمراغه", + "Tel1": "04137226548", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "احمدي اصفهان", + "Tel1": "03132239425", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "احمدي تهران", + "Tel1": "02133532502", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اختري مرند", + "Tel1": "04142270716", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اخوان تهران", + "Tel1": "02133975768", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ارشاد سنندج", + "Tel1": "08733127593", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ارغوان بوکان", + "Tel1": "04446223894", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ارگ مشهد", + "Tel1": "05132217178", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اروم سنجش اروميه", + "Tel1": "04532251400", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اسپادانا اصفهان", + "Tel1": "03132234249", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اشنوسنج", + "Tel1": "04444632531", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اشکان همدان", + "Tel1": "08132520427", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اطمينان تهران", + "Tel1": "02155582669", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اعتماد خوي", + "Tel1": "04436220767", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اعتماد يزد", + "Tel1": "03536228399", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "افق تهران", + "Tel1": "02133878917", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "البرز اصفهان", + "Tel1": "03132206963", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "الماس شهرکرد", + "Tel1": "03832244724", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "الوند ملاير", + "Tel1": "09139691631", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اميد کرج", + "Tel1": "02632225738", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اميدسنجش بهشهر", + "Tel1": "01134537755", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "امير مشکين شهر", + "Tel1": "04532540622", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اميران سلماس", + "Tel1": "04435241923", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اميرحسين تنکابن", + "Tel1": "01154222224", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "امين اردبيل", + "Tel1": "0453224553", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "امين اصفهان", + "Tel1": "03132234679", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "امين تهران", + "Tel1": "02136613516", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اوين بوکان", + "Tel1": "04446220684", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "اياز زاهدان", + "Tel1": "09151414630", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ايران تبريز", + "Tel1": "04135249640", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ايران ري تهران", + "Tel1": "02133939432", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ايران ري مشهد", + "Tel1": "05132238666", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ايران ري يزد", + "Tel1": "03536268298", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ايران قم", + "Tel1": "02537706076", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ايران ليزر تهران", + "Tel1": "02133906071", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "باختر کرمانشاه", + "Tel1": "08337295717", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "باقري خرم آباد", + "Tel1": "06633314772", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "بامدادي مشهد", + "Tel1": "05138473997", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "براتي مشهد", + "Tel1": "05133731581", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "برليان تبريز", + "Tel1": "04135538395", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "برنا آبادان", + "Tel1": "06153266092", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "بعثت يزد", + "Tel1": "03536269763", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "به سنجش قائم شهر", + "Tel1": "01134537406", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "بهروزي مشهد", + "Tel1": "05137321238", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "بهساز تهران", + "Tel1": "02166439294", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "بوکان ري", + "Tel1": "04446246611", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارس اصفهان", + "Tel1": "03134488229", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارس انديشه تهران", + "Tel1": "02165504056", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارس تربت حيدريه", + "Tel1": "05152220553", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارس تهران", + "Tel1": "02188935730", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارس ري کرج", + "Tel1": "02665504056", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارس شمس شيراز", + "Tel1": "07153316791", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارسا زارعي ملارد", + "Tel1": "09190854484", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارسه آمل", + "Tel1": "01144228084", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارسيان اصفهان", + "Tel1": "03132212285", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارسيان بيرجند", + "Tel1": "05632231061", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پارسيان زر شاهرود", + "Tel1": "09124734902", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پايتخت تهران", + "Tel1": "02133950863", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پايش سبزمعتمد بجنورد", + "Tel1": "05832242730", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پرتو تهران", + "Tel1": "02155580093", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پويا اصفهان", + "Tel1": "03132215700", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پويازر قم", + "Tel1": "02538827939", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پويش اصفهان", + "Tel1": "03132220810", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پيرايه زيست قزوين", + "Tel1": "02833239664", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پيروز اصفهان", + "Tel1": "03132200741", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پيشتاز اصفهان", + "Tel1": "03132203619", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پيمان اصفهان", + "Tel1": "03132220574", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "پيمان تهران", + "Tel1": "02133946941", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تابش تهران", + "Tel1": "02133975794", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تاراز بروجرد", + "Tel1": "06642611679", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تالش", + "Tel1": "09128404680", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تنديس شمال آمل", + "Tel1": "01144225915", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تهران سنج", + "Tel1": "02136615456", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تک آزما ورامين", + "Tel1": "02136291412", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تک اردبيل", + "Tel1": "04532256770", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تکنو تست تبريز", + "Tel1": "04135255440", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تکنو تهران", + "Tel1": "02133992787", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تکنوتست اصفهان", + "Tel1": "03132205552", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "تکنوفن اصفهان", + "Tel1": "03132214688", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ثامن يزد", + "Tel1": "03536264845", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "جباري مشهد", + "Tel1": "05132243657", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "جعفري بوکان", + "Tel1": "04446261267", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "جم خوي", + "Tel1": "04436444978", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "جمالي تهران", + "Tel1": "02133920929", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حاج احد تهران", + "Tel1": "02133959909", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حافظ اصفهان", + "Tel1": "03132216740", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حجت تهران", + "Tel1": "02133954317", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حسام زاگرس کرمانشاه", + "Tel1": "08337278623", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حسيني تهران", + "Tel1": "02136419216", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حميد 1 تهران", + "Tel1": "02133904198", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حميد شمال بابل", + "Tel1": "01132191833", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حميد قديم تهران", + "Tel1": "02133900194", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "حکمت تهران", + "Tel1": "02133905756", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "خاوران سنجش دارايي مشهد", + "Tel1": "05136093716", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "خاوران سنجش مولايي مشهد", + "Tel1": "05138451574", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "خرم آباد", + "Tel1": "06633306087", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "خسرو خاور مشهد", + "Tel1": "05132214286", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "خورشيد گرگان", + "Tel1": "01732225258", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "درخشان تهران", + "Tel1": "02155618599", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "درخشان سلماس", + "Tel1": "04435245327", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "درويشان تهران", + "Tel1": "02133900690", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقت تهران", + "Tel1": "02133926724", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقت زنجان", + "Tel1": "02433326529", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق آزما تهران", + "Tel1": "02133532717", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق تبريز", + "Tel1": "04135230666", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق خوي", + "Tel1": "04436452911", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق ري تهران", + "Tel1": "02155933299", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق سلماس", + "Tel1": "04435245941", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق شيراز", + "Tel1": "07132233625", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق ماکو", + "Tel1": "04434229272", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دقيق ملکان", + "Tel1": "04137823984", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "دهزاد قائم شهر", + "Tel1": "01142208081", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رئال خوي", + "Tel1": "04436721677", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رازي اصفهان", + "Tel1": "03132227555", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رجبي قائم شهر", + "Tel1": "01142232432", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رزگلد بروجرد", + "Tel1": "06642607998", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رصد مراغه", + "Tel1": "04137242391", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رضا مياندوآب", + "Tel1": "04445260540", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رنجبر ساوه", + "Tel1": "08642437350", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "روح الهي کرمان", + "Tel1": "03432223838", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "روزبهاني ملاير", + "Tel1": "08132226779", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رويال ليزر اسلامشهر", + "Tel1": "02156359441", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "رويايي مشهد", + "Tel1": "05132794730", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ري 110 تهران", + "Tel1": "02133982746", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ري اتحاديه کرج", + "Tel1": "02632255047", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ري تبريز", + "Tel1": "04135257615", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زاهدان", + "Tel1": "05433233472", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زر تات تهران", + "Tel1": "02155591038", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زر ري تهران", + "Tel1": "02155631867", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرآزما اصفهان", + "Tel1": "03132219217", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرآزمون شهير تهران", + "Tel1": "02155638486", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرچي تهران", + "Tel1": "02133933940", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرسنج قم", + "Tel1": "02537707233", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرسنج مشهد", + "Tel1": "05133670555", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرسنج مياندوآب", + "Tel1": "04445241011", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرسنجش بابل", + "Tel1": "01132198528", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرسنجش ساري", + "Tel1": "09372466686", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرمحک گرگان", + "Tel1": "01732221391", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرنگار شهرضا", + "Tel1": "03153237838", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرياب زنجان", + "Tel1": "02433364725", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين آزما سلماس", + "Tel1": "04435243783", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين آزما کرج", + "Tel1": "02632403700", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين اصفهان", + "Tel1": "03132212700", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين تاج تهران", + "Tel1": "02144200749", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين تبريز", + "Tel1": "04135538182", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين تهران", + "Tel1": "09121157174", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين مشهد", + "Tel1": "05137511710", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرين مياندوآب", + "Tel1": "04445260434", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زريک اصفهان", + "Tel1": "03132200615", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرکوب گرگان", + "Tel1": "01732247020", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زرکوبان نيک زاهدان", + "Tel1": "0543220779", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زمرد کاشان", + "Tel1": "03155448408", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زنگشاهي ايرانشهر", + "Tel1": "09377605347", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زوارقي ملکان", + "Tel1": "04137829956", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "زيبازر قم", + "Tel1": "02537700276", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سالار بناب", + "Tel1": "04137722353", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سام فلاحي کرمانشاه", + "Tel1": "08337287150", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سبحان ابهر", + "Tel1": "02435245574", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سبلان اردبيل", + "Tel1": "04533339768", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سپاهان اصفهان", + "Tel1": "03132217081", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سپهر بجنورد", + "Tel1": "05832212498", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ستار تهران", + "Tel1": "02155148422", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سحرخيز گنبدکاووس", + "Tel1": "01733293113", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سريع سنج شمال", + "Tel1": "09111160032", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سريع سنج يزد", + "Tel1": "03536224764", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سعادتي راد کاشان", + "Tel1": "03155453014", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سعيد سمنان", + "Tel1": "02333340215", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش اصفهان", + "Tel1": "03132235612", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش افشين تهران", + "Tel1": "02133118185", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش تبريز", + "Tel1": "04135256461", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش جباري مشهد", + "Tel1": "05138529794", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش خوي", + "Tel1": "04436442909", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش درويش تهران", + "Tel1": "02133902223", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سنجش مشهد", + "Tel1": "05138519989", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سهراب اردبيل", + "Tel1": "04532252383", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سهند مراغه", + "Tel1": "04137223304", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سهيل تهران", + "Tel1": "02133974805", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سوگند ايلام", + "Tel1": "08433366617", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سولدا زنجان", + "Tel1": "02433363412", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سيد تهران", + "Tel1": "02136055382", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سيفي ايلام", + "Tel1": "08433366625", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "سينا همدان", + "Tel1": "08132523121", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شاهي تهران", + "Tel1": "02133934033", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شمرون تهران", + "Tel1": "09128200369", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شمس تجريش", + "Tel1": "02122721577", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شهريار", + "Tel1": "09352901397", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شوشتري قزوين", + "Tel1": "02833235647", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شيران اصفهان", + "Tel1": "03132233875", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "شکوه دزفول", + "Tel1": "06142237791", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "صائب تبريز", + "Tel1": "04135237325", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "صالحي تبريز", + "Tel1": "04135234144", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "صداقت پيرانشهر", + "Tel1": "04442240307", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ضيايي خوي", + "Tel1": "04436730299", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "طاها ايرانشهر", + "Tel1": "05437223182", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "طلا سنج تهران", + "Tel1": "02155890577", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "طلاي تهران", + "Tel1": "02144232021", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "طلاکاران کوثر اصفهان", + "Tel1": "03142644030", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "طهران گلد", + "Tel1": "02155575125", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ظفري اراک", + "Tel1": "09188635815", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "عباسي ملکان", + "Tel1": "04137826322", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "عزت خواه اروميه", + "Tel1": "04532255656", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "علي تهران", + "Tel1": "02133912752", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "عيار مشهد", + "Tel1": "05133653870", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "عيارسنج سنندج", + "Tel1": "08733151700", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فارس آناليز شيراز", + "Tel1": "07132362641", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فارس محک شيراز", + "Tel1": "07132231895", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فارس کيميا شيراز", + "Tel1": "07132234765", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فرامرزي تبريز", + "Tel1": "04142276120", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فرامرزي مرند", + "Tel1": "04142276120", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فرهاد بناب", + "Tel1": "04137732842", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فرهادي اراک", + "Tel1": "09183600891", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فرهنگ تهران", + "Tel1": "02155801091", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "فريد تبريز", + "Tel1": "04135233871", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "قائم تهران", + "Tel1": "02166717561", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "قريشي اراک", + "Tel1": "08632223345", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گلد سنج نيشابور", + "Tel1": "05142235051", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گلدآزما تهران", + "Tel1": "02136610343", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گلستانه پيرانشهر", + "Tel1": "04444239080", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گنجينه يزد", + "Tel1": "03536260980", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گوهرپارسيان رشت", + "Tel1": "01344239189", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گوياي گرگان", + "Tel1": "01732249995", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گيلازر گيلان", + "Tel1": "01333253603", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "گيلان", + "Tel1": "01333262246", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "لعل تهران", + "Tel1": "02133999544", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مازند ري", + "Tel1": "01132198528", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ماهان اصفهان", + "Tel1": "03132213038", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مجاهدي دو مشهد", + "Tel1": "05132258945", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مجاهدي يک مشهد", + "Tel1": "05132254924", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مجيد بوشهر", + "Tel1": "07733324243", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محسن ايرانشهر", + "Tel1": "09389956460", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محسن قائم شهر", + "Tel1": "09389956460", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محک تبريز", + "Tel1": "04135533468", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محک تهران", + "Tel1": "02133112160", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محک ساري", + "Tel1": "01133304469", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محک مشهد", + "Tel1": "05138524362", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "محک يزد", + "Tel1": "03536273217", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مرکزي تهران", + "Tel1": "02136870399", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مسعود تهران", + "Tel1": "02133118808", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مسلايي قم", + "Tel1": "02537713266", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مطهري سبزوار", + "Tel1": "05144223116", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "معيار آستارا", + "Tel1": "01344823887", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "معيار تهران", + "Tel1": "02144254570", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مقدم بابل", + "Tel1": "01132203869", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مقياس تهران", + "Tel1": "02133920322", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ملل اسلامشهر", + "Tel1": "02156140009", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "منصوري تهران", + "Tel1": "02133900783", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "منهاج تهران", + "Tel1": "02133941664", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مهتاب اصفهان", + "Tel1": "03132229555", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مهدي2 تهران", + "Tel1": "02133937445", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مهرگان مشهد", + "Tel1": "05132795001", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مهندس حريرفروش تهران", + "Tel1": "02133998629", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "مي ريز فارس", + "Tel1": "07153839915", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ميثم مراغه", + "Tel1": "04137244602", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ميرحسني مشهد", + "Tel1": "05133664161", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ميرحسني مشهد", + "Tel1": "05138114069", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ناصر ورامين", + "Tel1": "02136273061", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نمونه تهران", + "Tel1": "02133958118", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نوژان مشهد", + "Tel1": "05133663241", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نوين بناب", + "Tel1": "04137742444", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نوين پويا تهران", + "Tel1": "02156359905", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نوين تبريز", + "Tel1": "04137742444", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نوين تهران", + "Tel1": "02133922259", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "نيکان اصفهان", + "Tel1": "03132224206", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "هادي اهواز", + "Tel1": "06132227463", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "هاشمي تبريز", + "Tel1": "04134227970", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "هزار تهران", + "Tel1": "02136870476", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "هزاراصفهان", + "Tel1": "03132215637", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "وحيد ماکو", + "Tel1": "04434222744", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ورامين", + "Tel1": "02136272422", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "وزيري مشهد", + "Tel1": "05132516192", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ويژن برازجان", + "Tel1": "09139889166", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "ياس زنجان", + "Tel1": "02433361337", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "يلدا شهرکرد", + "Tel1": "03832276779", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "يوسفي اردبيل", + "Tel1": "04533872815", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "يکتا اصفهان", + "Tel1": "03132210869", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کاسپين تهران", + "Tel1": "02133440221", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کاشي کرج", + "Tel1": "09196524144", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کانيار مشهد", + "Tel1": "05136052951", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کاوه تهران", + "Tel1": "02133905727", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کاوه مهاباد", + "Tel1": "04142241419", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کاوه نقده", + "Tel1": "04435627389", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کريمه ملاير", + "Tel1": "09384638733", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کسري کرج", + "Tel1": "02644236820", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کوثر تهران", + "Tel1": "02133111907", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کويراصفهان", + "Tel1": "03132219563", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کياني تبريز", + "Tel1": "04135570510", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کيميا اصفهان", + "Tel1": "03132243143", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کيميا يزد", + "Tel1": "03536227513", + "Tel2": "", + "Tel3": "", + "Tel4": "" + }, + { + "Name": "کيميازر قم", + "Tel1": "02537727641", + "Tel2": "", + "Tel3": "", + "Tel4": "" + } + ] + } + } + } + }, + "description": "از این متد برای دریافت لیست آزمایشگاه های ریگیری استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListNameReygiri": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListNameReygiri": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListNameReygiri": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListNameReygiri\": []\n}\n```" + } + } + }, + "/DoListGorooh": { + "post": { + "summary": "DoListGorooh", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListGorooh", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "GID": { + "type": "integer" + } + } + } + }, + "example": [ + { + "Name": "بنکداران (بازار)", + "GID": 1 + }, + { + "Name": "همکار", + "GID": 2 + }, + { + "Name": "متفرقه", + "GID": 3 + }, + { + "Name": "سازنده", + "GID": 4 + }, + { + "Name": "مخارج", + "GID": 5 + }, + { + "Name": "کیفی", + "GID": 6 + }, + { + "Name": "تراشکار", + "GID": 7 + }, + { + "Name": "ویترین", + "GID": 8 + }, + { + "Name": "جواهر", + "GID": 9 + }, + { + "Name": "صندوق", + "GID": 10 + }, + { + "Name": "سرمایه", + "GID": 11 + }, + { + "Name": "كارمندان", + "GID": 12 + }, + { + "Name": "مشتري", + "GID": 13 + } + ] + } + } + } + }, + "description": "از این متد برای دریافت گروه های حساب ها استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListGorooh": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListGorooh": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListGorooh": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListGorooh\": []\n}\n```" + } + } + }, + "/DoListNameSekeh": { + "post": { + "summary": "DoListNameSekeh", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListNameSekeh", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Vazn": { + "type": "number" + }, + "Ayar": { + "type": "integer" + }, + "Jens_Felez": { + "type": "integer" + }, + "Hide": { + "type": "boolean" + } + } + } + }, + "example": [ + { + "Name": "آزادي", + "Vazn": 8.13, + "Ayar": 900, + "Jens_Felez": 0, + "Hide": true + }, + { + "Name": "امامي", + "Vazn": 8.13, + "Ayar": 900, + "Jens_Felez": 0, + "Hide": false + }, + { + "Name": "ربع سکه", + "Vazn": 2.02, + "Ayar": 900, + "Jens_Felez": 0, + "Hide": false + }, + { + "Name": "نيم سکه", + "Vazn": 4.06, + "Ayar": 900, + "Jens_Felez": 0, + "Hide": false + } + ] + } + } + } + }, + "description": "از این متد برای دریافت لیست نام سکه ها استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListNameSekeh": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListNameSekeh": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListNameSekeh": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListNameSekeh\": []\n}\n```" + } + } + }, + "/DoListNameShemsh": { + "post": { + "summary": "DoListNameShemsh", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListNameShemsh", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Vazn": { + "type": "integer" + }, + "Ayar": { + "type": "number" + }, + "Jens_Felez": { + "type": "integer" + }, + "Hide": { + "type": "boolean" + } + } + } + }, + "example": [ + { + "Name": "10 گرم", + "Vazn": 10, + "Ayar": 999.9, + "Jens_Felez": 0, + "Hide": false + }, + { + "Name": "2.5 گرم", + "Vazn": 2.5, + "Ayar": 999.9, + "Jens_Felez": 0, + "Hide": false + }, + { + "Name": "5 گرم", + "Vazn": 5, + "Ayar": 999.9, + "Jens_Felez": 0, + "Hide": true + }, + { + "Name": "نيم انس", + "Vazn": 10, + "Ayar": 999.9, + "Jens_Felez": 0, + "Hide": false + }, + { + "Name": "يک انس", + "Vazn": 20, + "Ayar": 999.9, + "Jens_Felez": 0, + "Hide": false + }, + { + "Name": "يک گرم", + "Vazn": 1, + "Ayar": 999.9, + "Jens_Felez": 0, + "Hide": false + } + ] + } + } + } + }, + "description": "از این متد برای دریافت لیست نام شمش های تعدادی استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListNameShemsh": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListNameShemsh": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListNameShemsh": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListNameShemsh\": []\n}\n```" + } + } + }, + "/DoListNameKarsakhte": { + "post": { + "summary": "DoListNameKarsakhte", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListNameKarsakhte", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "VaznSabet": { + "type": "null" + }, + "Ayar": { + "type": "integer" + }, + "LastSanad": { + "type": "string" + } + } + } + }, + "example": [ + { + "Name": "النگو آسيا", + "VaznSabet": null, + "Ayar": 750, + "LastSanad": "1405/05/04" + }, + { + "Name": "رولکس", + "VaznSabet": null, + "Ayar": 750, + "LastSanad": "1405/04/25" + } + ] + } + } + } + }, + "description": "از این متد برای دریافت لیست نام کار های ساخته ی دارای سند ثبت شده، استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListNameKarsakhte": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListNameKarsakhte": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListNameKarsakhte": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListNameKarsakhte\": []\n}\n```" + } + } + }, + "/DoListHesabBanki": { + "post": { + "summary": "DoListHesabBanki", + "tags": [ + "List" + ], + "responses": { + "404": { + "description": "DoListHesabBanki", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "هیچ رکوردی یافت نشد.", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "23", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "8644", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "63672", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:04:10", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "34", + "Count_UnSuccess_Request": "6", + "Last_Request": "2026-08-05 16:05:41" + } + } + } + } + }, + "description": "از این متد برای دریافت لیست حساب های بانکی استفاده می شود.\n\n### پارامترهای Body\n\nاین درخواست پارامتر ورودی در آرایه Body ندارد.", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListHesabBanki": { + "type": "array", + "items": [] + } + } + }, + "example": { + "DoListHesabBanki": [] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListHesabBanki": [] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListHesabBanki\": []\n}\n```" + } + } + }, + "/DoListGetUpdatedEtiket": { + "post": { + "summary": "DoListGetUpdatedEtiket", + "tags": [ + "List" + ], + "responses": { + "404": { + "description": "DoListGetUpdatedEtiket", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "هیچ رکوردی یافت نشد.", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "54", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "21940", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "59606", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:32:57", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "285", + "Count_UnSuccess_Request": "24", + "Last_Request": "2026-08-05 16:34:28" + } + } + } + } + }, + "description": "نمایش لیست اتیکت های آپدیت شده (ثبت، تغییر، فروش، خروج و مرجوع) در این بازه ی زمانی\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `AzTarikhShamsi` | `\"1404-08-07\"` |\n| 1 | `TaTarikhShamsi` | `\"1404-08-07\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListGetUpdatedEtiket": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "DoListGetUpdatedEtiket": [ + "1404-08-07", + "1404-08-07" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListGetUpdatedEtiket": [ + "1404-08-07", + "1404-08-07" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListGetUpdatedEtiket\": [\n \"1404-08-07\",\n \"1404-08-07\"\n ]\n}\n```" + } + } + }, + "/DoList-EtiketByCodeKar": { + "post": { + "summary": "DoList_EtiketByCodeKar", + "tags": [ + "List" + ], + "responses": { + "404": { + "description": "DoList_EtiketByCodeKar", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "هیچ رکوردی یافت نشد.", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "34", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "4448", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "59611", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:33:03", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "286", + "Count_UnSuccess_Request": "25", + "Last_Request": "2026-08-05 16:34:33" + } + } + } + } + }, + "description": "نمایش لیست اتیکت ها بر اساس کد کار\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Code_Kar_String` | `\"KC1\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "dolist_etiketbycodekar": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "dolist_etiketbycodekar": [ + "KC1" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "dolist_etiketbycodekar": [ + "KC1" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"dolist_etiketbycodekar\": [\n \"KC1\"\n ]\n}\n```" + } + } + }, + "/DoList-Etiket-Filter": { + "post": { + "summary": "DoList_Etiket_Filter", + "tags": [ + "List" + ], + "responses": { + "404": { + "description": "DoList_Etiket_Filter", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "هیچ رکوردی یافت نشد.", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "45", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "21940", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "59616", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:33:09", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "286", + "Count_UnSuccess_Request": "26", + "Last_Request": "2026-08-05 16:34:40" + } + } + } + } + }, + "description": "نمایش لیست اتیکت ها بر اساس کد کار\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Bishtar_Az_Vazn` | `0` |\n| 1 | `Kamtar_Az_Vazn` | `1` |\n| 2 | `Name_Kar` | `\"انگشتر\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoList_Etiket_Filter": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoList_Etiket_Filter": [ + 0, + 1, + "انگشتر" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoList_Etiket_Filter": [ + 0, + 1, + "انگشتر" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoList_Etiket_Filter\": [\n 0,\n 1,\n \"انگشتر\"\n ]\n}\n```" + } + } + }, + "/DoListAsnad": { + "post": { + "summary": "DoListAsnad", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListAsnad", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "1892": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "Count": { + "type": "string" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "null" + }, + "Tarikh_Cheq": { + "type": "null" + }, + "Sh_Cheq": { + "type": "null" + }, + "Sh_Posht_Check": { + "type": "null" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "null" + }, + "Sharh1": { + "type": "null" + }, + "Sharh2": { + "type": "string" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + }, + "1893": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "Count": { + "type": "string" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "null" + }, + "Tarikh_Cheq": { + "type": "null" + }, + "Sh_Cheq": { + "type": "null" + }, + "Sh_Posht_Check": { + "type": "null" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "null" + }, + "Sharh1": { + "type": "null" + }, + "Sharh2": { + "type": "null" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + } + } + }, + "example": { + "1892": { + "ID": 1892, + "Radif": 1, + "Factor_Code": "17710212026072618003419736197", + "MCode": 1, + "Tarikh": "1405/05/04", + "Tarikh_Time": "18:00:36", + "ZamanSabt": "1405/05/04 18:00:36", + "ZamanEdit": null, + "NO": "ورود وجه نقد", + "Sh_Factor": 97, + "Vazn": "null", + "No_Kar": "null", + "Ayar": "null", + "Fi": "null", + "Mazaneh": "null", + "Count": "null", + "TabdilVazn": "null", + "Mali": 200000000, + "Name_Bank": null, + "Tarikh_Cheq": null, + "Sh_Cheq": null, + "Sh_Posht_Check": null, + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": null, + "Sharh1": null, + "Sharh2": "(از 498,010,000 مبلغ کل)", + "TasirBarMande": 1, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "IRR", + "Jens_Felez": 0, + "Seller": null, + "User": "مدير", + "isSanadMovaghat": false + }, + "1893": { + "ID": 1893, + "Radif": 1, + "Factor_Code": "86948212026072618003684340997", + "MCode": 1, + "Tarikh": "1405/05/04", + "Tarikh_Time": "18:00:45", + "ZamanSabt": "1405/05/04 18:00:45", + "ZamanEdit": null, + "NO": "ورود وجه نقد", + "Sh_Factor": 97, + "Vazn": "null", + "No_Kar": "null", + "Ayar": "null", + "Fi": "null", + "Mazaneh": "null", + "Count": "null", + "TabdilVazn": "null", + "Mali": 98010000, + "Name_Bank": null, + "Tarikh_Cheq": null, + "Sh_Cheq": null, + "Sh_Posht_Check": null, + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": null, + "Sharh1": null, + "Sharh2": null, + "TasirBarMande": 1, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "IRR", + "Jens_Felez": 0, + "Seller": null, + "User": "مدير", + "isSanadMovaghat": false + } + } + } + } + } + }, + "description": "نمایش لیست از تاریخ تا تاریخ مشخص و تعداد برگشتی و کد حساب مورد نظر\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Count_Last` | `2` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `AzTarikhShamsi` | `\"1405-05-02\"` |\n| 3 | `TaTarikhShamsi` | `\"1405-05-15\"` |\n| 4 | `FilterNoSanad` | `\"\"` |\n| 5 | `Mande_Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListAsnad": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoListAsnad": [ + 0, + 1, + "1405-05-02", + "1405-06-11", + "", + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListAsnad": [ + 0, + 1, + "1405-05-02", + "1405-06-11", + "", + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListAsnad\": [\n 0,\n 1,\n \"1405-05-02\",\n \"1405-06-11\",\n \"\",\n 0\n ]\n}\n```" + } + } + }, + "/DoListUpdatedAsnad": { + "post": { + "summary": "DoListUpdatedAsnad", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListUpdatedAsnad", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "1957": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "Count": { + "type": "string" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "string" + }, + "Tarikh_Cheq": { + "type": "string" + }, + "Sh_Cheq": { + "type": "string" + }, + "Sh_Posht_Check": { + "type": "null" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "string" + }, + "Sharh1": { + "type": "null" + }, + "Sharh2": { + "type": "null" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + }, + "1958": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "Count": { + "type": "string" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "string" + }, + "Tarikh_Cheq": { + "type": "string" + }, + "Sh_Cheq": { + "type": "string" + }, + "Sh_Posht_Check": { + "type": "string" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "null" + }, + "Sharh1": { + "type": "string" + }, + "Sharh2": { + "type": "null" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + }, + "1959": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "Count": { + "type": "string" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "null" + }, + "Tarikh_Cheq": { + "type": "null" + }, + "Sh_Cheq": { + "type": "null" + }, + "Sh_Posht_Check": { + "type": "null" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "null" + }, + "Sharh1": { + "type": "string" + }, + "Sharh2": { + "type": "null" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + }, + "1960": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "integer" + }, + "Count": { + "type": "integer" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "null" + }, + "Tarikh_Cheq": { + "type": "null" + }, + "Sh_Cheq": { + "type": "null" + }, + "Sh_Posht_Check": { + "type": "null" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "null" + }, + "Sharh1": { + "type": "string" + }, + "Sharh2": { + "type": "null" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + }, + "1961": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Radif": { + "type": "integer" + }, + "Factor_Code": { + "type": "string" + }, + "MCode": { + "type": "integer" + }, + "Tarikh": { + "type": "string" + }, + "Tarikh_Time": { + "type": "string" + }, + "ZamanSabt": { + "type": "string" + }, + "ZamanEdit": { + "type": "null" + }, + "NO": { + "type": "string" + }, + "Sh_Factor": { + "type": "integer" + }, + "Vazn": { + "type": "string" + }, + "No_Kar": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Fi": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "Count": { + "type": "string" + }, + "TabdilVazn": { + "type": "string" + }, + "Mali": { + "type": "integer" + }, + "Name_Bank": { + "type": "null" + }, + "Tarikh_Cheq": { + "type": "null" + }, + "Sh_Cheq": { + "type": "null" + }, + "Sh_Posht_Check": { + "type": "null" + }, + "Operation_Date": { + "type": "null" + }, + "Sh_Sharti": { + "type": "null" + }, + "Name_az": { + "type": "null" + }, + "Baabat": { + "type": "null" + }, + "Sharh1": { + "type": "null" + }, + "Sharh2": { + "type": "null" + }, + "TasirBarMande": { + "type": "integer" + }, + "TahesabVazni": { + "type": "integer" + }, + "TahesabMali": { + "type": "integer" + }, + "Arz": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "Seller": { + "type": "null" + }, + "User": { + "type": "string" + }, + "isSanadMovaghat": { + "type": "boolean" + } + } + } + } + }, + "example": { + "1957": { + "ID": 1957, + "Radif": 1, + "Factor_Code": "00730339120260805163343589707151", + "MCode": 1, + "Tarikh": "1405/04/21", + "Tarikh_Time": "16:33:43", + "ZamanSabt": "1405/05/14 16:33:43", + "ZamanEdit": null, + "NO": "خروج چک(هزينه)", + "Sh_Factor": 151, + "Vazn": "null", + "No_Kar": "null", + "Ayar": "null", + "Fi": "null", + "Mazaneh": "null", + "Count": "null", + "TabdilVazn": "null", + "Mali": -1000000, + "Name_Bank": "mellat", + "Tarikh_Cheq": "1405/04/20", + "Sh_Cheq": "100", + "Sh_Posht_Check": null, + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": "ABZAR", + "Sharh1": null, + "Sharh2": null, + "TasirBarMande": 0, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "IRR", + "Jens_Felez": 0, + "Seller": null, + "User": "APi", + "isSanadMovaghat": false + }, + "1958": { + "ID": 1958, + "Radif": 1, + "Factor_Code": "0018981120260805163348423880152", + "MCode": 1, + "Tarikh": "1405/04/21", + "Tarikh_Time": "16:33:48", + "ZamanSabt": "1405/05/14 16:33:48", + "ZamanEdit": null, + "NO": "ورود چک", + "Sh_Factor": 152, + "Vazn": "null", + "No_Kar": "null", + "Ayar": "null", + "Fi": "null", + "Mazaneh": "null", + "Count": "null", + "TabdilVazn": "null", + "Mali": 1000000, + "Name_Bank": "mellat", + "Tarikh_Cheq": "1405/04/20", + "Sh_Cheq": "100", + "Sh_Posht_Check": "8", + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": null, + "Sharh1": "sharh", + "Sharh2": null, + "TasirBarMande": 1, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "IRR", + "Jens_Felez": 0, + "Seller": null, + "User": "APi", + "isSanadMovaghat": false + }, + "1959": { + "ID": 1959, + "Radif": 1, + "Factor_Code": "00160235120260805163352731744153", + "MCode": 1, + "Tarikh": "1404/12/23", + "Tarikh_Time": "16:33:52", + "ZamanSabt": "1405/05/14 16:33:52", + "ZamanEdit": null, + "NO": "تخفيف [USD]", + "Sh_Factor": 153, + "Vazn": "null", + "No_Kar": "null", + "Ayar": "null", + "Fi": "null", + "Mazaneh": "null", + "Count": "null", + "TabdilVazn": "null", + "Mali": 1000000, + "Name_Bank": null, + "Tarikh_Cheq": null, + "Sh_Cheq": null, + "Sh_Posht_Check": null, + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": null, + "Sharh1": "sharh", + "Sharh2": null, + "TasirBarMande": 1, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "USD", + "Jens_Felez": 0, + "Seller": null, + "User": "APi", + "isSanadMovaghat": false + }, + "1960": { + "ID": 1960, + "Radif": 1, + "Factor_Code": "007245121202608051633573345911", + "MCode": 1, + "Tarikh": "1405/03/03", + "Tarikh_Time": "16:33:57", + "ZamanSabt": "1405/05/14 16:33:57", + "ZamanEdit": null, + "NO": "فروش ارز [USD]", + "Sh_Factor": 1, + "Vazn": "null", + "No_Kar": "USD", + "Ayar": "null", + "Fi": "null", + "Mazaneh": 1700000, + "Count": 1000, + "TabdilVazn": "null", + "Mali": -1700000000, + "Name_Bank": null, + "Tarikh_Cheq": null, + "Sh_Cheq": null, + "Sh_Posht_Check": null, + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": null, + "Sharh1": "sharh", + "Sharh2": null, + "TasirBarMande": 1, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "EURO", + "Jens_Felez": 0, + "Seller": null, + "User": "APi", + "isSanadMovaghat": false + }, + "1961": { + "ID": 1961, + "Radif": 2, + "Factor_Code": "007245121202608051633573345911", + "MCode": 1, + "Tarikh": "1405/03/03", + "Tarikh_Time": "16:33:57", + "ZamanSabt": "1405/05/14 16:33:57", + "ZamanEdit": null, + "NO": "بدهي [USD]", + "Sh_Factor": 1, + "Vazn": "null", + "No_Kar": "null", + "Ayar": "null", + "Fi": "null", + "Mazaneh": "null", + "Count": "null", + "TabdilVazn": "null", + "Mali": 1000, + "Name_Bank": null, + "Tarikh_Cheq": null, + "Sh_Cheq": null, + "Sh_Posht_Check": null, + "Operation_Date": null, + "Sh_Sharti": null, + "Name_az": null, + "Baabat": null, + "Sharh1": null, + "Sharh2": null, + "TasirBarMande": 1, + "TahesabVazni": 0, + "TahesabMali": 0, + "Arz": "USD", + "Jens_Felez": 0, + "Seller": null, + "User": "APi", + "isSanadMovaghat": false + } + } + } + } + } + }, + "description": "نمایش لیست اسناد بر اساس زمان ثبت یا ویرایش\n\nبرای بدست آودن لیست تغییرات جدید اسناد بر اساس زمان\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Count_Last` | `5` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListUpdatedAsnad": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoListUpdatedAsnad": [ + 5 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListUpdatedAsnad": [ + 5 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListUpdatedAsnad\": [\n 5\n ]\n}\n```" + } + } + }, + "/DoListEtiket": { + "post": { + "summary": "DoListEtiket", + "tags": [ + "List" + ], + "responses": { + "200": { + "description": "DoListEtiket", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "100": { + "type": "object", + "properties": { + "ID": { + "type": "integer" + }, + "Code": { + "type": "string" + }, + "Code_Kar": { + "type": "string" + }, + "Size": { + "type": "string" + }, + "Color": { + "type": "string" + }, + "Group": { + "type": "string" + }, + "Vitrin": { + "type": "string" + }, + "Ayar": { + "type": "string" + }, + "Sharh": { + "type": "string" + }, + "Name": { + "type": "string" + }, + "Vazn": { + "type": "string" + }, + "IsMojood": { + "type": "string" + }, + "OnlinePrice": { + "type": "string" + }, + "DarsadVaznMaye": { + "type": "string" + }, + "DarsadVaznForoosh": { + "type": "string" + }, + "Jens_Felez": { + "type": "integer" + }, + "LastUpdate": { + "type": "string" + }, + "No_Etiket": { + "type": "integer" + }, + "No_Ojrat": { + "type": "integer" + }, + "RFID": { + "type": "string" + }, + "MazaneDarVazn": { + "type": "string" + }, + "Ojrat_Maye": { + "type": "integer" + }, + "Ojrat_Foroosh": { + "type": "integer" + }, + "DarsadSood": { + "type": "string" + }, + "Sood": { + "type": "string" + }, + "DarsadVAT": { + "type": "string" + }, + "VAT": { + "type": "string" + }, + "PoolSang": { + "type": "string" + }, + "VaznKolSang": { + "type": "string" + }, + "DarsadVazn": { + "type": "string" + }, + "Mazaneh": { + "type": "string" + }, + "MazanehGetTime": { + "type": "string" + }, + "OjratDarVazn": { + "type": "string" + }, + "Base64Photo": { + "type": "string" + }, + "PictureFileName": { + "type": "string" + } + } + } + } + }, + "example": { + "100": { + "ID": 82, + "Code": "100", + "Code_Kar": "12345678912345", + "Size": "", + "Color": "", + "Group": "0", + "Vitrin": "", + "Ayar": "750", + "Sharh": "", + "Name": "اتگشتر", + "Vazn": "10.500", + "IsMojood": "1", + "OnlinePrice": "2549875282/4", + "DarsadVaznMaye": "0", + "DarsadVaznForoosh": "20", + "Jens_Felez": 0, + "LastUpdate": "1405/05/11", + "No_Etiket": 1, + "No_Ojrat": 1, + "RFID": "", + "MazaneDarVazn": "1938426000", + "Ojrat_Maye": 0, + "Ojrat_Foroosh": 5000000, + "DarsadSood": "7", + "Sood": "163177784", + "DarsadVAT": "10", + "VAT": "55586298/4", + "PoolSang": "0", + "VaznKolSang": "0.000 ct", + "DarsadVazn": "20.000", + "Mazaneh": "184612000", + "MazanehGetTime": "2026/08/05 16:34:02", + "OjratDarVazn": "392685200", + "Base64Photo": "", + "PictureFileName": "Etiket-100(8246606) Camera.jpg" + } + } + } + } + } + }, + "description": "نمایش لیست اتیکت ها از شناسه کار تا شناسه کار\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `From_Code` | `1` |\n| 1 | `To_Code` | `500` |\n| 2 | `WithPhoto_1_0` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListEtiket": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoListEtiket": [ + 100, + 100, + 1 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListEtiket": [ + 100, + 100, + 1 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListEtiket\": [\n 100,\n 100,\n 1\n ]\n}\n```" + } + } + }, + "/GetMandeHesabByGID": { + "post": { + "summary": "GetMandeHesabByGID", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "GetMandeHesabByGID", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "MandeHesab": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Code": { + "type": "string" + }, + "MandeyeMali": { + "type": "string" + }, + "MandeyeVazniNoghre": { + "type": "string" + }, + "MandeyeVazni": { + "type": "string" + }, + "MandeMenhayeSeke": { + "type": "string" + }, + "Seke_يک گرم": { + "type": "string" + }, + "Seke_shemshname": { + "type": "string" + }, + "Seke_sekehname": { + "type": "string" + }, + "Seke_azadi": { + "type": "string" + }, + "MandeyeArz_USD": { + "type": "string" + }, + "MandeyeArz_EURO": { + "type": "string" + }, + "MandeyeArz_DRH": { + "type": "string" + }, + "MandeyeArz_0": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Value": { + "type": "string" + }, + "Value1": { + "type": "null" + }, + "Value2": { + "type": "null" + }, + "Value3": { + "type": "null" + }, + "Value4": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "example": { + "MandeHesab": [ + { + "Code": "1", + "MandeyeMali": "-114419230", + "MandeyeVazniNoghre": "1511.86", + "MandeyeVazni": "-156.43", + "MandeMenhayeSeke": "-177.28", + "Seke_يک گرم": "1", + "Seke_shemshname": "-20", + "Seke_sekehname": "20", + "Seke_azadi": "2", + "MandeyeArz_USD": "62000", + "MandeyeArz_EURO": "-3400000000", + "MandeyeArz_DRH": "-400.36", + "MandeyeArz_0": "2000", + "details": [ + { + "Name": "مانده مالی", + "Value": "-114419230", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "-114419230" + }, + { + "Name": "مانده نقره", + "Value": "1511.86", + "Value1": "1511.86", + "Value2": null, + "Value3": null, + "Value4": null + }, + { + "Name": "مانده طلا", + "Value": "-156.43", + "Value1": "-156.43", + "Value2": null, + "Value3": null, + "Value4": null + }, + { + "Name": "مانده منهای سکه", + "Value": "-177.28", + "Value1": "-177.28", + "Value2": null, + "Value3": null, + "Value4": null + }, + { + "Name": "(سکه) يک گرم", + "Value": "1", + "Value1": "1.33", + "Value2": "1", + "Value3": null, + "Value4": null + }, + { + "Name": "(سکه) shemshname", + "Value": "-20", + "Value1": "-97.44", + "Value2": "-20", + "Value3": null, + "Value4": null + }, + { + "Name": "(سکه) sekehname", + "Value": "20", + "Value1": "97.44", + "Value2": "20", + "Value3": null, + "Value4": null + }, + { + "Name": "(سکه) azadi", + "Value": "2", + "Value1": "19.52", + "Value2": "2", + "Value3": null, + "Value4": null + }, + { + "Name": "مانده حساب (USD)", + "Value": "62000", + "Value1": null, + "Value2": null, + "Value3": "62000", + "Value4": null + }, + { + "Name": "مانده حساب (EURO)", + "Value": "-3400000000", + "Value1": null, + "Value2": null, + "Value3": "-3400000000", + "Value4": null + }, + { + "Name": "مانده حساب (DRH)", + "Value": "-400.36", + "Value1": null, + "Value2": null, + "Value3": "-400.36", + "Value4": null + }, + { + "Name": "مانده حساب (0)", + "Value": "2000", + "Value1": null, + "Value2": null, + "Value3": "2000", + "Value4": null + } + ] + }, + { + "Code": "6", + "MandeyeVazni": "54.34", + "details": [ + { + "Name": "مانده طلا", + "Value": "54.34", + "Value1": "54.34", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "7", + "MandeyeVazni": "148.56", + "details": [ + { + "Name": "مانده طلا", + "Value": "148.56", + "Value1": "148.56", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "8", + "MandeyeVazni": "32.81", + "details": [ + { + "Name": "مانده طلا", + "Value": "32.81", + "Value1": "32.81", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "9", + "MandeyeMali": "75000000", + "MandeyeVazni": "3.7", + "details": [ + { + "Name": "مانده مالی", + "Value": "75000000", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "75000000" + }, + { + "Name": "مانده طلا", + "Value": "3.7", + "Value1": "3.7", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "10", + "MandeyeMali": "-11495900000", + "MandeyeVazni": "455.26", + "details": [ + { + "Name": "مانده مالی", + "Value": "-11495900000", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "-11495900000" + }, + { + "Name": "مانده طلا", + "Value": "455.26", + "Value1": "455.26", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "11", + "MandeyeMali": "888840000", + "MandeyeVazni": "-7.94", + "details": [ + { + "Name": "مانده مالی", + "Value": "888840000", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "888840000" + }, + { + "Name": "مانده طلا", + "Value": "-7.94", + "Value1": "-7.94", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "12" + }, + { + "Code": "13" + }, + { + "Code": "14", + "MandeyeVazni": "13.09", + "details": [ + { + "Name": "مانده طلا", + "Value": "13.09", + "Value1": "13.09", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "15", + "MandeyeVazni": "3.79", + "details": [ + { + "Name": "مانده طلا", + "Value": "3.79", + "Value1": "3.79", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "16", + "MandeyeMali": "-207000000", + "details": [ + { + "Name": "مانده مالی", + "Value": "-207000000", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "-207000000" + } + ] + }, + { + "Code": "17", + "MandeyeMali": "-200000000", + "MandeyeVazni": "8.45", + "details": [ + { + "Name": "مانده مالی", + "Value": "-200000000", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "-200000000" + }, + { + "Name": "مانده طلا", + "Value": "8.45", + "Value1": "8.45", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "18", + "MandeyeVazni": "22.45", + "details": [ + { + "Name": "مانده طلا", + "Value": "22.45", + "Value1": "22.45", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "19", + "MandeyeVazni": "3.88", + "details": [ + { + "Name": "مانده طلا", + "Value": "3.88", + "Value1": "3.88", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + }, + { + "Code": "23", + "MandeyeVazni": "0.45", + "details": [ + { + "Name": "مانده طلا", + "Value": "0.45", + "Value1": "0.45", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + } + ] + } + } + } + } + }, + "description": "دریافت آخرین مانده حساب و تفکیک ته حساب بر اساس کد گروه حساب\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `GID_List` | `1` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "GetMandeHesabByGID": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "GetMandeHesabByGID": [ + 1 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "GetMandeHesabByGID": [ + 1 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"GetMandeHesabByGID\": [\n 1\n ]\n}\n```" + } + } + }, + "/GetMandeHesabByCode": { + "post": { + "summary": "GetMandeHesabByCode", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "GetMandeHesabByCode", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "MandeHesab": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Code": { + "type": "string" + }, + "MandeyeMali": { + "type": "string" + }, + "MandeyeVazniNoghre": { + "type": "string" + }, + "MandeyeVazni": { + "type": "string" + }, + "MandeMenhayeSeke": { + "type": "string" + }, + "Seke_يک گرم": { + "type": "string" + }, + "Seke_azadi": { + "type": "string" + }, + "MandeyeArz_USD": { + "type": "string" + }, + "MandeyeArz_DRH": { + "type": "string" + }, + "MandeyeArz_0": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Value": { + "type": "string" + }, + "Value1": { + "type": "null" + }, + "Value2": { + "type": "null" + }, + "Value3": { + "type": "null" + }, + "Value4": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "example": { + "MandeHesab": [ + { + "Code": "1", + "MandeyeMali": "-238999230", + "MandeyeVazniNoghre": "1511.86", + "MandeyeVazni": "-177.431", + "MandeMenhayeSeke": "-198.276", + "Seke_يک گرم": "1", + "Seke_azadi": "2", + "MandeyeArz_USD": "60000", + "MandeyeArz_DRH": "-400.36", + "MandeyeArz_0": "2000", + "details": [ + { + "Name": "مانده مالی", + "Value": "-238999230", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "-238999230" + }, + { + "Name": "مانده نقره", + "Value": "1511.86", + "Value1": "1511.86", + "Value2": null, + "Value3": null, + "Value4": null + }, + { + "Name": "مانده طلا", + "Value": "-177.431", + "Value1": "-177.431", + "Value2": null, + "Value3": null, + "Value4": null + }, + { + "Name": "مانده منهای سکه", + "Value": "-198.276", + "Value1": "-198.276", + "Value2": null, + "Value3": null, + "Value4": null + }, + { + "Name": "(سکه) يک گرم", + "Value": "1", + "Value1": "1.333", + "Value2": "1", + "Value3": null, + "Value4": null + }, + { + "Name": "(سکه) azadi", + "Value": "2", + "Value1": "19.512", + "Value2": "2", + "Value3": null, + "Value4": null + }, + { + "Name": "مانده حساب (USD)", + "Value": "60000", + "Value1": null, + "Value2": null, + "Value3": "60000", + "Value4": null + }, + { + "Name": "مانده حساب (DRH)", + "Value": "-400.36", + "Value1": null, + "Value2": null, + "Value3": "-400.36", + "Value4": null + }, + { + "Name": "مانده حساب (0)", + "Value": "2000", + "Value1": null, + "Value2": null, + "Value3": "2000", + "Value4": null + } + ] + } + ] + } + } + } + } + }, + "description": "دریافت مانده حساب بر اساس کد حساب\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Moshtari_Code_List` | `\"1\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "getmandehesabbycode": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "getmandehesabbycode": [ + "1" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "getmandehesabbycode": [ + "1" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"getmandehesabbycode\": [\n \"1\"\n ]\n}\n```" + } + } + }, + "/GetMandeHesabByTarikh": { + "post": { + "summary": "GetMandeHesabByTarikh", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "GetMandeHesabByTarikh", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Code": { + "type": "string" + }, + "MandeyeMali": { + "type": "string" + }, + "MandeyeVazni": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string" + }, + "Value": { + "type": "string" + }, + "Value1": { + "type": "null" + }, + "Value2": { + "type": "null" + }, + "Value3": { + "type": "null" + }, + "Value4": { + "type": "string" + } + } + } + } + } + }, + "example": { + "Code": "1", + "MandeyeMali": "100000", + "MandeyeVazni": "1.25", + "details": [ + { + "Name": "مانده مالی", + "Value": "100000", + "Value1": null, + "Value2": null, + "Value3": null, + "Value4": "100000" + }, + { + "Name": "مانده طلا", + "Value": "1.25", + "Value1": "1.25", + "Value2": null, + "Value3": null, + "Value4": null + } + ] + } + } + } + } + }, + "description": "دریافت مانده حساب بر اساس کد حساب و تا تاریخ مشخص\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `ثابت` | `\"1\"` |\n| 1 | `1403-08-06` | `\"1404-12-12\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "GetMandeHesabByTarikh": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "GetMandeHesabByTarikh": [ + "1", + "1404-12-12" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "GetMandeHesabByTarikh": [ + "1", + "1404-12-12" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"GetMandeHesabByTarikh\": [\n \"1\",\n \"1404-12-12\"\n ]\n}\n```" + } + } + }, + "/DoNewMoshtari": { + "post": { + "summary": "DoNewMoshtari", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "DoNewMoshtari", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "integer" + } + } + }, + "example": { + "OK": 35 + } + } + } + } + }, + "description": "ثبت حساب یا مشتری جدید\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Moshtari_Name` | `\"Moshtari1\"` |\n| 1 | `GroupName` | `\"Tahesab\"` |\n| 2 | `Tel` | `\"0912123456\"` |\n| 3 | `Address` | `\"kh Vila\"` |\n| 4 | `CodeMeli` | `\"00112312311\"` |\n| 5 | `Tarikh_Tavalod` | `\"1366-12-04\"` |\n| 6 | `Moaref` | `\"ALI\"` |\n| 7 | `Code_Moaref` | `\"1\"` |\n| 8 | `Moshtari_Code` | `-1` |\n| 9 | `Jens_Felez` | `2` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewMoshtari": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "DoNewMoshtari": [ + "Moshtari1", + "Tahesab", + "0912123456", + "kh Vila", + "00112312311", + "1366-12-04", + "ALI", + "1", + -1, + 2 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewMoshtari": [ + "Moshtari1", + "Tahesab", + "0912123456", + "kh Vila", + "00112312311", + "1366-12-04", + "ALI", + "1", + -1, + 2 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewMoshtari\": [\n \"Moshtari1\",\n \"Tahesab\",\n \"0912123456\",\n \"kh Vila\",\n \"00112312311\",\n \"1366-12-04\",\n \"ALI\",\n \"1\",\n -1,\n 2\n ]\n}\n```" + } + } + }, + "/DoEditMoshtari": { + "post": { + "summary": "DoEditMoshtari", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "DoEditMoshtari", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Edited": { + "type": "integer" + } + } + }, + "example": { + "Edited": 1 + } + } + } + } + }, + "description": "ویرایش اطلاعات حساب یا مشتری\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Moshtari_Name` | `\"Masoud\"` |\n| 1 | `GroupName` | `\"بنکدار\"` |\n| 2 | `Tel` | `\"9121234567\"` |\n| 3 | `Address` | `\"آدرس جدید\"` |\n| 4 | `CodeMeli` | `\"-1\"` |\n| 5 | `Tarikh_Tavalod` | `\"1360-09-30\"` |\n| 6 | `Moaref` | `\"-1\"` |\n| 7 | `Code_Moaref` | `\"-1\"` |\n| 8 | `Moshtari_Code` | `1` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoEditMoshtari": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "DoEditMoshtari": [ + "Masoud", + "بنکدار", + "9121234567", + "آدرس جدید", + "-1", + "1360-09-30", + "-1", + "-1", + 1 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoEditMoshtari": [ + "Masoud", + "بنکدار", + "9121234567", + "آدرس جدید", + "-1", + "1360-09-30", + "-1", + "-1", + 1 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoEditMoshtari\": [\n \"Masoud\",\n \"بنکدار\",\n \"9121234567\",\n \"آدرس جدید\",\n \"-1\",\n \"1360-09-30\",\n \"-1\",\n \"-1\",\n 1\n ]\n}\n```" + } + } + }, + "/DoListMoshtari-ByCode": { + "post": { + "summary": "DoListMoshtari (ByCode)", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "DoListMoshtari (ByCode)", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "1": { + "type": "object", + "properties": { + "Code": { + "type": "integer" + }, + "Name": { + "type": "string" + }, + "GID": { + "type": "string" + }, + "GoroupName": { + "type": "string" + }, + "Mobile": { + "type": "string" + }, + "CodeMelli": { + "type": "string" + }, + "Address": { + "type": "string" + }, + "City": { + "type": "string" + }, + "Rasteh": { + "type": "integer" + }, + "BDate": { + "type": "string" + } + } + }, + "2": { + "type": "object", + "properties": { + "Code": { + "type": "integer" + }, + "Name": { + "type": "string" + }, + "GID": { + "type": "string" + }, + "GoroupName": { + "type": "string" + }, + "Mobile": { + "type": "string" + }, + "CodeMelli": { + "type": "string" + }, + "Address": { + "type": "string" + }, + "City": { + "type": "string" + }, + "Rasteh": { + "type": "integer" + }, + "BDate": { + "type": "null" + } + } + } + } + }, + "example": { + "1": { + "Code": 1, + "Name": "مشتري اول", + "GID": "1", + "GoroupName": "بنکداران (بازار)", + "Mobile": "9121790179", + "CodeMelli": "", + "Address": "آدرس جدید", + "City": "", + "Rasteh": 0, + "BDate": "1360/09/30" + }, + "2": { + "Code": 2, + "Name": "مشتري دوم", + "GID": "2", + "GoroupName": "همکار", + "Mobile": "09121234567", + "CodeMelli": "", + "Address": "", + "City": "", + "Rasteh": 0, + "BDate": null + } + } + } + } + } + }, + "description": "لیست حساب/مشتری ها با فیلتر از کد تا کد حساب\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `From_Code` | `1` |\n| 1 | `To_Code` | `2` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Dolistmoshtari": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "Dolistmoshtari": [ + 1, + 1 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "Dolistmoshtari": [ + 1, + 1 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"Dolistmoshtari\": [\n 1,\n 1\n ]\n}\n```" + } + } + }, + "/DoListMoshtari-ByPhone": { + "post": { + "summary": "DoListMoshtari (ByPhone)", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "404": { + "description": "DoListMoshtari (ByPhone)", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "هیچ رکوردی یافت نشد.", + "Command": "GET", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "31", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "21940", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "63815", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:06:10", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "97", + "Count_UnSuccess_Request": "19", + "Last_Request": "2026-08-05 16:07:41" + } + } + } + } + }, + "description": "لیست حساب/مشتری ها با فیلتر بر اساس شماره موبایل\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Code_List` | `9121790179` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListMoshtari": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoListMoshtari": [ + 9121790179 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListMoshtari": [ + 9121790179 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListMoshtari\": [\n 9121790179\n ]\n}\n```" + } + } + }, + "/DoListMoshtari-ByName": { + "post": { + "summary": "DoListMoshtari (ByName)", + "tags": [ + "Hesab-Moshtari" + ], + "responses": { + "200": { + "description": "DoListMoshtari (ByName)", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "1": { + "type": "object", + "properties": { + "Code": { + "type": "integer" + }, + "Name": { + "type": "string" + }, + "GID": { + "type": "string" + }, + "GoroupName": { + "type": "string" + }, + "Mobile": { + "type": "string" + }, + "CodeMelli": { + "type": "string" + }, + "Address": { + "type": "string" + }, + "City": { + "type": "string" + }, + "Rasteh": { + "type": "integer" + }, + "BDate": { + "type": "string" + } + } + } + } + }, + "example": { + "1": { + "Code": 1, + "Name": "masoud", + "GID": "0", + "GoroupName": "بنکدار", + "Mobile": "9121234567", + "CodeMelli": "", + "Address": "آدرس جدید", + "City": "", + "Rasteh": 0, + "BDate": "1360/09/30" + } + } + } + } + } + }, + "description": "لیست حساب/مشتری ها با فیلتر بر اساس نام\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n|---:|---|---|\n| 0 | `Code_List` | `\"masoud\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoListMoshtari": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "example": { + "DoListMoshtari": [ + "masoud" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoListMoshtari": [ + "masoud" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoListMoshtari\": [\n \"masoud\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadSharh": { + "post": { + "summary": "DoNewSanadSharh", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadSharh", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "009527851202608051608000522171", + "Factor_Code": "009527851202608051608000522171", + "Sh_factor": "1", + "Factor_Number": "1", + "ID": 1933 + } + } + } + } + }, + "description": "ثبت سند شرح (این سند تاثیری در وزن و مبلغ ندارد و صرفا یک یادداشت هست)\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `0` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `11` |\n| 6 | `Shamsi_Day` | `9` |\n| 7 | `ثابت` | `0` |\n| 8 | `ثابت` | `0` |\n| 9 | `ثابت` | `\"\"` |\n| 10 | `ثابت` | `\"\"` |\n| 11 | `ثابت` | `0` |\n| 12 | `ثابت` | `0` |\n| 13 | `Sharh` | `\"Sharh\"` |\n| 14 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 15 | `ثابت` | `0` |\n| 16 | `MultiRadif` | `-1` |\n| 17 | `ثابت` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadSharh": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadSharh": [ + 1, + 1, + 1, + 1, + 1405, + 5, + 19, + 0, + 0, + "", + "", + 0, + 0, + "Sharh", + "123456891234d567891234561", + 0, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadSharh": [ + 1, + 1, + 1, + 1, + 1405, + 5, + 19, + 0, + 0, + "", + "", + 0, + 0, + "Sharh", + "123456891234d567891234561", + 0, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadSharh\": [\n 1,\n 1,\n 1,\n 1,\n 1405,\n 5,\n 19,\n 0,\n 0,\n \"\",\n \"\",\n 0,\n 0,\n \"Sharh\",\n \"123456891234d567891234561\",\n 0,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadVKHGOLD": { + "post": { + "summary": "DoNewSanadVKHGOLD", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadVKHGOLD", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00725682120260805161110772530135", + "Factor_Code": "00725682120260805161110772530135", + "Sh_factor": "135", + "Factor_Number": "135", + "ID": 1934 + } + } + } + } + }, + "description": "ثبت سند ورود و خروج آبشده و متفرقه\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1405` |\n| 5 | `Shamsi_Month` | `4` |\n| 6 | `Shamsi_Day` | `28` |\n| 7 | `Vazn` | `1.25` |\n| 8 | `Ayar` | `750` |\n| 9 | `Ang_Number` | `1` |\n| 10 | `Name_az` | `\"Az\"` |\n| 11 | `IsVoroodOrKhorooj_0_1` | `1` |\n| 12 | `IsMotefaregheOrAbshode_0_1` | `1` |\n| 13 | `Sharh` | `\"Sharh\"` |\n| 14 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 15 | `HavalehBe_Mcode` | `-1` |\n| 16 | `MultiRadif` | `-1` |\n| 17 | `Jens_Felez` | `0` |\n| 18 | `IsSharti` | `true` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadVKHGOLD": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadVKHGOLD": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 1.25, + 750, + 1, + "Az", + 1, + 1, + "Sharh", + "12345678912345678912345678", + -1, + -1, + 0, + true + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadVKHGOLD": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 1.25, + 750, + 1, + "Az", + 1, + 1, + "Sharh", + "12345678912345678912345678", + -1, + -1, + 0, + true + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadVKHGOLD\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 1.25,\n 750,\n 1,\n \"Az\",\n 1,\n 1,\n \"Sharh\",\n \"12345678912345678912345678\",\n -1,\n -1,\n 0,\n true\n ]\n}\n```" + } + } + }, + "/DoNewSanadBuySaleGOLD": { + "post": { + "summary": "DoNewSanadBuySaleGOLD", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadBuySaleGOLD", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + }, + "OK_HAVALEH": { + "type": "string" + }, + "Sh_factor_Havaleh": { + "type": "string" + }, + "Havaleh_ID": { + "type": "string" + } + } + }, + "example": { + "OK": "00665412120260805163011592596136", + "Factor_Code": "00665412120260805163011592596136", + "Sh_factor": "136", + "Factor_Number": "136", + "ID": 1935, + "OK_HAVALEH": "0066541212026080516301159259613619356099", + "Sh_factor_Havaleh": "60", + "Havaleh_ID": "1935" + } + } + } + } + }, + "description": "ثبت سند خرید و فروش آبشده و متفرقه بدون تسویه\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1405` |\n| 5 | `Shamsi_Month` | `4` |\n| 6 | `Shamsi_Day` | `27` |\n| 7 | `Vazn` | `0.01` |\n| 8 | `Ayar` | `750` |\n| 9 | `ثابت` | `123456` |\n| 10 | `ثابت` | `\"Reygiri\"` |\n| 11 | `BuyOrSale_0_1` | `0` |\n| 12 | `Mazaneh` | `4600000` |\n| 13 | `MazanehIsMesghalOrGeram_0_1` | `0` |\n| 14 | `IsMotefaregheOrAbshode_0_1` | `1` |\n| 15 | `MablaghKol` | `10000000` |\n| 16 | `Sharh` | `\"Sharh\"` |\n| 17 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 18 | `HavalehBe_Mcode` | `2` |\n| 19 | `MultiRadif` | `-1` |\n| 20 | `Jens_Felez` | `0` |\n| 21 | `Zaman_Tasvie` | `\"1404-07-13\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadBuySaleGOLD": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadBuySaleGOLD": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 0.01, + 750, + 123456, + "Reygiri", + 0, + 4600000, + 0, + 1, + 10000000, + "Sharh", + "1234567891234567891234567", + 2, + -1, + 0, + "1404-07-13" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadBuySaleGOLD": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 0.01, + 750, + 123456, + "Reygiri", + 0, + 4600000, + 0, + 1, + 10000000, + "Sharh", + "1234567891234567891234567", + 2, + -1, + 0, + "1404-07-13" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadBuySaleGOLD\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 0.01,\n 750,\n 123456,\n \"Reygiri\",\n 0,\n 4600000,\n 0,\n 1,\n 10000000,\n \"Sharh\",\n \"1234567891234567891234567\",\n 2,\n -1,\n 0,\n \"1404-07-13\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadVKHSEKEH": { + "post": { + "summary": "DoNewSanadVKHSEKEH", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadVKHSEKEH", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00341293120260805163029604434137", + "Factor_Code": "00341293120260805163029604434137", + "Sh_factor": "137", + "Factor_Number": "137", + "ID": 1937 + } + } + } + } + }, + "description": "ثبت سند ورود و خروج سکه\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `11` |\n| 6 | `Shamsi_Day` | `12` |\n| 7 | `Vazn` | `4.06` |\n| 8 | `Ayar` | `900` |\n| 9 | `Count` | `10` |\n| 10 | `Name_Sekeh` | `\"SEKEHName\"` |\n| 11 | `IsVoroodOrKhorooj_0_1` | `1` |\n| 12 | `Sharh` | `\"Sharh\"` |\n| 13 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 14 | `ثابت` | `-1` |\n| 15 | `MultiRadif` | `-1` |\n| 16 | `Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadVKHSEKEH": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadVKHSEKEH": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "SEKEHName", + 1, + "Sharh", + "123456789123456789123456", + -1, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadVKHSEKEH": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "SEKEHName", + 1, + "Sharh", + "123456789123456789123456", + -1, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadVKHSEKEH\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 4.06,\n 900,\n 10,\n \"SEKEHName\",\n 1,\n \"Sharh\",\n \"123456789123456789123456\",\n -1,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadTBSEKEH": { + "post": { + "summary": "DoNewSanadTBSEKEH", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadTBSEKEH", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + }, + "OK_HAVALEH": { + "type": "string" + }, + "Sh_factor_Havaleh": { + "type": "string" + }, + "Havaleh_ID": { + "type": "string" + } + } + }, + "example": { + "OK": "00898809120260805163033555566138", + "Factor_Code": "00898809120260805163033555566138", + "Sh_factor": "138", + "Factor_Number": "138", + "ID": 1938, + "OK_HAVALEH": "0089880912026080516303355556613819386199", + "Sh_factor_Havaleh": "61", + "Havaleh_ID": "1938" + } + } + } + } + }, + "description": "ثبت سند طلب و بدهی سکه\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `12` |\n| 6 | `Shamsi_Day` | `23` |\n| 7 | `Vazn` | `4.06` |\n| 8 | `Ayar` | `900` |\n| 9 | `Count` | `10` |\n| 10 | `Name_Sekeh` | `\"SEKEHName\"` |\n| 11 | `Is_BedehieMa_TalabeMa_0_1` | `0` |\n| 12 | `Sharh` | `\"Sharh\"` |\n| 13 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 14 | `HavalehBe_Mcode` | `2` |\n| 15 | `MultiRadif` | `-1` |\n| 16 | `Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadTBSEKEH": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadTBSEKEH": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "SEKEHName", + 0, + "Sharh", + "12345678912345678912345", + 2, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadTBSEKEH": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "SEKEHName", + 0, + "Sharh", + "12345678912345678912345", + 2, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadTBSEKEH\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 4.06,\n 900,\n 10,\n \"SEKEHName\",\n 0,\n \"Sharh\",\n \"12345678912345678912345\",\n 2,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadVKHShemsh": { + "post": { + "summary": "DoNewSanadVKHShemsh", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadVKHShemsh", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00433789120260805163038781539139", + "Factor_Code": "00433789120260805163038781539139", + "Sh_factor": "139", + "Factor_Number": "139", + "ID": 1940 + } + } + } + } + }, + "description": "ثبت سند ورود و خروج شمش\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `11` |\n| 6 | `Shamsi_Day` | `12` |\n| 7 | `Vazn` | `4.06` |\n| 8 | `Ayar` | `900` |\n| 9 | `Count` | `10` |\n| 10 | `Name_Shemsh` | `\"ShemshName\"` |\n| 11 | `IsVoroodOrKhorooj_0_1` | `1` |\n| 12 | `Sharh` | `\"Sharh\"` |\n| 13 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 14 | `ثابت` | `-1` |\n| 15 | `MultiRadif` | `-1` |\n| 16 | `Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadVKHShemsh": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadVKHShemsh": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "ShemshName", + 1, + "Sharh", + "1234567891234567891234", + -1, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadVKHShemsh": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "ShemshName", + 1, + "Sharh", + "1234567891234567891234", + -1, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadVKHShemsh\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 4.06,\n 900,\n 10,\n \"ShemshName\",\n 1,\n \"Sharh\",\n \"1234567891234567891234\",\n -1,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadTBShemsh": { + "post": { + "summary": "DoNewSanadTBShemsh", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadTBShemsh", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + }, + "OK_HAVALEH": { + "type": "string" + }, + "Sh_factor_Havaleh": { + "type": "string" + }, + "Havaleh_ID": { + "type": "string" + } + } + }, + "example": { + "OK": "00440992120260805163109647378140", + "Factor_Code": "00440992120260805163109647378140", + "Sh_factor": "140", + "Factor_Number": "140", + "ID": 1941, + "OK_HAVALEH": "0044099212026080516310964737814019416299", + "Sh_factor_Havaleh": "62", + "Havaleh_ID": "1941" + } + } + } + } + }, + "description": "ثبت سند طلب و بدهی شمش\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `12` |\n| 6 | `Shamsi_Day` | `23` |\n| 7 | `Vazn` | `4.06` |\n| 8 | `Ayar` | `900` |\n| 9 | `Count` | `10` |\n| 10 | `Name_Shemsh` | `\"ShemshName\"` |\n| 11 | `IsVoroodOrKhorooj_0_1` | `1` |\n| 12 | `Sharh` | `\"Sharh\"` |\n| 13 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 14 | `HavalehBe_Mcode` | `2` |\n| 15 | `MultiRadif` | `-1` |\n| 16 | `Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadTBShemsh": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadTBShemsh": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "ShemshName", + 1, + "Sharh", + "123456789123456789123", + 2, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadTBShemsh": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "ShemshName", + 1, + "Sharh", + "123456789123456789123", + 2, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadTBShemsh\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 4.06,\n 900,\n 10,\n \"ShemshName\",\n 1,\n \"Sharh\",\n \"123456789123456789123\",\n 2,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadBuySaleSEKEH": { + "post": { + "summary": "DoNewSanadBuySaleSEKEH", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadBuySaleSEKEH", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00234112120260805163115497809141", + "Factor_Code": "00234112120260805163115497809141", + "Sh_factor": "141", + "Factor_Number": "141", + "ID": 1943 + } + } + } + } + }, + "description": "ثبت سند خرید و فروش سکه\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `12` |\n| 6 | `Shamsi_Day` | `23` |\n| 7 | `Vazn` | `4.06` |\n| 8 | `Ayar` | `900` |\n| 9 | `Count` | `10` |\n| 10 | `Name_Sekeh` | `\"SEKEHName\"` |\n| 11 | `BuyOrSale_0_1` | `1` |\n| 12 | `Mazaneh` | `10000` |\n| 13 | `MablaghKol` | `1000000` |\n| 14 | `Sharh` | `\"Sharh\"` |\n| 15 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 16 | `ثابت` | `-1` |\n| 17 | `MultiRadif` | `-1` |\n| 18 | `Jens_Felez` | `0` |\n| 19 | `ArzName` | `\"USD\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadBuySaleSEKEH": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadBuySaleSEKEH": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "SEKEHName", + 1, + 10000, + 1000000, + "Sharh", + "A123456789123456789123", + -1, + -1, + 0, + "USD" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadBuySaleSEKEH": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "SEKEHName", + 1, + 10000, + 1000000, + "Sharh", + "A123456789123456789123", + -1, + -1, + 0, + "USD" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadBuySaleSEKEH\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 4.06,\n 900,\n 10,\n \"SEKEHName\",\n 1,\n 10000,\n 1000000,\n \"Sharh\",\n \"A123456789123456789123\",\n -1,\n -1,\n 0,\n \"USD\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadBuySaleShemsh": { + "post": { + "summary": "DoNewSanadBuySaleShemsh", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadBuySaleShemsh", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00701794120260805163120280715142", + "Factor_Code": "00701794120260805163120280715142", + "Sh_factor": "142", + "Factor_Number": "142", + "ID": 1944 + } + } + } + } + }, + "description": "ثبت سند خرید و فروش شمش\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `12` |\n| 6 | `Shamsi_Day` | `23` |\n| 7 | `Vazn` | `4.06` |\n| 8 | `Ayar` | `900` |\n| 9 | `Count` | `10` |\n| 10 | `Name_Shemsh` | `\"ShemshName\"` |\n| 11 | `BuyOrSale_0_1` | `1` |\n| 12 | `Mazaneh` | `10000` |\n| 13 | `MablaghKol` | `1000000` |\n| 14 | `Sharh` | `\"Sharh\"` |\n| 15 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 16 | `ثابت` | `-1` |\n| 17 | `MultiRadif` | `-1` |\n| 18 | `Jens_Felez` | `0` |\n| 19 | `ArzName` | `\"USD\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadBuySaleShemsh": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadBuySaleShemsh": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "ShemshName", + 1, + 10000, + 1000000, + "Sharh", + "12345678912345678912", + -1, + -1, + 0, + "USD" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadBuySaleShemsh": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 4.06, + 900, + 10, + "ShemshName", + 1, + 10000, + 1000000, + "Sharh", + "12345678912345678912", + -1, + -1, + 0, + "USD" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadBuySaleShemsh\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 4.06,\n 900,\n 10,\n \"ShemshName\",\n 1,\n 10000,\n 1000000,\n \"Sharh\",\n \"12345678912345678912\",\n -1,\n -1,\n 0,\n \"USD\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadBuySaleKar": { + "post": { + "summary": "DoNewSanadBuySaleKar", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadBuySaleKar", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00244949120260805163147552118123", + "Factor_Code": "00244949120260805163147552118123", + "Sh_factor": "123", + "Factor_Number": "123", + "ID": 1945 + } + } + } + } + }, + "description": "ثبت سند خرید و فروش کارساخته\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `123` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `12` |\n| 6 | `Shamsi_Day` | `23` |\n| 7 | `Vazn` | `1.21` |\n| 8 | `Ayar` | `750` |\n| 9 | `Count` | `2` |\n| 10 | `Name_Kar` | `\"name_kar\"` |\n| 11 | `BuyOrSale_0_1` | `0` |\n| 12 | `Mazaneh` | `107900000` |\n| 13 | `MazanehIsMesghalOrGeram_0_1` | `1` |\n| 14 | `MablaghKol` | `63190000` |\n| 15 | `OjratTedadiOrGerami_0_1` | `1` |\n| 16 | `Darsad_Maliat` | `0` |\n| 17 | `MeghdarMaliat` | `0` |\n| 18 | `Darsad_Sood` | `0` |\n| 19 | `Darsad_Talayee` | `0` |\n| 20 | `IsMarjoo_1_0` | `1` |\n| 21 | `PoolSang` | `0` |\n| 22 | `PictureFileName` | `\"\"` |\n| 23 | `Ojrat` | `6000000` |\n| 24 | `Sharh` | `\"sharh\"` |\n| 25 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 26 | `ثابت` | `-1` |\n| 27 | `MultiRadif` | `-1` |\n| 28 | `Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadBuySaleKar": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadBuySaleKar": [ + 1, + 1, + 123, + 1, + 1405, + 5, + 19, + 1.21, + 750, + 2, + "name_kar", + 0, + 107900000, + 1, + 63190000, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + "", + 6000000, + "sharh", + "12345678912345678911111", + -1, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadBuySaleKar": [ + 1, + 1, + 123, + 1, + 1405, + 5, + 19, + 1.21, + 750, + 2, + "name_kar", + 0, + 107900000, + 1, + 63190000, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + "", + 6000000, + "sharh", + "12345678912345678911111", + -1, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadBuySaleKar\": [\n 1,\n 1,\n 123,\n 1,\n 1405,\n 5,\n 19,\n 1.21,\n 750,\n 2,\n \"name_kar\",\n 0,\n 107900000,\n 1,\n 63190000,\n 1,\n 0,\n 0,\n 0,\n 0,\n 1,\n 0,\n \"\",\n 6000000,\n \"sharh\",\n \"12345678912345678911111\",\n -1,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadVKHKar": { + "post": { + "summary": "DoNewSanadVKHKar", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadVKHKar", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00597430120260805163158719937143", + "Factor_Code": "00597430120260805163158719937143", + "Sh_factor": "143", + "Factor_Number": "143", + "ID": 1947 + } + } + } + } + }, + "description": "ثبت سند ورود و خروج کارساخته\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `7` |\n| 6 | `Shamsi_Day` | `29` |\n| 7 | `Vazn` | `1.25` |\n| 8 | `Ayar` | `750` |\n| 9 | `Count` | `1` |\n| 10 | `Name_Kar` | `\"M\"` |\n| 11 | `IsVoroodOrKhorooj_0_1` | `0` |\n| 12 | `OjratTedadiOrGerami_0_1` | `1` |\n| 13 | `MablaghKol` | `100000` |\n| 14 | `Darsad_Maliat` | `0` |\n| 15 | `MeghdarMaliat` | `0` |\n| 16 | `Darsad_Talayee` | `0` |\n| 17 | `IsMarjoo_1_0` | `0` |\n| 18 | `PictureFileName` | `\"\"` |\n| 19 | `Ojrat` | `10000` |\n| 20 | `PoolSang` | `0` |\n| 21 | `Sharh` | `\"Sharh\"` |\n| 22 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 23 | `HavalehBe_Mcode` | `-1` |\n| 24 | `MultiRadif` | `-1` |\n| 25 | `Jens_Felez` | `0` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadVKHKar": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadVKHKar": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 1.25, + 750, + 1, + "M", + 0, + 1, + 100000, + 0, + 0, + 0, + 0, + "", + 10000, + 0, + "Sharh", + "123456789123456789111111", + -1, + -1, + 0 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadVKHKar": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 1.25, + 750, + 1, + "M", + 0, + 1, + 100000, + 0, + 0, + 0, + 0, + "", + 10000, + 0, + "Sharh", + "123456789123456789111111", + -1, + -1, + 0 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadVKHKar\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 1.25,\n 750,\n 1,\n \"M\",\n 0,\n 1,\n 100000,\n 0,\n 0,\n 0,\n 0,\n \"\",\n 10000,\n 0,\n \"Sharh\",\n \"123456789123456789111111\",\n -1,\n -1,\n 0\n ]\n}\n```" + } + } + }, + "/DoNewSanadBuySaleEtiket": { + "post": { + "summary": "DoNewSanadBuySaleEtiket", + "tags": [ + "Sanad" + ], + "responses": { + "404": { + "description": "DoNewSanadBuySaleEtiket", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "شناسه کار یافت نشد.", + "Command": "POST", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "157", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "4448", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "61694", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:30:33", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "256", + "Count_UnSuccess_Request": "21", + "Last_Request": "2026-08-05 16:32:04" + } + } + } + } + }, + "description": "ثبت سند خرید و فروش اتیکت\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `12` |\n| 6 | `Shamsi_Day` | `23` |\n| 7 | `ثابت` | `0` |\n| 8 | `ثابت` | `0` |\n| 9 | `ثابت` | `0` |\n| 10 | `ثابت` | `\"\"` |\n| 11 | `BuyOrSale_0_1` | `1` |\n| 12 | `Mazaneh` | `46000000` |\n| 13 | `MazanehIsMesghalOrGeram_0_1` | `1` |\n| 14 | `MablaghKol` | `10000000` |\n| 15 | `OjratTedadiOrGerami_0_1` | `1` |\n| 16 | `Darsad_Maliat` | `10` |\n| 17 | `MeghdarMaliat` | `1500` |\n| 18 | `Darsad_Sood` | `7` |\n| 19 | `Darsad_Talayee` | `15` |\n| 20 | `IsMarjoo_1_0` | `0` |\n| 21 | `PoolSang` | `15` |\n| 22 | `PictureFileName` | `\"\"` |\n| 23 | `Ojrat` | `1500` |\n| 24 | `Shenase` | `1` |\n| 25 | `Sharh` | `\"Sharh\"` |\n| 26 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 27 | `ثابت` | `-1` |\n| 28 | `MultiRadif` | `-1` |\n| 29 | `ArzName` | `\"USD\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadBuySaleEtiket": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadBuySaleEtiket": [ + 1, + 1, + -1, + 1, + 1404, + 12, + 23, + 0, + 0, + 0, + "", + 1, + 46000000, + 1, + 10000000, + 1, + 10, + 1500, + 7, + 15, + 0, + 15, + "", + 1500, + 1, + "Sharh", + "", + -1, + -1, + "USD" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadBuySaleEtiket": [ + 1, + 1, + -1, + 1, + 1404, + 12, + 23, + 0, + 0, + 0, + "", + 1, + 46000000, + 1, + 10000000, + 1, + 10, + 1500, + 7, + 15, + 0, + 15, + "", + 1500, + 1, + "Sharh", + "", + -1, + -1, + "USD" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadBuySaleEtiket\": [\n 1,\n 1,\n -1,\n 1,\n 1404,\n 12,\n 23,\n 0,\n 0,\n 0,\n \"\",\n 1,\n 46000000,\n 1,\n 10000000,\n 1,\n 10,\n 1500,\n 7,\n 15,\n 0,\n 15,\n \"\",\n 1500,\n 1,\n \"Sharh\",\n \"\",\n -1,\n -1,\n \"USD\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadVKHEtiket": { + "post": { + "summary": "DoNewSanadVKHEtiket", + "tags": [ + "Sanad" + ], + "responses": { + "404": { + "description": "DoNewSanadVKHEtiket", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ERROR": { + "type": "string" + }, + "Command": { + "type": "string" + }, + "Document": { + "type": "string" + }, + "Accept": { + "type": "string" + }, + "AcceptEncoding": { + "type": "string" + }, + "AcceptLanguage": { + "type": "string" + }, + "ContentType": { + "type": "string" + }, + "ContentLength": { + "type": "string" + }, + "QueryLen": { + "type": "string" + }, + "Referer": { + "type": "string" + }, + "SSL": { + "type": "string" + }, + "SSLPassThrough": { + "type": "string" + }, + "SSLVersion": { + "type": "string" + }, + "SSLCipher": { + "type": "string" + }, + "SSLCipherBits": { + "type": "string" + }, + "SSLCipherDesc": { + "type": "string" + }, + "OpenSSLVersion": { + "type": "string" + }, + "ThreadID": { + "type": "string" + }, + "ProcessID": { + "type": "string" + }, + "httpVer": { + "type": "string" + }, + "Host": { + "type": "string" + }, + "UA": { + "type": "string" + }, + "UserIP1": { + "type": "string" + }, + "UserIP2": { + "type": "string" + }, + "UserPort": { + "type": "string" + }, + "TahesabVersion": { + "type": "string" + }, + "DBType": { + "type": "string" + }, + "DBName": { + "type": "string" + }, + "ServerDBVersion": { + "type": "string" + }, + "ClientDBVersion": { + "type": "string" + }, + "OSVersion": { + "type": "string" + }, + "ErrorCount": { + "type": "string" + }, + "API_Uptime": { + "type": "string" + }, + "API_DB_Uptime": { + "type": "string" + }, + "Count_Success_Request": { + "type": "string" + }, + "Count_UnSuccess_Request": { + "type": "string" + }, + "Last_Request": { + "type": "string" + } + } + }, + "example": { + "ERROR": "شناسه کار یافت نشد.", + "Command": "POST", + "Document": "/", + "Accept": "*/*", + "AcceptEncoding": "gzip, deflate, br", + "AcceptLanguage": "", + "ContentType": "application/json", + "ContentLength": "134", + "QueryLen": "0", + "Referer": "", + "SSL": "1", + "SSLPassThrough": "0", + "SSLVersion": "TLSv1.3", + "SSLCipher": "TLS_AES_128_GCM_SHA256", + "SSLCipherBits": "128", + "SSLCipherDesc": "TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD\n", + "OpenSSLVersion": "OpenSSL 4.0.1 9 Jun 2026", + "ThreadID": "8644", + "ProcessID": "21188", + "httpVer": "HTTP/1.1", + "Host": "127.0.0.1:8081", + "UA": "PostmanRuntime/7.56.0", + "UserIP1": "127.0.0.1", + "UserIP2": "127.0.0.1", + "UserPort": "61698", + "TahesabVersion": "10.1405.5.11", + "DBType": "Access", + "DBName": "db", + "ServerDBVersion": "ACCESS 04.00.0000", + "ClientDBVersion": "10.00.28000", + "OSVersion": "Windows 11 (Version 26H1, OS Build 28000.2608, 64-bit Edition)", + "ErrorCount": "0", + "API_Uptime": "00:30:38", + "API_DB_Uptime": "00:00:00", + "Count_Success_Request": "256", + "Count_UnSuccess_Request": "22", + "Last_Request": "2026-08-05 16:32:09" + } + } + } + } + }, + "description": "ثبت سند ورود و خروج اتیکت\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1404` |\n| 5 | `Shamsi_Month` | `7` |\n| 6 | `Shamsi_Day` | `29` |\n| 7 | `ثابت` | `0` |\n| 8 | `ثابت` | `0` |\n| 9 | `ثابت` | `0` |\n| 10 | `ثابت` | `\"\"` |\n| 11 | `IsVoroodOrKhorooj_0_1` | `1` |\n| 12 | `ثابت` | `0` |\n| 13 | `ثابت` | `0` |\n| 14 | `MablaghKol` | `1500000` |\n| 15 | `OjratTedadiOrGerami_0_1` | `1` |\n| 16 | `Darsad_Maliat` | `0` |\n| 17 | `MeghdarMaliat` | `0` |\n| 18 | `ثابت` | `0` |\n| 19 | `Darsad_Talayee` | `15` |\n| 20 | `IsMarjoo_1_0` | `0` |\n| 21 | `PoolSang` | `100` |\n| 22 | `PictureFileName` | `\"\"` |\n| 23 | `Ojrat` | `100` |\n| 24 | `Shenase` | `1` |\n| 25 | `Sharh` | `\"Sharh\"` |\n| 26 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 27 | `ثابت` | `-1` |\n| 28 | `MultiRadif` | `-1` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadVKHEtiket": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadVKHEtiket": [ + 1, + 1, + -1, + 1, + 1404, + 7, + 29, + 0, + 0, + 0, + "", + 1, + 0, + 0, + 1500000, + 1, + 0, + 0, + 0, + 15, + 0, + 100, + "", + 100, + 1, + "Sharh", + "", + -1, + -1 + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadVKHEtiket": [ + 1, + 1, + -1, + 1, + 1404, + 7, + 29, + 0, + 0, + 0, + "", + 1, + 0, + 0, + 1500000, + 1, + 0, + 0, + 0, + 15, + 0, + 100, + "", + 100, + 1, + "Sharh", + "", + -1, + -1 + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadVKHEtiket\": [\n 1,\n 1,\n -1,\n 1,\n 1404,\n 7,\n 29,\n 0,\n 0,\n 0,\n \"\",\n 1,\n 0,\n 0,\n 1500000,\n 1,\n 0,\n 0,\n 0,\n 15,\n 0,\n 100,\n \"\",\n 100,\n 1,\n \"Sharh\",\n \"\",\n -1,\n -1\n ]\n}\n```" + } + } + }, + "/DoNewSanadVKHVaghNaghd": { + "post": { + "summary": "DoNewSanadVKHVaghNaghd", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadVKHVaghNaghd", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + }, + "OK_HAVALEH": { + "type": "string" + }, + "Sh_factor_Havaleh": { + "type": "string" + }, + "Havaleh_ID": { + "type": "string" + } + } + }, + "example": { + "OK": "00936819120260805163214653909144", + "Factor_Code": "00936819120260805163214653909144", + "Sh_factor": "144", + "Factor_Number": "144", + "ID": 1948, + "OK_HAVALEH": "0093681912026080516321465390914419486399", + "Sh_factor_Havaleh": "63", + "Havaleh_ID": "1948" + } + } + } + } + }, + "description": "ثبت سند ورود و خروج وجه نقد (اسکناس)\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1405` |\n| 5 | `Shamsi_Month` | `4` |\n| 6 | `Shamsi_Day` | `1` |\n| 7 | `IsVoroodOrKhorooj_0_1` | `1` |\n| 8 | `MablaghKol` | `1000000` |\n| 9 | `Sharh` | `\"Sharh\"` |\n| 10 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 11 | `HavalehBe_Mcode` | `2` |\n| 12 | `MultiRadif` | `-1` |\n| 13 | `ArzName` | `\"IRR\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadVKHVaghNaghd": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadVKHVaghNaghd": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 1, + 1000000, + "Sharh", + "12345678912345678911111111", + 2, + -1, + "IRR" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadVKHVaghNaghd": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + 1, + 1000000, + "Sharh", + "12345678912345678911111111", + 2, + -1, + "IRR" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadVKHVaghNaghd\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n 1,\n 1000000,\n \"Sharh\",\n \"12345678912345678911111111\",\n 2,\n -1,\n \"IRR\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadDarAmadNaghd": { + "post": { + "summary": "DoNewSanadDarAmadNaghd", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadDarAmadNaghd", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00391345120260805163219750587145", + "Factor_Code": "00391345120260805163219750587145", + "Sh_factor": "145", + "Factor_Number": "145", + "ID": 1950 + } + } + } + } + }, + "description": "ثبت سند درآمد وجه نقد (اسکناس)\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1405` |\n| 5 | `Shamsi_Month` | `4` |\n| 6 | `Shamsi_Day` | `1` |\n| 7 | `ثابت` | `-1` |\n| 8 | `MablaghKol` | `1000000` |\n| 9 | `Sharh` | `\"Sharh\"` |\n| 10 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 11 | `ثابت` | `-1` |\n| 12 | `MultiRadif` | `-1` |\n| 13 | `ArzName` | `\"IRR\"` |\n| 14 | `Baabat` | `\"Baabat\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + "type": "string", + "default": "DB" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "DoNewSanadDarAmadNaghd": { + "type": "array", + "items": { + "type": "integer" + } + } + } + }, + "example": { + "DoNewSanadDarAmadNaghd": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + -1, + 1000000, + "Sharh", + "123456789123456789111111111", + -1, + -1, + "IRR", + "Baabat" + ] + }, + "examples": { + "postman": { + "summary": "نمونه بادی Postman", + "value": { + "DoNewSanadDarAmadNaghd": [ + 1, + 1, + -1, + 1, + 1405, + 5, + 19, + -1, + 1000000, + "Sharh", + "123456789123456789111111111", + -1, + -1, + "IRR", + "Baabat" + ] + } + } + } + } + }, + "description": "نمونهٔ بادی ارسال‌شده:\n\n```json\n{\n \"DoNewSanadDarAmadNaghd\": [\n 1,\n 1,\n -1,\n 1,\n 1405,\n 5,\n 19,\n -1,\n 1000000,\n \"Sharh\",\n \"123456789123456789111111111\",\n -1,\n -1,\n \"IRR\",\n \"Baabat\"\n ]\n}\n```" + } + } + }, + "/DoNewSanadHazinehNaghd": { + "post": { + "summary": "DoNewSanadHazinehNaghd", + "tags": [ + "Sanad" + ], + "responses": { + "200": { + "description": "DoNewSanadHazinehNaghd", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "OK": { + "type": "string" + }, + "Factor_Code": { + "type": "string" + }, + "Sh_factor": { + "type": "string" + }, + "Factor_Number": { + "type": "string" + }, + "ID": { + "type": "integer" + } + } + }, + "example": { + "OK": "00574066120260805163228865740146", + "Factor_Code": "00574066120260805163228865740146", + "Sh_factor": "146", + "Factor_Number": "146", + "ID": 1951 + } + } + } + } + }, + "description": "ثبت سند هزینه ی وجه نقد (اسکناس)\n\n### پارامترهای Body\n\n| اندیس | نام یا معنی پارامتر | مقدار نمونه |\n| --- | --- | --- |\n| 0 | `Sabte_Kol_Or_Movaghat_1_0` | `1` |\n| 1 | `Moshtari_Code` | `1` |\n| 2 | `Factor_Number` | `-1` |\n| 3 | `Radif_Number` | `1` |\n| 4 | `Shamsi_Year` | `1405` |\n| 5 | `Shamsi_Month` | `4` |\n| 6 | `Shamsi_Day` | `1` |\n| 7 | `ثابت` | `-1` |\n| 8 | `MablaghKol` | `1000000` |\n| 9 | `Sharh` | `\"Sharh\"` |\n| 10 | `Factor_Code` | `\"حداقل 20 کارکتر\" \"05d5cd63-ad7f-4c2b-a135-4e226eedc712\"` |\n| 11 | `ثابت` | `-1` |\n| 12 | `MultiRadif` | `-1` |\n| 13 | `ArzName` | `\"IRR\"` |\n| 14 | `Baabat` | `\"Baabat\"` |", + "parameters": [ + { + "name": "DBname", + "in": "header", + "required": true, + "schema": { + + +[131,038 characters truncated due to size] \ No newline at end of file diff --git a/docs/integrations/tahesab.md b/docs/integrations/tahesab.md new file mode 100644 index 0000000..5143cd6 --- /dev/null +++ b/docs/integrations/tahesab.md @@ -0,0 +1,71 @@ +# اتصال ته‌حساب (فاز ۱) + +مرجع API: [Tahesab API Reference](https://tahesab.ir/APiDoc/) · OpenAPI: `docs/integrations/tahesab-openapi.json` + +## اصول + +- هر سازمان می‌تواند **چند اتصال** داشته باشد (`baseUrl` + `token` + `dbName`). +- توکن با **AES-256-GCM** و کلید محیطی `INTEGRATIONS_ENCRYPTION_KEY` رمز می‌شود و هرگز کامل به فرانت برنمی‌گردد. +- مانده و اسناد: **منبع حقیقت ته‌حساب** است؛ CRM فقط cache و لینک نگه می‌دارد. +- ثبت سند فقط از فرم اختصاصی تب **دارایی** با `Factor_Code` یکتا (≥۲۰ کاراکتر) و جدول `AccountingDocumentLog` (idempotent). + +## مدل‌ها + +| مدل | نقش | +|-----|-----| +| `AccountingConnection` | اتصال چند-DB | +| `PersonAccountingLink` | لینک شخص ↔ `moshtariCode` روی یک اتصال | +| `AccountingDocumentLog` | لاگ push سند | +| `AccountingBalanceCache` | cache مانده | +| `AccountingSyncJob` | لاگ جستجو/وارد کردن | + +## APIهای CRM + +پیشوند: `/api/integrations/tahesab` + +- اتصالات (owner/admin): `GET/POST/PATCH/DELETE /connections` · `POST /connections/:id/test` +- لیست عمومی اتصالات: `GET /connections/public` +- لینک شخص: `GET/POST .../people/:id/links` · `DELETE .../links/:connectionId` +- تطبیق: `POST .../people/:id/match` · ثبت: `POST .../create-in-tahesab` +- دارایی: `GET .../people/:id/assets` · اسناد: `GET .../people/:id/asnad` +- ثبت سند: `POST .../people/:id/sanad` +- sync دوطرفه: `POST /sync/search` · `POST /sync/import` + +## تطبیق مشتری + +1. نرمال‌سازی موبایل → `DoListMoshtari-ByPhone` +2. اگر خالی → `DoListMoshtari-ByName` +3. اگر بیش از یک نتیجه → انتخاب دستی (لینک خودکار روی ابهام ممنوع) +4. لینک دستی با کد · یا `DoNewMoshtari` + +## انواع سند فاز ۱ + +| کلید CRM | متد ته‌حساب | +|----------|-------------| +| `buy_sale_gold` | `DoNewSanadBuySaleGOLD` | +| `buy_sale_sekeh` | `DoNewSanadBuySaleSEKEH` | +| `talab_bedehi` | `DoNewSanadTalabBedehi` | +| `vkh_gold` | `DoNewSanadVKHGOLD` | +| `vkh_bank` | `DoNewSanadVKHBank` | + +مانده: مسیر `GetMandeHesabByCode` با کلید body `getmandehesabbycode` (مثل همکار). + +## استقرار + +1. `INTEGRATIONS_ENCRYPTION_KEY` را روی سرور بگذارید (۶۴ کاراکتر hex). +2. `npx prisma migrate deploy` در `apps/api` +3. rebuild API/web و restart PM2 + +## چک‌لیست تست دستی + +- [ ] افزودن اتصال + تست health +- [ ] افزودن اتصال دوم با DB دیگر؛ انتخاب پیش‌فرض +- [ ] تطبیق شخص با موبایل / لینک دستی / ثبت جدید +- [ ] نمایش مانده و جزئیات در تب دارایی +- [ ] لیست اسناد با بازه شمسی +- [ ] ثبت سند؛ retry با همان Factor_Code نباید سند تکراری بسازد +- [ ] وارد کردن مشتری از تنظیمات ته‌حساب + +## خارج از فاز ۱ + +push خودکار از معامله/فاکتور، RFID/اتیکت، PDF/Excel اسناد، ویرایش سند در ته‌حساب. diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index c48c863..d62a827 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1461,6 +1461,93 @@ export interface CreateAutomationRuleRequest { export type UpdateAutomationRuleRequest = Partial; +// —— ته‌حساب / حسابداری —— + +export const TAHSAB_SANAD_TYPES = [ + "buy_sale_gold", + "buy_sale_sekeh", + "talab_bedehi", + "vkh_gold", + "vkh_bank", +] as const; + +export type TahesabSanadType = (typeof TAHSAB_SANAD_TYPES)[number]; + +export const TAHSAB_SANAD_LABELS: Record = { + buy_sale_gold: "خرید/فروش آبشده", + buy_sale_sekeh: "خرید/فروش سکه", + talab_bedehi: "طلب/بدهی", + vkh_gold: "واریز/خروج طلا", + vkh_bank: "واریز/خروج بانکی", +}; + +export interface TahesabConnectionDto { + id: string; + organizationId: string; + provider: string; + label: string; + baseUrl: string; + dbName: string; + tokenMasked: string; + enabled: boolean; + isDefault: boolean; + allowInsecureTls: boolean; + lastHealthAt: string | null; + lastHealthOk: boolean | null; + lastError: string | null; + createdAt: string; + updatedAt: string; +} + +export interface CreateTahesabConnectionRequest { + label: string; + baseUrl: string; + dbName: string; + token: string; + enabled?: boolean; + isDefault?: boolean; + allowInsecureTls?: boolean; +} + +export type UpdateTahesabConnectionRequest = Partial; + +export interface PersonAccountingLinkDto { + id: string; + personId: string; + connectionId: string; + moshtariCode: number; + matchMethod: string; + linkedAt: string; + lastBalanceSyncedAt: string | null; + connectionLabel?: string; + dbName?: string; + isDefaultConnection?: boolean; +} + +export interface MandehValueDto { + amount: string | number; + unit: string; + status: "بس" | "بد"; +} + +export interface MandehDetailItemDto { + Name: string; + values: MandehValueDto[]; +} + +export interface PersonAssetsDto { + connectionId: string; + connectionLabel: string; + dbName: string; + moshtariCode: number; + goldBalance: number | null; + rialBalance: number | null; + currencyBalance: number | null; + totalGoldEquiv: number | null; + mandehDetail: MandehDetailItemDto[]; + fetchedAt: string; +} + export const APP_NAME = "Mento CRM"; export const APP_NAME_FA = "منتو"; export const API_PREFIX = "api";