-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscope.html
More file actions
1029 lines (975 loc) · 66.9 KB
/
Copy pathscope.html
File metadata and controls
1029 lines (975 loc) · 66.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Accounting module — scope — Multi-Tenant Platform</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Fraunces:opsz,wght@9..144,500;9..144,600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="../../assets/styles.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" />
<style>
.matrix-table th, .matrix-table td { text-align: center; font-size: .85rem; padding: .35rem .45rem; }
.matrix-table th:first-child, .matrix-table td:first-child { text-align: left; font-weight: 600; }
.matrix-table .x { color: #1a7f37; font-weight: 700; }
.matrix-table .hub { background: #fff8e6; }
.mermaid { background: #fafafa; border: 1px solid var(--rule); border-radius: var(--radius); padding: 1rem; margin: 1rem 0; }
.gap-badge { background: #fce2e2; color: #b3261e; padding: .1rem .45rem; border-radius: 3px; font-size: .78rem; font-weight: 600; }
.ok-badge { background: #e6f4ea; color: #1a7f37; padding: .1rem .45rem; border-radius: 3px; font-size: .78rem; font-weight: 600; }
.partial-badge { background: #fff8e6; color: #7a5a0a; padding: .1rem .45rem; border-radius: 3px; font-size: .78rem; font-weight: 600; }
.cluster-table td:nth-child(1) { width: 4ch; text-align: center; font-weight: 600; }
.cluster-table td:nth-child(2) { width: 24%; font-weight: 600; }
.cluster-table code a { color: inherit; text-decoration: underline dotted; }
</style>
</head>
<body>
<div class="layout">
<aside class="sidebar">
<a href="../../index.html" class="brand">
<span class="brand-mark">MTP</span>
<span class="brand-text">Multi-Tenant Platform</span>
</a>
<nav>
<div class="nav-group">
<h4>Foundations</h4>
<ul>
<li><a href="../../index.html"><span class="nav-num">00</span>Overview</a></li>
<li><a href="../../docs/01-findings.html"><span class="nav-num">01</span>Findings</a></li>
<li><a href="../../docs/02-architecture.html"><span class="nav-num">02</span>Architecture</a></li>
<li><a href="../../docs/10-tenancy-model.html"><span class="nav-num">10</span>Tenancy Model</a></li>
</ul>
</div>
<div class="nav-group">
<h4>Validation</h4>
<ul>
<li><a href="../../docs/03-code-sketch.html"><span class="nav-num">03</span>Code Sketch</a></li>
<li><a href="../../docs/04-ui-rule-config.html"><span class="nav-num">04</span>UI Rule Config</a></li>
<li><a href="../../docs/05-result-pattern.html"><span class="nav-num">05</span>Result Pattern</a></li>
<li><a href="../../docs/06-reconciliation.html"><span class="nav-num">06</span>Reconciliation</a></li>
</ul>
</div>
<div class="nav-group">
<h4>Tenant Surface</h4>
<ul>
<li><a href="../../docs/07-ui-schema.html"><span class="nav-num">07</span>UI Schema</a></li>
<li><a href="../../docs/08-i18n-l10n.html"><span class="nav-num">08</span>i18n / l10n</a></li>
<li><a href="../../docs/09-extension-fields.html"><span class="nav-num">09</span>Extension Fields</a></li>
</ul>
</div>
<div class="nav-group">
<h4>Decisions</h4>
<ul>
<li><a href="../../adr/0001-hybrid-validation-strategy.html"><span class="nav-num">ADR-1</span>Hybrid Validation</a></li>
<li><a href="../../adr/0002-database-per-client.html"><span class="nav-num">ADR-2</span>DB-per-Client</a></li>
<li><a href="../../adr/0003-frontend-stack.html"><span class="nav-num">ADR-3</span>Frontend Stack</a></li>
<li><a href="../../adr/0004-authorization-permission-model.html"><span class="nav-num">ADR-4</span>Authz & Permissions</a></li>
<li><a href="../../adr/0005-repo-topology.html"><span class="nav-num">ADR-5</span>Repo Topology</a></li>
<li><a href="../../adr/0006-no-module-federation.html"><span class="nav-num">ADR-6</span>No Module Federation</a></li>
<li><a href="../../adr/0007-ui-stack-radix-cssmodules.html"><span class="nav-num">ADR-7</span>UI Stack — Radix</a></li>
<li><a href="../../adr/0008-mtp-web-folder-structure.html"><span class="nav-num">ADR-8</span>mtp-web Folder Structure</a></li>
<li><a href="../../adr/0009-hr-payroll-three-aggregates.html"><span class="nav-num">ADR-9</span>HR-Payroll — 3 Aggregates, 1 Module</a></li>
</ul>
</div>
<div class="nav-group">
<h4>GNUMS — Conventions</h4>
<ul>
<li><a href="../module-catalog.html"><span class="nav-num">MOD</span>Module Catalog</a></li>
<li><a href="../all-modules-inventory.html"><span class="nav-num">REF</span>Procedure Inventory</a></li>
<li><a href="../methodology.html"><span class="nav-num">HOW</span>Study Methodology</a></li>
<li><a href="../staff/scope.html"><span class="nav-num">STF</span>Staff — Scope</a></li>
<li><a href="../hr-payroll/scope.html"><span class="nav-num">HRP</span>HR-Payroll — Scope</a></li>
</ul>
</div>
<div class="nav-group">
<h4>GNUMS — Accounting</h4>
<ul>
<li><a href="scope.html" class="active"><span class="nav-num">ACC</span>Accounting — Scope</a></li>
<li><a href="legacy-antipatterns.html"><span class="nav-num">AP</span>Legacy Anti-Patterns</a></li>
</ul>
</div>
<div class="nav-group">
<h4>GNUMS — Exam</h4>
<ul>
<li><a href="../exam/scope.html"><span class="nav-num">EXM</span>Exam — Scope</a></li>
<li><a href="../exam/strategy.html"><span class="nav-num">PLAY</span>Exam — Strategy</a></li>
</ul>
</div>
</nav>
</aside>
<main>
<span class="eyebrow">GNUMS · Accounting Scope Study</span>
<h1>Accounting module scope (from GNUMS legacy)</h1>
<p class="lede">
Synthesis of the legacy <code>ACC_*</code> accounting module across 19 functional clusters
and 4 cross-cuts. Purpose: understand the full <em>functional surface</em> of school /
college / hospital accounting in the legacy code so the new platform can be designed
against requirements, not schema. Legacy is <strong>input</strong>; the new domain model
is <strong>output</strong>. Cluster docs under
<code>gnums/accounting/clusters/</code> are the source-of-truth deep dives; this page is
the consolidated map.
</p>
<div class="callout">
<strong>Companion pages.</strong> Each cluster is a separate markdown file linked from
Section 2's table. Anti-patterns that must NOT be carried over are catalogued in
<a href="legacy-antipatterns.html">Legacy Anti-Patterns</a>. The cluster-by-cluster build
strategy lives in <code>STUDY-PLAN.md</code> at the repo root.
</div>
<!-- ====================================================================== -->
<h2>1. Module purpose and scope</h2>
<p>
The GNUMS accounting module is a multi-company, India-localised general-ledger system
embedded inside a school / college / hospital ERP. It absorbs money from many upstream
sources (student fees, OPD receipts, donations, sales invoices), books expenses against
vendors and staff (purchase invoices, expert/PhD remuneration, trip claims, petty cash),
and pushes payments out through cheque, NEFT/RTGS/IMPS and an HDFC corporate-banking API.
Every event lands as a balanced double-entry voucher in <code>ACC_AccountVoucher</code> +
<code>ACC_AccountVoucherTran</code> with a mirror in <code>ACC_Journal</code> +
<code>ACC_JournalTran</code>. The module is used by accountants, cashiers, finance
officers, AP/AR clerks, treasury, and a multi-level approval chain that walks from
junior accountant through registrar.
</p>
<p>
It matters because the fee-collection cycle is the largest inbound money stream in any
Indian education tenant: thousands of student receipts per day get aggregated into bank
deposit slips that must reconcile against the bank statement, then feed downstream into
GST output, TDS deduction (194C, 194J, 194I, 194Q), Form 26Q quarterly returns, and
GSTR-3B / GSTR-9 filings. The module also services hospital OPD (`HOP_*`), PhD scholarship
remuneration, and traveller advance settlement. Multi-company tenancy is first-class:
one trust often controls 3–15 legal entities (companies) sharing inter-company
bridge accounts.
</p>
<p>
<strong>In scope:</strong> chart of accounts and account groups, voucher core +
numbering + balancing, automatic posting bridges from 20+ source events, cost-centre +
budget allocation, bank account + cheque-book lifecycle + GDI+ cheque printing, online
bank payment with JWS+JWE envelopes, multi-level journal approval, vendor bill capture +
verification + booking + payment + advance settlement, sales invoicing with GST split,
student refund orders, cash advance issuance and settlement, inter-company fund transfer,
consolidated fee-collection deposit slips, OPD receipt collection, TDS sections + monthly
challan deposit + section-wise register, GST rate master + GSTR aggregators (incomplete),
petty-cash expense capture + cost-centre distribution, expert and PhD honorarium payment
with 194J TDS, staff trip approval + advance + expense report.
</p>
<p>
<strong>Out of scope:</strong> payroll (lives in HRP module — salary TDS 192 / 24Q
stays there), inventory valuation, fixed-asset depreciation schedules, e-invoice IRN
generation (legacy gap), e-Way Bill (legacy gap), bank statement import (MT940 / OFX /
camt.053 — legacy gap), Schedule-III Balance Sheet / P&L / Trial Balance as
RDLC reports (legacy gap), automated NSDL 26Q text-file export (legacy gap), period
close / FY hard-lock (legacy gap — <code>GetFinalLockLevel()</code> stub returns
<code>1</code>, no accounting SP enforces a lock-date), and 11 of the 13 inbound payment
gateways' refund flows.
</p>
<!-- ====================================================================== -->
<h2>2. Cluster map</h2>
<p>
Nineteen functional clusters and four cross-cuts. The hub is Cluster 3
— the <em>posting bridge</em> — through which every source event transits
on its way to the voucher core (Cluster 2) and the journal (Cluster 7). Diagram capped
at 30 nodes for readability; orange = hub clusters, blue = source events, grey =
cross-cuts.
</p>
<div class="mermaid">
graph TD
subgraph SOURCES ["Source events"]
C13[13 Fee Collection]
C14[14 OPD Receipt]
C8[8 Purchase Invoice]
C9[9 Sales Invoice]
C10[10 Refund Order]
C11[11 Cash Advance]
C12[12 Fund Transfer]
C17[17 Expense]
C18[18 Remuneration]
C19[19 Trip]
end
subgraph HUB ["Hub — posting + ledger"]
C3[/3 Posting Bridge /]
C2[2 Voucher Core]
C7[7 Journal + Approval]
end
subgraph MASTERS ["Masters + lifecycle"]
C1[1 Chart of Accounts]
C4[4 Cost Centre]
C5[5 Bank + Cheque]
C6[6 Online Bank Payment]
C15[15 TDS]
C16[16 GST]
end
subgraph CROSS ["Cross-cuts"]
A[A Reports + Dashboards]
B[B Integrations]
Cfg[C Config + FY + Lock]
D[D i18n strings]
end
C13 --> C3
C14 --> C3
C8 --> C3
C9 --> C3
C10 --> C3
C11 --> C3
C12 --> C3
C17 --> C3
C18 --> C3
C19 --> C3
C3 --> C2
C2 --> C7
C7 --> C6
C1 -.-> C3
C4 -.-> C3
C5 -.-> C2
C5 -.-> C6
C15 -.-> C3
C16 -.-> C3
A -.-> C2
A -.-> C7
B -.-> C6
Cfg -.-> C2
D -.-> C7
classDef hub fill:#fff3e0,stroke:#e65100,color:#5d2e00
classDef source fill:#e3f2fd,stroke:#1565c0,color:#0d3a6b
classDef master fill:#f3e5f5,stroke:#6a1b9a,color:#3a0e58
classDef cross fill:#eeeeee,stroke:#616161,color:#212121
class C3,C2,C7 hub
class C13,C14,C8,C9,C10,C11,C12,C17,C18,C19 source
class C1,C4,C5,C6,C15,C16 master
class A,B,Cfg,D cross
</div>
<h3>Cluster index</h3>
<table class="cluster-table">
<thead>
<tr><th>#</th><th>Cluster</th><th>One-line summary</th><th>Doc</th></tr>
</thead>
<tbody>
<tr>
<td>01</td><td>Chart of Accounts & Master</td>
<td>3-level account hierarchy, multi-company books, account groups, payment modes, vendor enrichment (PAN/GSTIN), TDS section linkage, account merge + transfer.</td>
<td><a href="clusters/cluster-01-coa-master.md"><code>cluster-01</code></a></td>
</tr>
<tr>
<td>02</td><td>Voucher Core</td>
<td>Master journal entry (BP/BR/CP/CR/CV/JV/FT/FC), per-FY voucher numbering, Dr/Cr balance enforcement at SP level, side-flip rules, bill adjustment, cheque link, verification, cancellation (soft), import.</td>
<td><a href="clusters/cluster-02-voucher-core.md"><code>cluster-02</code></a></td>
</tr>
<tr>
<td>03</td><td>Posting Bridge <em>(hub)</em></td>
<td>20+ posters that convert source-module events into balanced double-entry vouchers. Encodes TDS, GST, cross-company inter-company contra, system-lock with reason. Largest SPs in the module (1k–1.6k lines each).</td>
<td><a href="clusters/cluster-03-posting-bridge.md"><code>cluster-03</code></a></td>
</tr>
<tr>
<td>04</td><td>Cost Centre + Budget</td>
<td>Arbitrary-tree cost centres, time-boxed cost projects, monthly budget (CostCentre × CostProject), bill-line allocation, percentage distribution template, budget-vs-actual dashboards, over-budget warn (never block).</td>
<td><a href="clusters/cluster-04-cost-centre.md"><code>cluster-04</code></a></td>
</tr>
<tr>
<td>05</td><td>Bank Account + Cheque</td>
<td>Institute's own bank accounts (extends <code>ACC_Account</code>), cheque books with pre-materialised leaves, flat lifecycle (Blank/Used/Cancelled), per-bank HTML + GDI+ print templates, Indian lakh/crore amount-in-words. No MICR/IFSC on bank master — gap.</td>
<td><a href="clusters/cluster-05-bank-cheque.md"><code>cluster-05</code></a></td>
</tr>
<tr>
<td>06</td><td>Online Bank Payment + Verification</td>
<td>HDFC CBX corporate-banking adapter with JWS (RS256) + JWE (RSA-OAEP-256 / A256GCM) wire envelope, mTLS, per-rail error-code dictionary, attempt / inquiry split. PennyDrop + PAN + GSTIN verification via EaseBuzz.</td>
<td><a href="clusters/cluster-06-online-bank-payment.md"><code>cluster-06</code></a></td>
</tr>
<tr>
<td>07</td><td>Journal + Approval</td>
<td>Single ledger (header + balanced trans), origin pointers back to source artefact, system-lock with HTML reason, N-level approval chain (DAT_Approval), payee onboarding with penny-drop name-match, NEFT/RTGS/Fund-Transfer classification by IFSC + amount.</td>
<td><a href="clusters/cluster-07-journal-approval.md"><code>cluster-07</code></a></td>
</tr>
<tr>
<td>08</td><td>Purchase Invoice (AP)</td>
<td>Four-stage AP: capture → verify → book → pay. Bill-to-bill matching, advance-against-bill settlement, multi-party single payment voucher, TDS at payment time, GST split on lines (CGST/SGST/IGST/Cess), system-lock chain.</td>
<td><a href="clusters/cluster-08-purchase-invoice.md"><code>cluster-08</code></a></td>
</tr>
<tr>
<td>09</td><td>Sales Invoice (AR)</td>
<td>GST tax invoices to external bodies (industry training, hostel rent, consultancy). Per-line HSN/SAC + CGST/SGST/IGST, intra/inter-state inference from customer state, approval / cancellation columns, 1:1 GL voucher rewritten on each save.</td>
<td><a href="clusters/cluster-09-sales-invoice.md"><code>cluster-09</code></a></td>
</tr>
<tr>
<td>10</td><td>Refund Order Payment</td>
<td>Student-refund disbursement against approved fee-refund orders. Three origin paths (self-service application, manual entry, hostel/transport pipe). One-minute duplicate window, FX-aware fee-head split, online-bank-payment hand-off.</td>
<td><a href="clusters/cluster-10-refund.md"><code>cluster-10</code></a></td>
</tr>
<tr>
<td>11</td><td>Cash Advance</td>
<td>Petty-cash APV (Dr) + ARV (Cr) with self-referencing settlement junction. Per-day <code>YYMMDD/NNN</code> voucher number, system-lock on first settlement, outstanding register filterable across modes. No statutory cash-limit (§269ST) enforcement.</td>
<td><a href="clusters/cluster-11-cash-advance.md"><code>cluster-11</code></a></td>
</tr>
<tr>
<td>12</td><td>Fund Transfer</td>
<td>Inter-account / inter-company movement (treasury concentration, trust → institute). Cash/Bank/JV × Payment/Receipt routing matrix, inter-company bridge account (<code>MST_Company.AccountID</code>), per-leg UTR + reconcile date.</td>
<td><a href="clusters/cluster-12-fund-transfer.md"><code>cluster-12</code></a></td>
</tr>
<tr>
<td>13</td><td>Fee Collection Bank <em>(heavy)</em></td>
<td>Daily/shift aggregate deposit slip bridging FEE module to GL. Three variants: Standard Contra, No-Contra Cash, ForOther. Stamps verification on FEE receipts, preserves bank-reconcile date across edits.</td>
<td><a href="clusters/cluster-13-fee-collection.md"><code>cluster-13</code></a></td>
</tr>
<tr>
<td>14</td><td>OPD Receipt Collection</td>
<td>Hospital twin of Cluster 13. Aggregates <code>HOP_Receipt</code> rows into one voucher per batch, with per-company cash-account XML for the no-contra cash path. Edit always rebuilds the voucher.</td>
<td><a href="clusters/cluster-14-opd-receipt.md"><code>cluster-14</code></a></td>
</tr>
<tr>
<td>15</td><td>TDS <em>(heavy)</em></td>
<td>Section master (auto-provisions liability ledger), PAN-4th-character → default section, monthly aggregate by (Company, Section, Period) computing unpaid balance, challan recording with cascade-lock on source vouchers. No NSDL 26Q export.</td>
<td><a href="clusters/cluster-15-tds.md"><code>cluster-15</code></a></td>
</tr>
<tr>
<td>16</td><td>GST</td>
<td>Per-tenant rate master (name + CGST/SGST/IGST + six ledger accounts), per-line GST snapshot on PI/SI lines, GSTIN-portal scheduler (30-day cooldown), GSTR-3B report (5 boxes), GSTR-9 stub. No IRN, no e-Way Bill, no JSON export.</td>
<td><a href="clusters/cluster-16-gst.md"><code>cluster-16</code></a></td>
</tr>
<tr>
<td>17</td><td>Expense</td>
<td>Two distinct flows under one prefix: petty-cash capture (Category → SubCategory → bill image) and post-voucher expense distribution across Campus/Institute/Faculty/Department dimensions. No state machine — binary lock only.</td>
<td><a href="clusters/cluster-17-expense.md"><code>cluster-17</code></a></td>
</tr>
<tr>
<td>18</td><td>Expert / PHD Remuneration</td>
<td>Honoraria outside payroll for visiting faculty + PhD examiners. Session capture, multi-level approval, completion proof photo, 194J TDS (travelling exempt for Expert, included for PHD — asymmetric).</td>
<td><a href="clusters/cluster-18-remuneration.md"><code>cluster-18</code></a></td>
</tr>
<tr>
<td>19</td><td>Trip / Travel</td>
<td>Staff trip approval → advance request → expense capture with FX rate inherited from approved advance → trip report bundling → multi-level approval → settlement posting. Hard 2-level dashboard assumption.</td>
<td><a href="clusters/cluster-19-trip.md"><code>cluster-19</code></a></td>
</tr>
<tr>
<td>A</td><td>Reports + Dashboards <em>(cross-cut)</em></td>
<td>16 RDLC reports (Day Book, Ledger, Cash & Bank, BRS, Cheque Book, Aging, Advance Register, TDS, Sales Invoice, GSTR-3B, GSTR-9). 6 dashboards: CFO summary, maintenance-anomaly, AP funnel, cost-centre, trip. <span class="gap-badge">Gaps</span> Trial Balance, P&L, Balance Sheet, Receipts & Payments not as RDLC.</td>
<td><a href="clusters/cross-A-reports.md"><code>cross-A</code></a></td>
</tr>
<tr>
<td>B</td><td>Integrations <em>(cross-cut)</em></td>
<td>One outbound rail (HDFC CBX). Twelve+ inbound payment gateways (Razorpay, PayU, SBI ePay, CCAvenue, Cashfree, EaseBuzz, Paytm, PayPhi, Pine Labs, Qfix, Edviron, GrayQuest, EasyPay) + cash-deposit machine. Tally = Excel only. GST/TDS/IRN = none.</td>
<td><a href="clusters/cross-B-integrations.md"><code>cross-B</code></a></td>
</tr>
<tr>
<td>C</td><td>Config + FY + Period Close <em>(cross-cut)</em></td>
<td>23-column <code>ACC_AccountingConfiguration</code> per (Company, Institute). Manual <code>FinYearID</code> sequence, free-text <code>FinYearName</code>, overlap check only. <span class="gap-badge">Critical gap</span> No period close, no soft/hard lock — any user with insert rights can post any date.</td>
<td><a href="clusters/cross-C-config-fy.md"><code>cross-C</code></a></td>
</tr>
<tr>
<td>D</td><td>i18n string catalog <em>(cross-cut)</em></td>
<td>124 user-visible business strings extracted from 905 <code>PR_ACC_*</code> SPs + 7 in-scope <code>PR_FEE_*</code>. All English, HTML-tagged (<code><b></code>/<code><br /></code>), <code>THROW 50001</code> dominant. Catalogued by cluster + category for new i18n resource files.</td>
<td><a href="clusters/cross-D-i18n.md"><code>cross-D</code></a></td>
</tr>
</tbody>
</table>
<!-- ====================================================================== -->
<h2>3. Domain ER diagram</h2>
<p>
Twenty-eight core entities at the heart of the module — capped at 30 nodes per
readability cap. Relationships shown are the ones that load-bear in cross-cluster flows;
audit shadows (<code>LOJ_*</code>), per-table log tables and config rows are omitted.
Read this as a sketch of the new domain, not a copy of the legacy schema.
</p>
<div class="mermaid">
erDiagram
Company ||--o{ Account : "owns ledger via AccountWiseCompany"
Account ||--o{ JournalTran : "ledger line"
AccountGroup ||--o{ Account : "classifies"
Account ||--o| BankAccount : "extends"
Account ||--o{ TDSSection : "liability ledger for"
AccountVoucher ||--|{ AccountVoucherTran : "lines"
AccountVoucher ||--o| Journal : "mirror"
Journal ||--|{ JournalTran : "lines"
Journal ||--o| JournalApproval : "if bank payment"
ChequeBook ||--|{ Cheque : "leaves"
AccountVoucher ||--o| Cheque : "consumes"
CompanyDefaultAccount }o--|| Company : "per-purpose default"
PaymentMode ||--o{ AccountVoucher : "classifies"
FeeCollectionBank ||--|{ FeeCollectionBankTran : "lines"
FeeCollectionBank ||--o| AccountVoucher : "produces"
OPDReceiptCollection ||--|{ OPDReceiptCollectionTran : "lines"
OPDReceiptCollection ||--o| AccountVoucher : "produces"
PI ||--|{ PITran : "items"
PIForAccounting ||--|{ PIForAccountingTran : "bills"
PIPayment ||--|{ PIPaymentTran : "trans"
PIForAccountingTran ||--o{ AccountVoucherAdjustment : "matched"
PIPaymentTran ||--o{ AccountVoucherAdjustment : "settles"
PIPayment ||--o| Cheque : "via"
PIPaymentTran }o--|| TDSSection : "withholds"
SI ||--|{ SITran : "items"
SITran }o--|| GSTPCT : "rate"
PITran }o--|| GSTPCT : "rate"
RefundOrderPayment ||--|{ RefundOrderPaymentTran : "settles"
RefundOrderPaymentTran }o--|| FEE_RefundOrder : "pays"
CashAdvanceReceipt ||--o{ CashAdvanceSettlement : "settles via"
CashAdvanceSettlement }o--|| CashAdvanceReceipt : "settled by"
FundTransferFrom ||--|{ FundTransferTo : "legs"
FundTransferFrom ||--o| AccountVoucher : "produces"
TDSPayment ||--|{ TDSPaymentTran : "challan"
TDSPaymentTran }o--|| Company : "per-company"
TDSPaymentTran }o--|| TDSSection : "per-section"
Expense }o--|| ACC_EXP_SubCategory : "category"
ExpenseDistribution ||--|{ ExpenseDistributionTran : "split"
ExpertSession ||--|{ ExpertSessionTran : "sittings"
ExpertRemuneration ||--|{ ExpertRemunerationTran : "per session"
PHDRemunerationPayment ||--|{ PHDRemunerationPaymentTran : "per claim"
TRIP_Trip ||--|{ TRIP_TripTran : "legs"
TRIP_Trip ||--o{ TRIP_AdvanceFund : "advances"
TRIP_Trip ||--o{ TRIP_Expense : "expenses"
TRIP_Report ||--o{ TRIP_AdvanceFund : "bundles"
TRIP_Report ||--o{ TRIP_Expense : "bundles"
CostCentre ||--o{ ExpenseDistributionTran : "tagged"
CostProject ||--o{ CostBudget : "budgeted"
</div>
<!-- ====================================================================== -->
<h2>4. State machines</h2>
<p>
Eight clusters carry explicit state. Most are implemented as nullable column-set rather
than typed enum (legacy convention: NULL = initial, populated columns mean state-X). The
three diagrams below are the most consequential; the table lists every state machine in
the module.
</p>
<table>
<thead><tr><th>Cluster</th><th>Aggregate</th><th>States</th><th>Approval levels</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>02</td><td>AccountVoucher</td><td>Draft (implicit) → Posted → Verified → Cancelled (soft) → Locked (downstream)</td><td>0–1</td><td>No Draft persistence; verification is per-permission flag.</td></tr>
<tr><td>06+07</td><td>JournalApproval / BankPaymentAttempt</td><td>Pending → Approved → Initiated → Accepted → Inquiring → Settled / Failed / Reject</td><td>N (role-driven)</td><td>The richest state machine in the module. <code>IsAllowBankPaymentAttempt</code> + <code>LockLevel</code> + <code>LastInquiryStatus</code>.</td></tr>
<tr><td>10</td><td>RefundOrder / RefundOrderPayment</td><td>Pending → Approved → (Paid | Cancelled-as-Rejected)</td><td>1</td><td>Cancellation forces status = Rejected with injected remark. Once paid, refund order is immutable.</td></tr>
<tr><td>11</td><td>CashAdvanceReceipt</td><td>Open (DR) → Partially settled → Fully settled → Cancelled (soft)</td><td>0</td><td>Lock applied on first settlement, auto-cleared when last live settlement is cancelled.</td></tr>
<tr><td>15</td><td>TDSPayment + source JournalTran</td><td>Unpaid → Deposited (cascade-locks source voucher)</td><td>0</td><td><code>JournalTran.TDSPaymentTranID IS NOT NULL</code> is the system-of-record marker.</td></tr>
<tr><td>18</td><td>ExpertSession</td><td>Pending → Approved (LockLevel=N) → Completed (SessionCompletionDate) → Paid</td><td>N</td><td>Any structural edit wipes approval state and forces re-approval.</td></tr>
<tr><td>18</td><td>PHD_Remuneration</td><td>Pending → Approved → PaymentRequested → Paid → EmailSent</td><td>N</td><td>Owned by PhD module; accounting consumes <code>PaymentRequestDate</code>.</td></tr>
<tr><td>19</td><td>TRIP_Trip / TRIP_Report</td><td>Pending → Approved → (Report: Submitted → Approved / Rejected → Resubmit)</td><td>N</td><td>Rejection nulls <code>ReportSubmitDateTime</code> — the user must resubmit, chain restarts from level 0.</td></tr>
<tr><td>19</td><td>TRIP_AdvanceFund</td><td>Pending → Approved | Rejected</td><td>1</td><td>Single-level finance approval; both Approve and Reject set <code>IsSystemLocked = 1</code>.</td></tr>
</tbody>
</table>
<h3>4.1 Journal Approval → Bank Payment (Clusters 6 + 7)</h3>
<div class="mermaid">
stateDiagram-v2
[*] --> Pending : Journal posted with payee
Pending --> Approved : Final-level approver clicks Approve
Pending --> Rejected : Approver clicks Reject
Rejected --> [*]
Approved --> Initiated : User picks row, attempt SP fires
Initiated --> Accepted : HDFC returns Transaction=Accepted
Initiated --> AttemptFailed : Bank returns error code
AttemptFailed --> Approved : Operator resubmits (re-opens IsAllowBankPaymentAttempt)
Accepted --> Inquiring : Cool-off elapsed, inquiry SP fires
Inquiring --> Settled : OD_STATUS = Success + UTR captured
Inquiring --> InquiryFailure : OD_STATUS = Failure
Inquiring --> Inquiring : Pending status, re-poll
InquiryFailure --> Approved : Operator re-enables attempt
Settled --> [*]
</div>
<h3>4.2 Refund Order (Cluster 10)</h3>
<div class="mermaid">
stateDiagram-v2
[*] --> Pending : InsertFromEntry
[*] --> Approved : InsertFromRefundApplicationApproval (born Approved)
Pending --> Approved : Approver clicks Approve
Pending --> Rejected : Approver clicks Reject
Approved --> Paid : Make-payment screen + voucher posting
Approved --> CancelledAsRejected : Cancel-before-pay
Paid --> OnlineQueued : PaymentMode.IsOnlineBankPayment=1
OnlineQueued --> OnlineSettled : Inquiry success, UTR captured
Rejected --> [*]
CancelledAsRejected --> [*]
OnlineSettled --> [*]
</div>
<h3>4.3 Trip + Report (Cluster 19)</h3>
<div class="mermaid">
stateDiagram-v2
state "Trip" as Trip {
[*] --> TripPending
TripPending --> TripApproved
TripPending --> TripRejected
}
state "AdvanceFund" as Adv {
[*] --> AdvPending
AdvPending --> AdvApproved : Trip must be Approved
AdvPending --> AdvRejected
}
state "Report" as Rep {
[*] --> ReportDraft
ReportDraft --> ReportSubmitted : User submits
ReportSubmitted --> ReportApproved : Multi-level approval at final
ReportSubmitted --> ReportRejected : Approver rejects + nulls submit
ReportRejected --> ReportDraft : User resubmits (chain restarts)
ReportApproved --> [*] : Journal posted
}
</div>
<!-- ====================================================================== -->
<h2>5. Cross-cluster touchpoints</h2>
<p>
Cluster 3 (Posting Bridge) is the hub. Every source-event cluster terminates here; the
output flows to Cluster 2 (Voucher Core) and Cluster 7 (Journal). The matrix below shows
which clusters consume or produce each other; <span class="x">✓</span> = direct
SP call or FK linkage. Highlighted column = the hub.
</p>
<div style="overflow-x: auto;">
<table class="matrix-table">
<thead>
<tr>
<th>Producer ↓ / Consumer →</th>
<th>01 CoA</th><th>02 Vch</th><th class="hub">03 Brg</th><th>04 CC</th><th>05 Bnk</th><th>06 OBP</th><th>07 Jrn</th><th>15 TDS</th><th>16 GST</th><th>A Rpt</th>
</tr>
</thead>
<tbody>
<tr><td>08 PI</td><td>·</td><td>·</td><td class="x hub">✓</td><td class="x">✓</td><td class="x">✓</td><td>·</td><td class="x">✓</td><td class="x">✓</td><td class="x">✓</td><td class="x">✓</td></tr>
<tr><td>09 SI</td><td>·</td><td>·</td><td class="x hub">✓</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td><td>·</td><td class="x">✓</td><td class="x">✓</td></tr>
<tr><td>10 Refund</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td class="x">✓</td><td class="x">✓</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td></tr>
<tr><td>11 Cash Advance</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td>·</td><td>·</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td></tr>
<tr><td>12 Fund Transfer</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td class="x">✓</td><td>·</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td></tr>
<tr><td>13 Fee Collection</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td class="x">✓</td><td>·</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td></tr>
<tr><td>14 OPD Receipt</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td class="x">✓</td><td>·</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td></tr>
<tr><td>17 Expense</td><td>·</td><td>·</td><td class="x hub">✓</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td><td>·</td><td>·</td><td>·</td></tr>
<tr><td>18 Remuneration</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td class="x">✓</td><td class="x">✓</td><td class="x">✓</td><td class="x">✓</td><td>·</td><td class="x">✓</td></tr>
<tr><td>19 Trip</td><td>·</td><td>·</td><td class="x hub">✓</td><td>·</td><td class="x">✓</td><td>·</td><td class="x">✓</td><td>·</td><td>·</td><td class="x">✓</td></tr>
</tbody>
</table>
</div>
<p class="note">
Reading: <em>row produces, column consumes</em>. The hub column has the most
<span class="x">✓</span> marks because every source event ends in
<code>PR_ACC_AccountVoucher_InsertBy{Source}ID</code> or
<code>PR_ACC_Journal_InsertBy{Source}ID</code>. Cluster 1 (CoA) is read by every cluster
but does not appear here because it is a static master — the entire module reads
it.
</p>
<!-- ====================================================================== -->
<h2>6. Indian compliance summary</h2>
<p>
Eight statutes / forms / portals touch the accounting module. Status reflects
legacy completeness; each <span class="gap-badge">Gap</span> is a v1 deliverable for the
new build.
</p>
<table>
<thead><tr><th>Area</th><th>Legacy status</th><th>Detail</th></tr></thead>
<tbody>
<tr>
<td><strong>TDS sections</strong> (192 / 194A / 194C / 194H / 194I / 194J / 194Q / 194R / 194O)</td>
<td><span class="ok-badge">Supported</span></td>
<td>Section master auto-provisions liability ledger; rate stored as <code>decimal(5,2)</code> percent on <code>ACC_TDSSection</code>. PAN-4th-character mapping table drives onboarding default. Cluster 15.</td>
</tr>
<tr>
<td><strong>Lower TDS certificate</strong> (Section 197)</td>
<td><span class="partial-badge">Partial</span></td>
<td>Per-vendor fields on <code>ACC_Account</code>: <code>IsLowerTDS</code>, <code>LowerTDSPCT</code>, <code>LowerTDSFromDate</code>, <code>LowerTDSToDate</code>, <code>LowerTDSUpToAmount</code>. Applied upstream at posting; not first-class certificate entity. No history of multiple certificates.</td>
</tr>
<tr>
<td><strong>Form 26Q quarterly TDS return</strong></td>
<td><span class="gap-badge">Gap</span></td>
<td>Section-wise printable register exists (<code>RPT_ACC_TDSSection_TDSReport</code>) with PAN, TAN, section, assessable amount, deducted amount. <strong>No NSDL fixed-width / FVU file export.</strong> Accountant rekeys into RPU utility.</td>
</tr>
<tr>
<td><strong>Form 16A</strong> (quarterly per-deductee certificate)</td>
<td><span class="gap-badge">Gap</span></td>
<td>Data available; no PDF generator. New build to deliver via QuestPDF.</td>
</tr>
<tr>
<td><strong>GST rate master</strong> + per-line snapshot</td>
<td><span class="ok-badge">Supported</span></td>
<td>Per-tenant <code>ACC_GSTPCT</code> with CGST/SGST/IGST + six ledger accounts. Snapshot on each PI/SI line. Cluster 16.</td>
</tr>
<tr>
<td><strong>GSTR-1</strong> (outward supplies)</td>
<td><span class="gap-badge">Gap</span></td>
<td>Flat list report (`PP_ACC_SI_SelectForGSTRReport`) emits B2B/B2C as a tabular dump. No JSON, no GSP integration. <code>Reverse Charge</code> hard-coded `N`, `Cess Amount` hard-coded 0, no HSN summary, no CDN.</td>
</tr>
<tr>
<td><strong>GSTR-3B</strong> (monthly summary)</td>
<td><span class="partial-badge">Partial</span></td>
<td>Five-box scalar return (3.1(a), 3.2(a), 4(A)(1), 4(A)(2), 4(A)(5)) from <code>PP_ACC_SI_SelectForGSTR3BReport</code>. Boxes 3.1(b/c/.1), 4(A)(3), 4(B), 4(D), 5, 6 not computed.</td>
</tr>
<tr>
<td><strong>GSTR-9</strong> (annual)</td>
<td><span class="gap-badge">Gap</span></td>
<td>SP <code>PP_ACC_SI_SelectForGSTR9Report</code> is a stub — declares result-shape but returns zero rows. RDLC exists but is empty.</td>
</tr>
<tr>
<td><strong>e-Invoice IRN + QR</strong></td>
<td><span class="gap-badge">Gap</span></td>
<td>No IRN, AckNo, AckDate, SignedQRCode, SignedInvoice columns anywhere. No IRP integration. Mandatory for AATO > ₹5 Cr B2B today.</td>
</tr>
<tr>
<td><strong>e-Way Bill</strong></td>
<td><span class="gap-badge">Gap</span></td>
<td>Not integrated. Some transport fields (<code>TransportMode</code>, <code>VehicleNo</code>, <code>LRNo</code>, <code>LRDate</code>) on <code>ACC_PI</code> header but no portal push.</td>
</tr>
<tr>
<td><strong>Financial Year (Apr–Mar)</strong></td>
<td><span class="partial-badge">Partial</span></td>
<td>Implicit. <code>MST_FinYear</code> stores arbitrary <code>FromDate</code>/<code>ToDate</code> with free-text name. No enforced 1-Apr / 31-Mar. <code>MAX(FinYearID)+1</code> sequence. <code>IsActive</code> is decorative (no posting gate).</td>
</tr>
<tr>
<td><strong>Period close / lock</strong></td>
<td><span class="gap-badge">Critical Gap</span></td>
<td><code>GetFinalLockLevel()</code> returns <code>1</code> as a stub; no <code>ACC_*</code> SP enforces lock-date. Any user with insert rights can post any voucher dated any day. Must build first-class period-close model in new platform.</td>
</tr>
<tr>
<td><strong>Cash payment limit</strong> (§40A(3) / §269ST)</td>
<td><span class="gap-badge">Gap</span></td>
<td>No ₹10k per-person-per-day cap, no ₹2k GST cap, no ₹2L §269ST cap. Cluster 11 and Cluster 8 do not enforce.</td>
</tr>
<tr>
<td><strong>i18n / RAISERROR strings</strong></td>
<td><span class="gap-badge">Gap</span></td>
<td>124 user-visible strings via <code>THROW 50001</code> + <code>THROW 500001</code> + <code>THROW 51000</code>, all English, HTML-tagged. Catalogued in cross-D. New build maps to ProblemDetails type URIs + HTTP status 400/409/422/423/404 by category.</td>
</tr>
<tr>
<td><strong>UTR + NEFT/RTGS/IMPS</strong></td>
<td><span class="ok-badge">Supported</span></td>
<td>Classification by IFSC-prefix + amount thresholds (₹2L NEFT↔RTGS legacy threshold — RBI removed it in 2019). UTR captured on <code>JournalTran.UTRNo</code>. PennyDrop verification via EaseBuzz.</td>
</tr>
<tr>
<td><strong>Bank statement import</strong> (MT940 / OFX / camt.053)</td>
<td><span class="gap-badge">Gap</span></td>
<td>Reconciliation is fully manual on <code>ACC_AccountVoucherTran_BankReconcileVerification.aspx</code>. No statement adapter.</td>
</tr>
<tr>
<td><strong>Schedule III statutory financials</strong></td>
<td><span class="gap-badge">Gap</span></td>
<td>No Trial Balance, Balance Sheet, Profit & Loss, Receipts & Payments as RDLC. Likely driven from ledger SP + COA roll-up on screen only.</td>
</tr>
<tr>
<td><strong>Multi-GSTIN per company</strong></td>
<td><span class="gap-badge">Gap</span></td>
<td>One GSTIN per <code>MST_Company</code>. Multi-state branches require multiple companies in legacy.</td>
</tr>
</tbody>
</table>
<!-- ====================================================================== -->
<h2>7. Tenant variation surface</h2>
<p>
Per-tenant configurable behaviour. Sources: <code>ACC_AccountingConfiguration</code> (23
columns, scoped by Company + Institute), <code>MST_Company</code> accounting subset, and
a small set of static-class constants (<code>CV_Accounting.*</code>) that must move into
DB rows for the new platform. Tenant variation is hard rule #12 — this list must be
surfaced as typed settings, not free-text columns.
</p>
<table>
<thead><tr><th>Flag / setting</th><th>Type</th><th>Drives feature in cluster(s)</th></tr></thead>
<tbody>
<tr><td><code>OnlineCollectionBasedOn</code></td><td>nvarchar(200)</td><td>06 — online-payment-receipt routing model</td></tr>
<tr><td><code>NoOfDaysAllowedForReconcile</code></td><td>int</td><td>05 — sliding window for bank reconciliation</td></tr>
<tr><td><code>BillRequirmentStatusForManualPayment</code></td><td>{Required / Optional / NotRequired}</td><td>02, 07 — manual payment requires bill attachment</td></tr>
<tr><td><code>BillRequirmentStatusForBillEntry</code></td><td>{Required / Optional / NotRequired}</td><td>08 — vendor bill capture requires attachment</td></tr>
<tr><td><code>BillRequirmentStatusForBillPayment</code></td><td>{Required / Optional / NotRequired}</td><td>08 — PI payment requires attachment</td></tr>
<tr><td><code>BillRequirmentStatusForJournalPayee</code></td><td>{Required / Optional / NotRequired}</td><td>02, 07 — journal payee entry requires attachment</td></tr>
<tr><td><code>BillRequirmentStatusForVendorBill</code></td><td>{Required / Optional / NotRequired}</td><td>08 — vendor-bill workflow attachment</td></tr>
<tr><td><code>Accounting_IsGSTVerificationRequired</code></td><td>bit</td><td>07, 08 — refuse payment to vendor whose GSTIN status != Active</td></tr>
<tr><td><code>Accounting_IsSetGlobalCompanyGroup</code></td><td>bit</td><td>13, 14 + most lists — force pick-company-group modal before any list/edit</td></tr>
<tr><td><code>Accounting_IsAccountingEffectForRefundOrderPayment</code></td><td>bit</td><td>10 — whether refund-payment posts a voucher (vs FEE-side only)</td></tr>
<tr><td><code>Accounting_IsFeeHeadWiseSeparateAccountingAllowed</code></td><td>bit</td><td>13 — enables IsFeeHeadWiseSeparateDeposit UI</td></tr>
<tr><td><code>ACC_IsShowAccountLedgerDetailedView</code></td><td>role-operation</td><td>A — ledger report shows JournalTranID column</td></tr>
<tr><td><code>IsTDSInBillEntry</code></td><td>{Yes / No}</td><td>08, 15 — TDS captured at PI entry vs at PI payment (UI dropdown; column not in extract — open question)</td></tr>
<tr><td><code>SVF_ACC_IsAllowCashPaymentInBackDate</code></td><td>bit</td><td>02 — relax back-date restriction on Cash Payment voucher</td></tr>
<tr><td><code>ACC_Get_IsStudentNamesInFeeCollectionVoucher</code></td><td>bit</td><td>13 — inline student enrollment numbers in deposit-slip voucher narration</td></tr>
<tr><td><code>ACC_Get_IsLockRefundOrderVoucher</code></td><td>bit</td><td>10 — whether refund voucher is system-locked post-post (stub: returns 1)</td></tr>
<tr><td><code>MST_Company.IsCostCentreApplicable</code></td><td>bit</td><td>04, 08 — require cost-centre allocation on bills</td></tr>
<tr><td><code>MST_Company.IsExpenseDistribution</code></td><td>bit</td><td>09, 17 — SI swaps single sales account for CC distribution; Expense uses Campus/Institute/Faculty/Dept split</td></tr>
<tr><td><code>MST_Company.OpeningDate</code></td><td>date</td><td>02 — implicit floor on voucher date (never enforced today)</td></tr>
<tr><td>Voucher print templates (5 paths + 5 upload IDs)</td><td>file</td><td>A, 02, 08, 11 — per-tenant HTML print templates per document type</td></tr>
<tr><td><code>Accounting_OBP_PaymentEnvironment</code> + 16 keys per env</td><td>config</td><td>06 — HDFC OBP URLs, OAuth creds, JOSE key paths, KIDs, LOGIN_ID, GCIF</td></tr>
<tr><td><code>FEE_PaymentGateway</code> rows</td><td>table</td><td>B — per-tenant per-environment merchant ID/key/salt/URLs for 12+ inbound gateways</td></tr>
<tr><td>Voucher numbering format (<code>CFG_VoucherConfig</code>)</td><td>per-(Company, FY, VoucherType)</td><td>02, 12 — prefix + width + reset-policy + numbering method (Auto/Manual)</td></tr>
<tr><td>10-day ContraEntryDate window</td><td>currently hard-coded</td><td>13 — ContraEntryDate − ReceiptDate ≤ 10 days (move to per-tenant config)</td></tr>
<tr><td>NEFT/RTGS amount thresholds</td><td>currently hard-coded ₹2L</td><td>06, 07 — classification threshold (RBI removed limit in 2019; legacy still encodes it)</td></tr>
</tbody>
</table>
<!-- ====================================================================== -->
<h2>8. Integration surface</h2>
<p>
Twenty-three external integration points across outbound and inbound directions. Source:
<a href="clusters/cross-B-integrations.md"><code>cross-B-integrations.md</code></a>.
</p>
<h3>Outbound (money / data leaves)</h3>
<table>
<thead><tr><th>Rail</th><th>Direction</th><th>Wire</th><th>Idempotency key</th><th>Status</th></tr></thead>
<tbody>
<tr><td><strong>HDFC CBX</strong> corporate banking</td><td>Payment initiate + inquiry poll</td><td>REST / JOSE — JWS (RS256) wrapped in JWE (RSA-OAEP-256 / A256GCM); mTLS X.509 PFX</td><td><code>PAYMENT_REF_NO</code> (client) + <code>CBX_API_REF_NO</code> (bank)</td><td><span class="ok-badge">Functional</span></td></tr>
<tr><td>ICICI / Axis / SBI / Yes / Kotak corporate APIs</td><td>—</td><td>—</td><td>—</td><td><span class="gap-badge">Not present</span></td></tr>
<tr><td>Tally Prime</td><td>Voucher / day-book export</td><td>Excel file dropped into <code>Upload/TallyIntegration/</code></td><td>n/a (filename timestamp)</td><td><span class="partial-badge">Stub — one historical sample</span></td></tr>
<tr><td>GSTN portal (GSTR-1 / GSTR-3B / GSTR-9)</td><td>Return push</td><td>None — RDLC printed / Excel re-keyed manually</td><td>n/a</td><td><span class="gap-badge">Offline only</span></td></tr>
<tr><td>NSDL / TIN-FC (24Q / 26Q)</td><td>Quarterly return</td><td>FVU file generated externally via RPU utility</td><td>n/a</td><td><span class="gap-badge">Offline only</span></td></tr>
<tr><td>NIC e-Invoice IRP (IRN + QR)</td><td>—</td><td>—</td><td>—</td><td><span class="gap-badge">Not present</span></td></tr>
<tr><td>e-Way Bill portal</td><td>—</td><td>—</td><td>—</td><td><span class="gap-badge">Not present</span></td></tr>
<tr><td>Cheque print (physical)</td><td>PDF / printer</td><td>GDI+ template positioned over pre-printed stock; or HTML template</td><td>Cheque number from book</td><td><span class="ok-badge">Functional</span></td></tr>
</tbody>
</table>
<h3>Inbound (money / data arrives)</h3>
<table>
<thead><tr><th>Provider</th><th>Wire</th><th>Idempotency</th><th>Refund</th></tr></thead>
<tbody>
<tr><td>Razorpay</td><td>REST + HTML POST redirect; HMAC-SHA256</td><td><code>razorpay_order_id</code> + <code>MerchantTransactionID</code></td><td>API</td></tr>
<tr><td>PayU Biz</td><td>HTML POST; SHA-512 hash</td><td><code>MerchantTransactionID</code></td><td>API</td></tr>
<tr><td>SBI ePay</td><td>HTML POST; AES-256 encrypted, pipe-delim response</td><td><code>MerchantTxnID</code></td><td>Manual</td></tr>
<tr><td>CCAvenue</td><td>HTML POST; AES encrypted JSON</td><td><code>MerchantTxnID</code></td><td>orderStatusQuery</td></tr>
<tr><td>Cashfree</td><td>SDK + REST; encrypted return_url</td><td><code>MerchantTransactionID</code></td><td>Webhook + API</td></tr>
<tr><td>EaseBuzz</td><td>HTML POST; hash</td><td><code>MerchantTxnID</code></td><td>API</td></tr>
<tr><td>Paytm</td><td>JSON POST; checksum</td><td><code>ORDERID</code></td><td>Manual</td></tr>
<tr><td>PayPhi</td><td>HTML POST + hash</td><td><code>MerchantTxnID</code></td><td>Manual</td></tr>
<tr><td>Pine Labs (Plural) v2.1</td><td>REST; SDK hash</td><td><code>MerchantOrderID</code></td><td>Refund-Inquiry API</td></tr>
<tr><td>Qfix</td><td>HTML POST + hash</td><td><code>MerchantTxnID</code></td><td>Manual</td></tr>
<tr><td>Edviron</td><td>REST</td><td><code>MerchantTxnID</code></td><td>Manual</td></tr>
<tr><td>GrayQuest (EMI)</td><td>REST</td><td><code>MerchantTxnID</code></td><td>Manual</td></tr>
<tr><td>EasyPay</td><td>HTML POST + hash</td><td><code>MerchantTxnID</code></td><td>Manual</td></tr>
<tr><td>Cash Deposit Machine (ProNote VM)</td><td>JSON via JavaScript bridge; response codes 0..34</td><td>Device <code>MachineId</code> + session</td><td>n/a</td></tr>
<tr><td>EaseBuzz PennyDrop / PAN / GSTIN verification</td><td>REST POST; SHA-512 hash auth</td><td><code>APIRequestNo = UserID_ddMMyyHHmmssfff</code></td><td>n/a</td></tr>
<tr><td>TRACES (Form 16 Part A)</td><td>Excel upload (TRACES download manual)</td><td><code>PAN + AssessmentYear</code></td><td>n/a</td></tr>
<tr><td>Bank statement (MT940 / OFX / camt.053)</td><td>None — manual reconciliation only</td><td>n/a</td><td>n/a <span class="gap-badge">Gap</span></td></tr>
</tbody>
</table>
<p class="note">
Credential storage is fragmented: per-tenant DB rows for PG keys, static-class constants
for HDFC OBP URLs/keys, web.config for some PayU keys, file system for HDFC PFX with a
Base64URL-encoded sidecar password, and the literal string <code>"PU@123"</code>
hard-coded as a fallback in three OBP files. New platform must consolidate into a single
tenant-scoped vault.
</p>
<!-- ====================================================================== -->
<h2>9. Reports and dashboards inventory</h2>
<p>
Two output surfaces: RDLC printable reports (16 files, ~58 KLOC of XML) and HTML
dashboards (6 ASPX pages, ~2.6 KLOC of code-behind). New platform replaces RDLC with
QuestPDF and ASPX dashboards with React widgets. Source: <a
href="clusters/cross-A-reports.md"><code>cross-A-reports.md</code></a>.
</p>
<h3>Printable reports</h3>
<table>
<thead><tr><th>Report</th><th>Category</th><th>Driving SP</th></tr></thead>
<tbody>
<tr><td>Day Book / Cash Book / Bank Book Register</td><td>Operational</td><td><code>PP_ACC_AccountVoucher_SelectForDayBookRegister</code></td></tr>
<tr><td>Account Ledger Print (Portrait + Landscape)</td><td>Operational</td><td><code>PR_ACC_Account_SelectLedgerByAccountID</code></td></tr>
<tr><td>Opening Balance Register</td><td>Operational</td><td><code>PR_ACC_Account_SelectOpeninBalance</code></td></tr>
<tr><td>Cash & Bank Balance Details</td><td>Operational</td><td><code>PP_ACC_AccountVoucher_SelectForCashBankBalanceDetails</code></td></tr>
<tr><td>Cash-in-Hand Report</td><td>Operational</td><td><code>PP_ACC_Journal_SelectForCashInHandReport</code></td></tr>
<tr><td>Negative Cash Report</td><td>Operational / audit</td><td><code>PR_ACC_Journal_SelectForNegativeCashReport</code></td></tr>
<tr><td>Bank Reconciliation Statement</td><td>Operational</td><td><code>PR_ACC_AccountVoucherTran_SelectByDateAccountIDIsReconciledCompanyID</code></td></tr>
<tr><td>Cheque Book Details</td><td>Operational</td><td><code>PP_ACC_Cheque_SelectForChequeBookDetails</code></td></tr>
<tr><td>Aging Report (Vendor / Customer)</td><td>Operational</td><td><code>PR_ACC_PIForAccountingTran_SelectForAgingReport</code></td></tr>
<tr><td>Cash Advance Outstanding / Settlement Register</td><td>Operational</td><td><code>PR_ACC_CashAdvanceReceipt_SelectForAdvanceRegister</code></td></tr>
<tr><td>TDS Section-wise Register (feeds 26Q draft)</td><td>Statutory</td><td><code>PR_ACC_TDSSection_SelectForTDSReport</code></td></tr>
<tr><td>Trip Expense Report (Trip / Expense / Advance / CSV)</td><td>Operational</td><td><code>PR_ACC_TRIP_Expense_SelectForExpenseReport</code></td></tr>
<tr><td>Sales Invoice (GST tax invoice format)</td><td>Statutory</td><td><code>PP_ACC_SI_SelectForPrint</code></td></tr>
<tr><td>GSTR-3B preview (5 boxes)</td><td>Statutory</td><td><code>PP_ACC_SI_SelectForGSTR3BReport</code></td></tr>
<tr><td>GSTR-9 preview (annual)</td><td>Statutory — stub</td><td><code>PP_ACC_SI_SelectForGSTR9Report</code> <span class="gap-badge">Returns 0 rows</span></td></tr>
<tr><td>Cost Centre Report + Distribution Report (Excel only)</td><td>Operational</td><td><code>PR_ACC_CostCentre_SelectForCostCentreReport</code></td></tr>
</tbody>
</table>
<h3>Dashboards</h3>
<table>
<thead><tr><th>Dashboard</th><th>Audience</th><th>Result sets</th></tr></thead>
<tbody>
<tr><td><code>ACC_Account_Dashboard</code></td><td>CFO / finance head</td><td>5 — voucher counts, bank reconcile, fund transfer, user-wise activity, cancelled cheque</td></tr>
<tr><td><code>ACC_AccountingMaintainanceDashboard</code></td><td>Global admin / period-close checker</td><td>12 — anomaly buckets (voucher-vs-journal mismatch, FY drift, duplicate fee / refund / online payment, voucher with no tran, …)</td></tr>
<tr><td><code>ACC_BankPaymentAttempt_ManagementDashboardV2</code></td><td>AP / payments clerk</td><td>8 — today vs 7-day funnel, inquiry status, payment-mode split (NEFT/RTGS/FT), approval pipeline, top-10 expense + party</td></tr>
<tr><td><code>ACC_CostCentre_ManagementDashboard</code></td><td>Cost-centre / budget owner</td><td>5 — budget vs actual, top projects, party-account top-10 pending, month-wise trend, utilisation + efficiency KPIs</td></tr>
<tr><td><code>ACC_TRIP_TripManagementDashboard</code></td><td>Travel admin / HR-finance</td><td>5 — trip counts + approval funnel, month-wise advance-vs-expense, country × category, top-10 users, top-10 countries</td></tr>
</tbody>
</table>
<p class="note">
Statutory reports MISSING from legacy and required for v1: <strong>Trial Balance,
Balance Sheet (Schedule III), Profit & Loss / Income & Expenditure, Receipts &
Payments, GSTR-1 (in JSON), GSTR-2A/2B reconciliation, NSDL 26Q FVU export, Form 16A
generator, e-Invoice IRN + QR.</strong>
</p>
<!-- ====================================================================== -->
<h2>10. Open design decisions for new build</h2>
<p>
Aggregated and ranked from per-cluster open-questions. These are the most consequential
decisions to settle before the build phase opens. Numbered for ticket traceability.
</p>
<ol>
<li>
<strong>Period close model.</strong> Build an explicit <code>AccountingPeriod</code>
aggregate with <code>{Draft, Open, SoftClosed, HardClosed, Archived}</code>; soft-close
warns + permits override with audit; hard-close blocks. Granularity = Month + Quarter
+ Year. <em>Legacy has none of this — cross-cut C critical gap.</em>
</li>
<li>
<strong>FY model.</strong> First-class entity with canonical name <code>FY YYYY-YY</code>,
Postgres <code>EXCLUDE USING gist daterange</code> overlap constraint, auto-derive
FinYearID from VoucherDate server-side (do not accept from client). Auto-generate four
quarters + twelve months on FY creation. <em>Legacy lets client pass any FinYearID
without re-derivation.</em>
</li>
<li>
<strong>Multi-company unit.</strong> Continue with DB-per-tenant (hard rule #3) and
keep <code>CompanyID</code> on every voucher for intra-tenant multi-entity? Or
DB-per-company? Inter-company bridge accounts (<code>MST_Company.AccountID</code>) are
load-bearing for trusts — the new design must keep that pattern.
</li>
<li>
<strong>Voucher numbering.</strong> Replace <code>COUNT(*)+1</code> /
<code>MAX(ID)+1</code> patterns (in <code>PR_ACC_SI_GetSINo</code>,
<code>PR_ACC_FundTransferTo_InsertFromFundTransfer</code>, cash-advance per-day
counter, expert-session XML cursor) with Postgres sequences per (Tenant, Company, FY,
VoucherType). Manual numbering still supported via <code>NumberingMethod='M'</code>.
</li>
<li>
<strong>Posting bridge architecture.</strong> 20+ legacy posters each ~1k lines.
Replace with one canonical <code>IPostingService</code> + per-source <code>SourceEvent</code>
handlers raising domain events; same in-process dispatcher (no MediatR per global
directive). Cross-company contra journals become a first-class concern.
</li>
<li>
<strong>System-lock semantics.</strong> Replace boolean <code>IsSystemLocked</code> +
free-text HTML <code>SystemLockedMessage</code> on every aggregate with a typed lock
reason enum + structured payload. Derive lock state from explicit state machine, not
from a stored flag with drift risk.
</li>
<li>
<strong>Audit model.</strong> Single event-sourced audit stream (hard rule #8) replaces
all <code>LOG_*</code> + <code>LOJ_*</code> per-table shadow tables. ~40 LOJ tables
across the module today. Use Marten event sourcing for audit-critical aggregates per
backend conventions.
</li>
<li>
<strong>TDS rate versioning + thresholds.</strong> Date-versioned
<code>TDSSectionRate (FromDate, ToDate, Rate)</code>; per-section threshold table with
both single-bill and aggregate-FY caps + per-PAN-entity-type split for 194C; auto-apply
20% under §206AA for missing/invalid PAN.
</li>
<li>
<strong>Lower-TDS certificate.</strong> First-class entity
<code>LowerTDSCertificate (VendorAccountID, SectionID, Rate, FromDate, ToDate,
MaxAmount, CertificateNumber, CertificateDate, ITOName)</code> supporting multiple
historical certificates. Pro-rata over partial-period validity. <em>Legacy stores on
ACC_Account — only one cert per vendor.</em>
</li>
<li>
<strong>NSDL 26Q / Form 16A generators.</strong> Build native exporters: per-quarter
Form 26Q producing the NSDL fixed-width TXT file + Form 27A challan summary; Form 16A
PDFs per quarter per deductee via QuestPDF. Replaces "rekey into RPU utility" workflow.
</li>
<li>
<strong>GST scope for v1.</strong> Decide: GSTR-1 JSON export + GSP integration (e.g.
ClearTax) day-one, or only the GSTR-3B preview? RCM flag at slab + vendor + HSN level?
Multi-GSTIN per company (one company, many state locations) or one company per GSTIN
(legacy)?
</li>
<li>
<strong>e-Invoice IRN.</strong> Synchronous to invoice issue or async with separate
state machine (<code>{Draft, IRNRequested, IRNAssigned, IRNCancelled}</code>)?
Mandatory for AATO > ₹5 Cr B2B — cannot be "future feature".
</li>
<li>
<strong>Cheque lifecycle.</strong> Promote from flat
<code>{Blank, Used, Cancelled}</code> to full state machine
<code>{Blank, Issued, Presented, Cleared, Bounced, Stopped, Cancelled}</code> wired to
bank-statement import + post-dated holding. <em>Legacy has no Bounced / Stopped /
Post-dated.</em>
</li>
<li>
<strong>Signatory model.</strong> Replace single <code>AuthorizedPersonName</code>
string on <code>ACC_ChequeTemplate</code> with multi-signatory master per bank account
with order + joint-signing rule + threshold-based escalation. Tenant feature flag for
small institutes.
</li>
<li>
<strong>Online bank rails.</strong> Extend beyond HDFC CBX. Adapter pattern per
bank (ICICI iConnect, Axis CIB, SBI YONO Business, Yes Bank, Kotak BAAS). Each has its
own crypto envelope — design needs sufficient generality without coupling.
Webhook receiver hub (signature-verifying, queued) for banks that webhook (no current
rail does).
</li>
<li>
<strong>Secret management.</strong> Migrate PFX certificates + passwords, OAuth
creds, EaseBuzz key/salt, PG keys out of file system + static constants + web.config
into a tenant-scoped vault (AWS KMS / Azure Key Vault / HashiCorp Vault / per-tenant
Postgres column with envelope encryption). Remove the literal <code>"PU@123"</code>
fallback. Rotation policy.
</li>
<li>
<strong>Tenant clock + timezone.</strong> Replace <code>GetPUMISDate()</code>
(server <code>GETDATE()</code>) with a <code>TenantClock</code> service: timezone-aware
(default <code>Asia/Kolkata</code>), mockable in tests, supports an <code>AsOf</code>
override during period-close finalisation and during bulk legacy migration.
</li>
<li>
<strong>Cash payment caps (§269ST / §40A(3)).</strong> Enforce per-tenant
configurable cap with warn / block policy on Cluster 11 (Cash Advance) + Cluster 17
(Expense) + Cluster 2 (Voucher CP/CR). Per-day-per-person aggregation.
</li>
<li>
<strong>Approval framework consolidation.</strong> Six clusters (06, 07, 09, 18, 19,
cross-C) use multi-level approval via <code>SEC_ApprovalStructure</code> +
<code>DAT_Approval</code>. Build a single generic <code>IApprovalWorkflow<TSubject></code>
primitive instead of per-cluster copy-paste. Replace the
<code>GetFinalLockLevel() = 1</code> stub with real per-operation configuration.
</li>
<li>
<strong>Payment gateway consolidation.</strong> Twelve+ inbound PG adapters with
copy-paste callback ASPX pages. Replace with a single
<code>/api/v1/payments/{provider}/callback</code> endpoint + provider-catalogue
master + adapter SDK shape (Initiate / HandleCallback / Verify / Refund). Decide
whether to drop direct PG integration in favour of a single aggregator
(Razorpay Route / Cashfree Connect) and lose per-tenant choice.
</li>
<li>
<strong>i18n architecture.</strong> Extract 124 catalogued strings into
<code>accounting.{locale}.json</code> resource files. API returns
<code>ProblemDetails.type</code> URI + structured extensions; frontend localises via
i18next. No <code>IStringLocalizer<></code> in API. Per-tenant override layer for
tone (hard rule #12).
</li>
<li>
<strong>Bank statement import.</strong> First-class adapter for camt.053 / MT940 / OFX
+ per-Indian-bank CSV variants. Matcher engine on (amount + UTR + date). Surfaces
unmatched lines for manual reconciliation. <em>Legacy is fully manual entry.</em>
</li>
<li>
<strong>Schedule III statements.</strong> Build Trial Balance, Balance Sheet, Profit
& Loss, Receipts & Payments as first-class reports with grouping-level
parameters (group / sub-group / account / sub-account), summary + detail modes. Drive
from a single <code>TrialBalanceGenerate(CompanyID, FromDate, ToDate)</code> projection.
</li>
<li>
<strong>FieldKey strategy (hard rule #11).</strong> Map legacy column-set states
(e.g. <code>ApprovalStatus</code>, <code>CRDRType</code>, <code>FundTransferType</code>,
<code>DistributionType</code>, <code>PaymentType</code>) to stable
<code>FieldKey</code>-backed enums so per-tenant variation (labels, allowed values)
layers on without breaking historical data.
</li>
<li>
<strong>Reverse-entry vs in-place edit.</strong> Several clusters (08, 09, 10, 13, 14,
15, 19) use delete-and-rewrite for the GL voucher on every update. Decide whether the
new design retains this (operationally simple, but breaks audit chain on referenced
voucher numbers) or switches to compensating reversal entries (Indian audit
convention).
</li>
<li>
<strong>Multi-currency.</strong> Several aggregates (refund order, fee receipt, trip
advance) already carry <code>CurrencyID</code>. Decide whether the new design supports
a non-INR base currency per tenant or per company, or stays INR-only as legacy
effectively does. FX rate snapshotting model (per-event vs per-day rate table).
</li>
<li>
<strong>Dashboard refresh + materialisation.</strong> Legacy dashboards do
single-query multi-resultset (~5–12 result sets per dashboard) and never