Harden Holoo-to-Hesabix document partition/mapping, sample E2E tooling, remove hardcoded SQL credentials from scripts, fix income AR account 10401, and publish Setup MSI 1.1.0. Co-authored-by: Cursor <cursoragent@cursor.com>
39 KiB
طرح فنی انتقال حسابداری هلو → حسابیکس
وضعیت: در حال پیادهسازی
آخرین پیشرفت: E2E biz 6823 — نمونه همه ماژولها OK؛ انتقال کامل در جریان (run-full-e2e.ps1)؛ 801→40001؛ EI بدون FACTURE/Check؛ بدون dump تکبانک/تکصندوق؛ چک API path اصلاح؛ درآمد شخص 10401.
پیشرفت پیادهسازی
| فاز | وضعیت | شواهد |
|---|---|---|
| ۰ سنجش | انجامشده | scripts/audit-partition.ps1 — روی Holoo1: MANUAL=4، excluded facture-linked=538 |
| ۱ پارتیشن | انجامشده | ReadManualJournalsInRange + CountSql با NOT EXISTS FACTURE؛ preflight گزارش overlap |
| ۲ کاتالوگ | انجامشده | mapper بدون 70401/FirstOrDefault؛ لینک مستقیم بانک و صندوق؛ وام/هزینه اختصاصی؛ invariants سبز |
| ۳ پروفایل UI | انجامشده | گرید با ستون Override قابل ویرایش؛ قفل پروفایل؛ انتقال اسناد بدون قفل متوقف |
| ۴–۶ انتقال | هسته + E2E افتتاحیه | افتتاحیه Holoo1→biz6823 ثبت و پست شد (۱۲۶ خط، متوازن)؛ Abort روی Block |
| ۷–۸ اثبات | جزئی→قویتر | BalanceProofService + compare-opening-balance.ps1؛ مقایسه خالص Col↔کد حسابیکس |
هدف محصول: هر سند هلو که اثر دفتری دارد، دقیقاً یکبار، با ماهیت درست، متوازن، و قابل ردیابی به Sanad_Code هلو، در حسابیکس بنشیند. اختلاف تراز فقط وقتی پذیرفته است که منبعش خود هلو باشد و در گزارش مهاجرت با کد سند توضیح داده شده باشد.
۱. قرارداد صحت (غیرقابل مذاکره)
این قواعد بر همه فازها حاکماند. فازی تمام نمیشود اگر یکی از آنها نقض شود.
- پارتیشن انحصاری اسناد. هر
Sanad_Codeحداکثر به یک ماژول انتقال تعلق دارد: افتتاحیه، فاکتور، دریافت/پرداخت، چک، هزینه/درآمد، یا سند دستی. عضویت در دو ماژول یعنی دوبل دفتری. - رد کردن بهتر از حدس زدن. اگر خط سند به حساب، شخص، بانک یا صندوق قطعی نگاشت نشود، کل سند
Failedمیشود. انتخاب «اولین بانک» یا «اولین صندوق» ممنوع است. - تراز در مبدأ. سندی با
|جمع بدهکار − جمع بستانکار| > 0.01منتقل نمیشود. بستن اختلاف به30106فقط برای افتتاحیه و فقط بعد از گزارش صریح مبلغ و علت مجاز است. - ردیف کنترلی منتقل نمیشود.
Col 005و006(تراز افتتاحیه/اختتامیه هلو) وSanad_Type = 5که GL چک است، کپی نمیشوند. اثر آنها از ماژول افتتاحیه و ماژول چک ساخته میشود. - کد عمومی حسابیکس تغییر نمیکند. حسابهای
business_id IS NULLفقط خوانده میشوند. کمبود با حساب اختصاصی همان کسبوکار جبران میشود. - اثر مالی با پیشوند کد حفظ میشود. طبقهبندی سود و زیان حسابیکس بر اساس پیشوند کد است (
pnl_account_classification). حساب اختصاصی هزینه باید با7شروع شود، درآمد با6، فروش با5، بهای تمامشده با4. کد الفبایی مثلHLO-601-0007در بستن سال و صورت سود و زیان دیده نمیشود. - زیردفتر جدا از حساب کل است. شخص، بانک، صندوق و تنخواه موجودیتاند و روی حسابهای نوعی (
10401/20201/10203/10202/10201) مینشینند. ساخت حساب عمومی جدید جایگزین تفصیل آنها نیست.
معیار پذیرش نهایی (روی Holoo1 و هر دیتابیس مشتری)
برای هر سال مالی:
| کنترل | شرط قبول |
|---|---|
| پوشش اسناد | تعداد SANAD غیرحذفشده = افتتاحیه + فاکتور (یکتا روی Sanad_Code) + Type20 + هزینه/درآمد + چکهای دارای سند + دستی + عمداً ردشده با دلیل |
| عدم دوبل | هیچ Sanad_Code در بیش از یک checkpoint موفق نیست |
| تراز | جمع بدهکار و بستانکار اسناد منتقلشده در حسابیکس با جمع متناظر هلو، پس از کسر 005/006 و GL تکراری چک، در حد ۰٫۰۱ برابر است |
| ماهیت | فروش هلو 901 فقط در گروه ۵، تخفیف فروش 903 در 50003، برگشت فروش 902 در 50002، خرید/برگشت/تخفیف خرید در گروه ۴ |
| رد خاموش | تعداد اسنادی که بهخاطر fallback بانک/صندوق منتقل شدهاند = ۰ |
۲. وضعیت فعلی (خط مبنا)
نگاشت فعلی در HolooSarfaslMapper.MapColToFixedCode فقط Col را به یک کد ثابت میبرد. درخت SARFASL کپی نمیشود. تفصیل شخص از CustomerSarfasl و بانک از تطبیق شماره حساب در نام سرفصل حل میشود.
روی Holoo1 (۵۵۰ سرفصل فعال، ۳۲ کل):
| واقعیت | اثر |
|---|---|
۵۳۸ فاکتور F/K به سند Type 13/14 با SaveFromFacture = 0 وصلاند |
اگر Invoices و ManualJournals هر دو روشن باشند، فروش/خرید دوبل میشود |
| نامزد «سند دستی» = ۵۴۲ رکورد: ۲۷۵ نوع ۱۳، ۲۶۵ نوع ۱۴، ۲ نوع ۴ | تقریباً همه نوع ۱۳/۱۴ همان GL فاکتورند؛ سند دستی واقعی فقط نوع ۴ است (۲ سند) |
903 به 60203 (سایر درآمدها) میرود |
تخفیف نقدی فروش از گروه فروش خارج میشود |
802 902 803 904 905 207 403 501 506 001 002 بدون نگاشتاند |
هر سند دستی که این کلها را داشته باشد کلاً رد میشود؛ در فاکتور هم اگر GL جدا خوانده شود گم میشوند |
104 همیشه 10403 است |
در افتتاحیه، 104.0002 «اسناد در جریان وصول» باید 10404 باشد |
معینهای وام زیر 401 (وام تجارت، قوامین، رفاه) به 20201 + شخص میروند |
تسهیلات با حساب پرداختنی تجاری قاطی میشود |
تطبیق هزینه با Contains روی نام؛ پیشفرض 70401 |
«هزینه تخفیفات - تعدیل حساب» (۲۱۶ سند) و مالیات/جریمه/صدقه به خرید خدمات میافتند |
ResolveBank / ResolveCashOrPetty در نهایت FirstOrDefault |
با ۱۲ بانک و ۲ صندوق، مانده میتواند بیصدا به حساب غلط برود |
اینها موضوع فاز ۱ تا ۳ هستند. فازهای بعدی روی همین موتور سوار میشوند.
۳. مدل هدف
۳.۱ کلید سرفصل
SarfaslKey = Col(3) + "|" + Moien + "|" + Tafzili
Moien و Tafzili خالی یعنی خود سطح کل/معین. نگاشت روی دقیقترین کلید موجود انجام میشود: اول تفصیلی، بعد معین، بعد کل.
۳.۲ سه لایه تصمیم برای هر سرفصل
| لایه | چه وقت | خروجی |
|---|---|---|
| A. زیردفتر | 101 صندوق/تنخواه، 102 بانک، 103/401 شخص تجاری |
موجودیت حسابیکس + حساب نوعی ثابت |
| B. کد عمومی | ماهیت با یک حساب seed یکی است | account_id همان کد عمومی |
| C. حساب اختصاصی کسبوکار | ماهیت در چارت عمومی نیست، یا معین هلو باید در گزارش جدا بماند | POST /api/v1/accounts/business/{id}/create |
ترتیب اجباری: A، سپس B، سپس C. ساخت حساب جدید وقتی کد عمومی درست وجود دارد ممنوع است (مثلاً 901 همیشه 50001 است، نه یک حساب فروش تازه).
۳.۳ قید ساخت حساب اختصاصی (از API موجود)
create_business_account اینها را تحمیل میکند:
parent_idاجباری است.- اگر والد عمومی است و برگ است (
childrenخالی)، خطایINVALID_PUBLIC_PARENTمیدهد. زیر10401،20201،50001،70401،10203نمیتوان فرزند ساخت. - والد باید عمومی باشد یا متعلق به همان
business_id. - یکتایی کد روی
(business_id, code)است. کد عمومی باbusiness_id NULLاین یکتایی را نمیبندد؛ بنابراین کد اختصاصی نباید با کد عمومی یکی باشد، وگرنهListAccountCodeMapبسته به ترتیب API ممکن است id غلط را بردارد. account_typeحساب اختصاصی مهاجرت ="0"(حساب عادی). نوعهایperson/bank/cash_registerفقط روی حسابهای سیستمی میمانند.
۳.۴ طرح کد اختصاصی
فرمت: {prefix گروه}9{Col سه رقم}{Moien چهار رقم} با pad صفر.
| ماهیت | والد (کد عمومی که از قبل فرزند دارد) | نمونه کد | پیشوند P&L / ترازنامه |
|---|---|---|---|
| هزینه عملیاتی بدون معادل | 704 |
70496010007 برای هلو 601.0007 |
با 7 شروع میشود → هزینه عملیاتی |
| هزینه بانکی/غیرعملیاتی | 709 |
70996010009 برای کارمزد اگر نخواهیم 70902 |
با 709 → غیرعملیاتی |
| درآمد بدون معادل | 602 |
60297020001 |
با 602 → درآمد غیرعملیاتی |
| درآمد خدماتی بدون معادل | 601 |
60197020003 |
با 601 |
| وام/تسهیلات زیر ۴۰۱ | 20501 |
205194010011 |
ترازنامه، بدهی غیرجاری |
| سایر بدهی جاری | 203 |
20394010008 |
ترازنامه |
| پیشدریافت اختصاصی | 204 |
20492070001 |
ترازنامه |
| دارایی ثابت اختصاصی | 107 |
10792050001 |
ترازنامه |
| حقوق صاحبان سهام اختصاصی | 301 |
30195010001 |
ترازنامه |
| انتظامی | 801 |
80190010001 |
خارج از سود و زیان |
9 بعد از پیشوند گروه، فضای کد را از کدهای پنجرقمی seed جدا میکند. نام حساب = Sarfasl_Name هلو، حداکثر طول مجاز API.
حساب اختصاصی یکبار در فاز ۲ ساخته میشود و در checkpoint با کلید ACC:{SarfaslKey} ذخیره میشود. اجرای مجدد، اگر کد موجود باشد، همان id را لینک میکند (ACCOUNT_CODE_NOT_UNIQUE → جستجو با code).
۳.۵ جدول نگاشت لایه B (جایگزین MapColToFixedCode)
نگاشت پیشفرض سیستمی، قابل override در پروفایل کسبوکار:
| کلید هلو | کد حسابیکس | یادداشت |
|---|---|---|
101.0001 و هر صندوق |
10202 + cash_register_id |
معین 0002 یا نام حاوی «تنخواه» → 10201 + petty_cash_id |
102.* |
10203 + bank_account_id |
تطبیق فقط با شماره حساب یا نقشه صریح؛ بدون fallback |
103.* شخص |
10401 اگر بدهکار خالص، 20201 اگر بستانکار خالص |
جهت خط سند تعیینکننده است، نه فقط Col |
104.0001 |
10403 اسناد دریافتنی |
|
104.0002 |
10404 اسناد در جریان وصول |
تفکیک اجباری |
104 با نام ضمانت/سپرده |
10302 / 10303 |
|
106 |
10102 |
فقط مبلغ ریالی افتتاحیه؛ مقدار کالا جدا و با cost_price = 0 |
107.0004 و نام مالیات/عوارض خرید |
10104 |
|
107 سایر |
10101 پیشپرداخت |
|
205 |
10704 اثاثیه |
اگر نام زمین/ساختمان/وسیله باشد → 10701/10702/10703 |
401 شخص تجاری |
20201 + person_id |
|
401 با طبقه «وام» |
حساب اختصاصی زیر 20501 |
شخص اختیاری در شرح، نه تفصیل AP |
402 |
20202 |
وصول/صدور واقعی از ماژول چک؛ در افتتاحیه سطر تجمیعی مجاز است |
207 / 403 |
20401 یا 20402 |
|
404 |
30105 جاری شرکا |
اگر تفصیل شریک به شخص وصل است، person_id هم پر شود |
501 / 506 |
30101 |
|
502 |
30106 |
سود و زیان سنوات؛ با حساب بستن اختلاف قاطی نشود |
503 |
40001 |
بهای تمامشده |
601.{moien} |
جدول صریح بخش ۳.۶ | |
702.{moien} |
جدول صریح بخش ۳.۶ | |
801 |
در فاکتور خرید تولید میشود؛ در سند دستی اگر مستقل بود 40001 سمت بدهکار خرید فقط وقتی فاکتور وصل نیست |
|
802 |
40002 |
|
803 |
40003 |
|
901 |
50001 |
|
902 |
50002 |
|
903 |
50003 |
اصلاح باگ فعلی 60203 |
904 |
50003 با علامت معکوس در شرح، یا حساب اختصاصی زیر گروه ۵ اگر باید جدا بماند |
تخفیف نقدی برگشت از فروش |
905 |
40003 |
تخفیف نقدی برگشت از خرید |
001 |
80101 |
|
002 |
80102 |
|
005 006 |
هیچ | حذف از خطوط |
105 موجودی پایان دوره |
هیچ، مگر سند اختتامیه که فاز ۷ جدا تصمیم میگیرد | حساب کنترلی انبار هلو |
620 کنترل هزینه |
هیچ تا وقتی سندی با مبلغ واقعی دیده شود؛ اگر دیده شد حساب اختصاصی زیر 704 با هشدار |
هر کلیدی که در این جدول نیست و در SND_LIST مبلغ غیرصفر دارد، قبل از انتقال باید یا به لایه B اضافه شود یا در لایه C ساخته شود. انتقال با «رد شدن خاموش خط» ممنوع است.
۳.۶ نگاشت صریح هزینه و درآمد (جایگزین keyword)
حداقل برای معینهای موجود Holoo1. پروفایل هر مشتری همین جدول را گسترش میدهد.
هلو 601 |
کد |
|---|---|
0001 آب |
70503 |
0002 برق |
70504 |
0003 تلفن |
70506 |
0004 0064 کرایه، 0066 اجاره |
70405 |
0005 مطالبات مشکوک / سوخت چک |
70802 |
0006 ضایعات |
70407 |
0008 کمیسیون |
70702 |
0009 کارمزد بانک |
70902 |
0052 حمل |
70403 |
0060 حقوق |
70201 |
0063 خوراک |
70502 |
0065 مصرفی |
70406 |
0067 سوخت |
70501 |
0068 بیمه |
70211 |
0070 جریمه دیرکرد |
70903 |
0007 تخفیف تعدیل، 0055 گرد کردن، 0056–0062 عوارض و مالیات، 0058 کد اقتصادی، 0069 صدقه |
حساب اختصاصی زیر 704 یا 709؛ پیشفرض 70401 حذف میشود |
هلو 702 |
کد |
|---|---|
0003 حقالعمل |
60101 |
0004 تخلیه/حمل |
60104 |
0001 0002 سایر |
60203 مگر کاربر جدا بخواهد |
قانون: اگر نام در جدول نبود، سند هزینه Failed با پیام «معین بدون نگاشت» است. ساخت خودکار حساب اختصاصی فقط وقتی مجاز است که کاربر در پیشنمایش فاز ۳ گزینه «ایجاد حساب» را زده باشد.
۴. پارتیشن اسناد (فاز ۱)
الگوریتم طبقهبندی، قبل از هر API call، روی کل SANAD غیرحذفشده یک برچسب میزند. برچسبها همپوشانی ندارند. ترتیب ارزیابی:
1. Sanad_Code = سند افتتاحیه (فعلی: Sanad_Code = 1، باید با Comment/تاریخ اول سال هم تأیید شود)
→ OPENING
2. Col فقط 005/006 یا سند بدون مبلغ واقعی
→ SKIP_CONTROL
3. Sanad_Type = 5 OR Sanad_Code / Sanad_Code2 در جدول Check
→ CHECK_GL_SKIP (اثر از ماژول چک)
4. EXISTS فاکتور غیرحذف با همین Sanad_Code
OR SaveFromFacture = 1 و Type in (0,13,14)
→ INVOICE_GL_SKIP (اثر از فاکتور + حواله انبار)
5. وجود خط 601 یا 702 با مبلغ، و طرفحساب فقط در {101,102,103,401}
و |آیتم − طرف| <= 0.01
→ EXPENSE_INCOME
6. Sanad_Type = 20 و شرط ۵ برقرار نیست
و طرف شخص + طرف 101 یا 102
→ RECEIPT_PAYMENT
7. بقیه اسناد با حداقل دو خط مبلغدار و تراز <= 0.01
→ MANUAL
8. هر چه ماند
→ UNCLASSIFIED (باید صفر شود یا با دلیل در گزارش بماند)
روی Holoo1 انتظار بعد از این قانون:
- Type 13/14 متصل به فاکتور از MANUAL خارج میشوند (۵۳۸ سند).
- MANUAL واقعی ≈ نوع ۴ (۲ سند) بهعلاوه هر سند متوازنی که به فاکتور، چک، Type20 و 601/702 نخورد.
- Type 0 با
SaveFromFacture = 1(۲۷۲۵ سند) فقط از مسیر فاکتور میرود.
خروجی فاز ۱ یک جدول ممیزی است، نه سند حسابیکس:
Sanad_Code, Date, Type, SaveFromFacture, Bucket, Debit, Credit, ColSet, Blocker
Blocker خالی یعنی قابل انتقال. مقدارش یکی از اینهاست: unmapped_sarfasl, unresolved_person, unresolved_bank, unbalanced, missing_dimension.
۵. فازهای اجرایی
هر فاز یک تحویل قابل تست دارد. فاز بعدی شروع نمیشود مگر معیار خروج فاز قبل روی Holoo1 سبز باشد. کدنویسی هر فاز جدا و قابل review است.
فاز ۰ — قفل محدوده و ابزار سنجش
هدف: قبل از تغییر نگاشت، بتوان اختلاف را اندازه گرفت.
کارها:
- اسکریپت خواندنی (فقط SELECT) که برای یک دیتابیس هلو اینها را بنویسد:
- توزیع
Col_CodeدرSND_LISTبا مبلغ. - توزیع Bucket طبق بخش ۴.
- فهرست
SarfaslKeyهای بدون نگاشت لایه B. - فهرست اسنادی که هم فاکتور دارند هم در فیلتر فعلی ManualJournals میافتند.
- توزیع
- ثابت کردن تلرانس پول: ۰٫۰۱ ریال، همان
ApiDateFormat.RoundMoney. - تعریف شناسه ردیابی در
extra_infoهمه اسناد حسابیکس:holoo_sanad_code,holoo_bucket,holoo_db.
خروج: گزارش baseline برای Holoo1 ذخیره شود و اعداد بخش ۲ همین سند را تأیید کند. هیچ write به حسابیکس در این فاز نیست.
فاز ۱ — کلاسهبند اسناد و بستن دوبل
هدف: Manual Journals دیگر GL فاکتور را برنمیدارد.
کارها در HolooDocumentReader.ReadManualJournalsInRange و شمارنده ماژول:
- شرط جدید:
NOT EXISTS (SELECT 1 FROM FACTURE f WHERE f.Sanad_Code = s.Sanad_Code AND ISNULL(f.[Delete],0)=0). Sanad_Type IN (13,14)حتی بدون ردیف فاکتور، اگرSaveFromFacture=1باشد، از دستی خارج بماند (الان با فیلترSaveFromFacture=0تا حدی هست؛ شرط فاکتور هنوز لازم است چون ۵۳۸ سندSaveFromFacture=0ولی فاکتور دارند).- Type 5 و پیوند
Check.Sanad_Code/Sanad_Code2سر جایش بماند. - اسناد
UNCLASSIFIEDدر preflight بهصورت error بیایند، نه warning.
خروج روی Holoo1:
- تعداد سند دستی کاندید از ۵۴۲ به حدود ۲ (نوع ۴) بهعلاوه موارد واقعاً بدون فاکتور برسد.
- اشتراک
Sanad_Codeبین فاکتورهایF/K/Y/X/Zو لیست دستی = ۰. - دو سند نوع ۴ (
16891بانک/شخص و23923صندوق/شخص) هنوز در لیست دستی باشند.
ریسک: فاکتور حذفشده با سند زنده. شرط حذف فاکتور باید باشد تا سند یتیم به دستی برگردد و گم نشود.
فاز ۲ — کاتالوگ نگاشت و ساخت حساب اختصاصی
هدف: هر SarfaslKey دارای مبلغ، قبل از انتقال سند، یک مقصد قطعی داشته باشد.
طراحی کامپوننت SarfaslCatalog (جایگزین تدریجی توابع Shared فعلی):
Resolve(line) →
Decision {
Kind: Person | Bank | Cash | Petty | FixedAccount | BusinessAccount | Skip | Block
AccountCode or AccountId
DimensionId? 'person / bank / cash / petty
BlockReason?
}
کارها:
- داده نگاشت لایه B را از کد جدا کنید (فایل یا جدول داخل checkpoint).
MapExpenseToFixedCodeمبتنی برContainsحذف شود؛ جدول بخش ۳.۶ منبع حقیقت است. - API کلاینت:
CreateBusinessAccount(businessId, parentCode, code, name).- parent را از
ListAccountCodeMapبا کد والد پیدا کنید. - اگر
INVALID_PUBLIC_PARENTبرگشت، والد را یک سطح بالاتر ببرید فقط اگر آن سطح در جدول ۳.۴ مجاز باشد؛ در غیر این صورت Block.
- parent را از
- ترتیب ساخت: اول والدهای اختصاصی (اگر لازم شد)، بعد برگها. در عمل فاز اول فقط برگ زیر والد عمومی غیربرگ میسازد؛ درخت چندسطحی اختصاصی لازم نیست.
- حسابهای سیستمی که نوعدارند (
account_typeشخص/بانک/صندوق/چک/کالا) را هرگز بهعنوان مقصد سند دستیِ بدون dimension انتخاب نکنید. API سند در این حالت یا رد میکند یا مانده تفصیل را خراب میکند. ResolveBank: حذفValues.FirstOrDefault()و حذف تطبیقContainsدوطرفه شماره حساب. تطبیق مجاز:- نقشه صریح
ACOUND_N.Id → bank_account_idکه در انتقال پایه ساخته شده. - برابری دقیق
Account_Nبا شماره داخل نام سرفصل. - اگر هیچکدام نبود:
Block / unresolved_bank.
- نقشه صریح
- همین قاعده برای صندوق و تنخواه: بیش از یک صندوق ⇒ نقشه
Cash.Idبه سرفصل، نه اولین رکورد. - طبقه
401: اگر نام معین با الگوهایوام|تسهیلات|قسطجور است، Kind = BusinessAccount زیر20501، نه Person+AP. لیست استثنا در پیشنمایش قابل اصلاح است (کارمند میتواند AP بماند).
خروج:
- برای
Holoo1، هر Col دارای مبلغ در افتتاحیه (101,102,103,104,106,107,205,401,402,404,502) تصمیم غیر Block دارد. 104.0002به کد10404حل میشود.903به50003حل میشود.- معین
601.0007یا حساب اختصاصی دارد یا Block است؛ هرگز70401پیشفرض نیست. - اجرای دوباره کاتالوگ، حساب تکراری نمیسازد.
وابستگی حسابیکس: اگر ساخت زیر یک والد عمومی بهخاطر برگ بودن شکست خورد، آن مورد در همین فاز با انتخاب والد مجاز ۳.۴ حل میشود. تغییر API حسابیکس لازم نیست مگر بخواهیم زیر برگ عمومی هم فرزند بسازیم؛ آن را عمداً نمیخواهیم چون برگهای عمومی نوعدارند و رفتار سند را عوض میکنند.
فاز ۳ — پیشنمایش انسانی و قفل پروفایل
هدف: اپراتور قبل از ارسال سند، نگاشت را ببیند و تأیید کند. انتقال اسناد تا قفل پروفایل شروع نشود.
کارها در UI ویزارد (بعد از اتصال SQL و انتخاب کسبوکار):
- گرید سرفصل: نام هلو، مبلغ گردش بدهکار/بستانکار، تصمیم پیشنهادی، مقصد، وضعیت (آماده / نیاز به ساخت حساب / مسدود).
- سه عمل روی ردیف مسدود یا قابل تغییر:
- نگاشت به کد عمومی موجود (لیست حسابهای همان کسبوکار + عمومی).
- ایجاد حساب اختصاصی (نام قابل ویرایش، والد از لیست مجاز ۳.۴، کد خودکار).
- «عمداً منتقل نشود» با دلیل اجباری. این ردیف در گزارش پذیرش میآید و سندهای درگیر را Block میکند مگر کل سند فقط از همین ردیفهای معاف تشکیل نشده باشد؛ اگر یک خط سند معاف است، کل سند Block است تا تراز نشکند.
- ذخیره پروفایل کنار checkpoint:
sarfasl-profile.jsonشامل overrideها و id حسابهای ساختهشده. - پیشنمایش Bucketها: تعداد و جمع مبلغ هر ماژول، بهعلاوه تعداد Blocker.
خروج: روی Holoo1 اپراتور میتواند بدون ارسال سند، ببیند وامهای 401 به 20501 میروند و ۵۳۸ سند فاکتوری در دستی نیستند. پروفایل قفلشده ورودی فاز ۴ است.
فاز ۴ — افتتاحیه سال اول
هدف: تراز افتتاحیه هلو، بدون دوبل موجودی کالا، در سند افتتاحیه حسابیکس بنشیند.
ورودی: خطوط ReadOpeningLines منهای 005/006، بهعلاوه مقدار First_exist کالا فقط برای کاردکس.
قواعد:
- هر خط از
SarfaslCatalog.Resolveرد شود. یک خط Block ⇒ افتتاحیه ثبت نشود (الان خط skip میشود و اختلاف به30106میرود؛ این رفتار حذف میشود). - تجمیع مجاز است فقط برای یک مقصد یکسان (همان شخص، همان بانک، همان کد حساب). تجمیع
401وام با401تأمینکننده ممنوع است چون Kind فرق دارد. 104.0001و104.0002دو سطر جدا (10403و10404).- موجودی کالا: سطر ریالی از Col
106روی10102میماند. سطر مقدار باcost_price = 0فقط کاردکس را پر میکند تا GL دوبل نشود. اگر جمع ریالیFirst_exist * costبا Col106بیش از تلرانس اختلاف داشت، در گزارش بیاید؛ سند را با میانگینگیری خاموش درست نکنید. - اختلاف باقیمانده بعد از نگاشت کامل: یک سطر به
30106با شرح «اختلاف تراز افتتاحیه هلو» فقط اگر گزارش فاز ۰ همان اختلاف را در خود سند هلو (پس از حذف 005/006) نشان بدهد. اگر اختلاف از خط Blockشده آمده، ثبت نکنید. - شخص افتتاحیه:
103بدهکار خالص →10401؛401تجاری بستانکار خالص →20201. وامها حساب اختصاصی، بدونperson_idاجباری.
خروج روی Holoo1: سند افتتاحیه Sanad_Code = 1 یا کامل ثبت میشود یا با فهرست خطوط Block متوقف میشود. جمع بدهکار و بستانکار ارسالی برابر است. حساب 30106 فقط به اندازه مانده خود Col 502 بهعلاوه اختلاف واقعی هلو بستانکار/بدهکار میشود، نه به اندازه خطوط جاافتاده.
فاز ۵ — اسناد عملیاتی (فاکتور، دریافت، چک، هزینه)
هدف: اسنادی که حسابیکس برایشان سند تخصصی دارد، از همان API بروند تا GL و زیردفتر با هم ساخته شود.
فاکتور
- منبع حقیقتcommercial همان
FACTURE/FACTARTاست، نه سند Type 13/14. - انواع:
Fفروش،Kخرید،Yبرگشت فروش،Xبرگشت خرید،Zمصرف مستقیم. - تسویه نقد/بانک از hint سند، با Catalog.resolve؛ اگر resolve نشد پرداخت روی فاکتور ننشیند و مانده نسیه بماند، و سند در گزارش «تسویه نامشخص» بیاید. چسباندن به صندوق پیشفرض ممنوع.
FCheckهمچنان نسیه میماند تا ماژول چک اسناد دریافتنی/پرداختنی را جابهجا کند. شرط پذیرش: جمع چکهای متصل به فاکتور باFCheckهمان فاکتور در حد تلرانس یکی باشد؛ اختلاف گزارش شود.- حواله انبار فقط از ماژول WarehouseDocs و فقط برای فاکتورهایی که حوالهشان در هلو اثر مقداری دارد. صدور دوباره GL موجودی از سند حسابداری هلو ممنوع.
دریافت/پرداخت Type 20
- فقط Bucket
RECEIPT_PAYMENT. - شخص و بانک/صندوق هر دو باید Resolve شوند وگرنه Fail همان سند.
- اگر سند Type 20 خط
601/702دارد، در این ماژول نیست (مال هزینه/درآمد است). این شرط الان هست؛ تستش را نگه دارید.
چک
- ایجاد، عودت، وصول فقط از ماژول چک.
- هیچ سندی از Type 5 یا
Check.Sanad_Code*دوباره بهصورت دستی پست نشود. - بانک وصول باید Resolve دقیق شود. نبود بانک = Fail وصول، نه اولین بانک.
- حالتهایی که باید در تست باشند: دریافت، پرداخت، در جریان وصول (
104.0002)، برگشت، ابطال. اگر API حسابیکس برای «خواباندن به حساب در جریان وصول» عمل جدا ندارد، سند دستی فقط برای همان شکاف با حساب10404مجاز است و باید در پارتیشن با برچسبCHECK_SUPPLEMENTباشد تا با سند صدور چک دوبل نشود. این شکاف در شروع فاز ۵ با یک سند نمونهHoloo1(مثلاً حوالیSanad 43051) اندازهگیری میشود؛ اگر API چک خودش10403 → 10404را میزند، مکمل دستی ساخته نمیشود.
هزینه/درآمد
- آیتمها فقط از جدول ۳.۶ یا حساب اختصاصی تأییدشده.
- طرفحساب خارج از شخص/صندوق/بانک ⇒ سند به MANUAL میرود (الان
Return Nothingیعنی Fail؛ فاز ۵ آن را إعادة طبقهبندی میکند تا سند ترکیبی گم نشود). - اختلاف مبلغ آیتم و طرف بیش از ۰٫۰۲ ⇒ Fail، بدون سرشکن.
خروج: برای یک سال نمونه Holoo1 (ترجیحاً آخرین سال)، شمارش فاکتور منتقلشده = شمارش فاکتور غیرحذف همان بازه. شمارش Type20 و هزینه همینطور. هیچکدام از این Sanad_Codeها در checkpoint دستی نیستند.
فاز ۶ — سند دستی کامل
هدف: Bucket MANUAL خطبهخط با Catalog به POST .../documents/manual برود.
قواعد BuildManualJournalPayload:
- خط
Skip(005/006) حذف میشود و در جمع تراز نمیآید. - خط
Block⇒ کل سند Fail با ذکرCol|Moien|Name. - خط شخص:
account_idاز جهت (AR/AP) +person_id. - خط بانک/صندوق/تنخواه:
account_idنوعی + dimension. بدون dimension ارسال نشود. - خط حساب عادی:
account_idعمومی یا اختصاصی. |bed − bes| > 0.01⇒ Fail.- کمتر از دو خط ⇒ Fail.
extra_info.holoo_sanad_codeاجباری برای برگشتپذیری.
خروج روی Holoo1: دو سند نوع ۴ یا منتقل میشوند یا دلیل Block مشخص دارند. جمع اسناد MANUAL موفق + ناموفق + SKIP = تعداد Bucket MANUAL. ناموفق صفر است مگر پروفایل فاز ۳ چیزی را عمداً معاف کرده باشد.
فاز ۷ — اثبات تراز و گزارش پذیرش
هدف: محصول بدون گزارش سبز، «تمامشده» اعلام نشود.
کارها:
- گزارش سمت هلو (SQL) و سمت حسابیکس (API تراز آزمایشی یا جمع اسناد) برای هر سال:
- جمع بدهکار/بستانکار به تفکیک Bucket.
- جمع به تفکیک کد حسابیکس مقصد.
- مقایسه:
- گروه فروش هلو (
901−902−903±904) با گردش50001/50002/50003. - گروه خرید (
801−802−803±905) با40001/40002/40003فقط برای اسنادی که از مسیر دستی/افتتاحیه آمدهاند؛ فاکتور خرید را حسابیکس در بهای تمامشده/موجودی طبق سیستم دائمی خودش مینشاند. این تفاوت سیستم دائمی در گزارش با یک سطر توضیحی میآید و بهعنوان خطا شمرده نمیشود، به شرطی که جمع فاکتور خرید هلو با جمع فاکتور خرید حسابیکس برابر باشد. - اشخاص: مانده هر
C_Codeدر هلو در پایان سال با مانده تفصیل همان شخص. - بانک: مانده هر
ACOUND_Nبا مانده همان بانک.
- گروه فروش هلو (
- فهرست اسناد Fail با دلیل، قابل خروجی CSV.
- آستانه قبول: اختلاف توضیحدادهنشده = ۰. اختلاف سیستم دائمی موجودی فقط در سطر توضیحی گزارش مجاز است.
خروج: یک فایل گزارش برای Holoo1 که بخش «اختلاف بدون توضیح» خالی است، یا فهرست دقیق کار باقیمانده را دارد. فاز تمام است فقط در حالت اول.
فاز ۸ — سختسازی محصول
هدف: رفتار بالا برای دیتابیس غیر از Holoo1 هم تکرار شود.
کارها:
- Preflight قبل از انتقال: اگر Bucket
UNCLASSIFIEDیا سرفصل Block بدون معافیت وجود دارد، دکمه شروع غیرفعال است. - Resume: checkpoint فعلی حفظ شود؛ حساب اختصاصی و پروفایل نگاشت بخشی از checkpoint باشند تا اجرای دوباره حساب نسازد و سند دوبل نزند.
- تست خودکار روی کپی کوچکشده از الگوهای
Holoo1:- فاکتور Type13 با
SaveFromFacture=0دوبل نشود. 903به50003برود.104.0002به10404برود.- وام
401به AP نرود. - بانک نامطابق سند را Fail کند.
- هزینه ناشناس بدون تأیید کاربر به
70401نرود. - ساخت حساب دوم با همان کد، id قبلی را برگرداند.
- فاکتور Type13 با
- لاگ مهاجرت برای هر سند: کلید هلو، id حسابیکس، bucket، جمع مبلغ.
خروج: مجموعه تست بالا سبز است و preflight یک دیتابیس مصنوعی با سرفصل ناشناس را متوقف میکند.
۶. ترتیب اجرا و وابستگی
فاز ۰ سنجش
→ فاز ۱ پارتیشن (دوبل را میبندد حتی قبل از نگاشت کامل)
→ فاز ۲ کاتالوگ + ساخت حساب
→ فاز ۳ قفل پروفایل
→ فاز ۴ افتتاحیه
→ فاز ۵ عملیاتی
→ فاز ۶ دستی
→ فاز ۷ اثبات
→ فاز ۸ تست و قفل محصول
فاز ۱ را میتوان مستقل از فاز ۲ منتشر کرد چون فقط جلوی دوبل را میگیرد و به حساب جدید نیاز ندارد. فاز ۴ به قفل فاز ۳ وابسته است. فاز ۶ بدون فاز ۲ سندهای دارای کلِ بدون نگاشت را همچنان Fail میکند؛ این Fail درست است و نباید با fallback پوشانده شود.
۷. آنچه عمداً خارج از انتقال دفتری است
| مورد | رفتار |
|---|---|
| حسابهای عمومی حسابیکس | ویرایش و حذف نمیشوند |
درخت کامل SARFASL بهعنوان کپی یکبهیک کد هلو |
ساخته نمیشود؛ فقط معینهایی که معادل عمومی ندارند و مبلغ دارند، با کد اختصاصی بخش ۳.۴ ساخته میشوند |
| سند Type 5 و GL چک | کپی نمیشود |
005 / 006 |
کپی نمیشود |
| موجودی مقداری کالا در افتتاحیه | کاردکس جدا؛ GL فقط از Col 106 |
| سیستم دائمی حسابیکس در مقابل ثبت خرید/فروش هلو | فاکتور از API فاکتور میرود تا موجودی و بهای تمامشده را خود حسابیکس بسازد؛ سند Type 13/14 همان فاکتور دوباره پست نمیشود |
۸. تعریف تمامشدن کار
انتقال وقتی بینقص است که هر چهار شرط با هم برقرار باشند:
- پارتیشن بخش ۴ هیچ
Sanad_Codeرا به دو ماژول موفق نداده باشد. - هر سرفصل دارای مبلغ، تصمیم قفلشده در پروفایل داشته باشد (نگاشت عمومی، حساب اختصاصی، یا معافیت با دلیل).
- گزارش فاز ۷ اختلاف توضیحدادهنشده نداشته باشد.
- تستهای فاز ۸ روی الگوی
Holoo1سبز باشند.
تا قبل از این چهار شرط، محصول نباید بهعنوان انتقال کامل حسابداری عرضه شود.