Skip to content

Commit 85e4872

Browse files
author
Jani Giannoudis
committed
Adopt ES.Nomina conventions: TC naming, script split, JSON split, README structure
1 parent eaec396 commit 85e4872

18 files changed

+735
-122
lines changed

README.md

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,31 @@ the calculation logic itself changes.
5757
Regulation.{CC}.{Name}/
5858
{Year}/
5959
Regulation/
60-
{CC}.{Name}.Cases.{Year}.json
61-
{CC}.{Name}.Collectors.{Year}.json
60+
{CC}.{Name}.{Year}.json
6261
{CC}.{Name}.Scripts.{Year}.json
63-
{CC}.{Name}.WageTypes.{Year}.json
62+
{CC}.{Name}.Collectors.{Year}.json
63+
{CC}.{Name}.Cases.Company.{Year}.json
64+
{CC}.{Name}.Cases.Employee.Core.{Year}.json
65+
{CC}.{Name}.Cases.Employee.{Scope}.{Year}.json (optional: additional splits)
66+
{CC}.{Name}.WageTypes.Guard.{Year}.json
67+
{CC}.{Name}.WageTypes.Gross.{Year}.json
68+
{CC}.{Name}.WageTypes.Deductions.{Year}.json
69+
{CC}.{Name}.WageTypes.Employer.{Year}.json
6470
Scripts/
65-
WageTypeValueFunction.Action.cs Custom actions (WageTypeValueAction)
66-
CaseValidateFunction.Action.cs Custom actions (CaseValidateAction)
67-
{CC}{Helper1}.cs {Description} (also unit-tested)
68-
{CC}{Helper2}.cs {Description}
71+
WageTypeValueFunction.Shared.Action.cs Shared helper methods (no action attributes)
72+
WageTypeValueFunction.Guard.Action.cs Guard actions (WT 1–9)
73+
WageTypeValueFunction.{Scope}.Action.cs Domain actions (Gross, Deductions, Employer, …)
74+
CaseValidateFunction.Action.cs CaseValidate actions
75+
{CC}{Domain}Algorithm.cs Pure algorithm classes (unit-testable)
6976
Tests/
7077
{CC}.Test.Setup.json
7178
{CC}.Test.CompanyCases.json
72-
Tests/ Individual test cases (WT-TC*, GUARD-TC*)
73-
Tests.Unit/ xUnit unit tests for algorithm classes
79+
WT-TC{nn}-{CC}-{Scope}/ Wage type test cases
80+
GUARD-TC{n}-{CC}-{Scope}/ Guard test cases
81+
Tests.Unit/ xUnit tests for algorithm classes
7482
Reports/
75-
{ReportFolder1}/
76-
{ReportFolder2}/
83+
{ReportFolder}/
84+
README.md
7785
Setup.pecmd
7886
Test.All.pecmd
7987
Data.{Source1}.{Year}/
@@ -121,19 +129,26 @@ Regulation.{CC}.{Name}/
121129

122130
## Custom Actions
123131

124-
### WageType Actions (`Scripts/WageTypeValueFunction.Action.cs`)
132+
### WageType Actions
133+
134+
Actions are split across domain files in `Scripts/`:
135+
136+
| File | Scope | Description |
137+
|:---|:---|:---|
138+
| `WageTypeValueFunction.Guard.Action.cs` | Guards (WT 1–9) | Abort on missing fields/lookups |
139+
| `WageTypeValueFunction.Shared.Action.cs` | Helpers | Private methods, no action attributes |
140+
| `WageTypeValueFunction.{Scope}.Action.cs` | Domain | Replace with actual domain name |
125141

126142
| Action | WT | Description |
127143
|:---|---:|:---|
128-
| `{CC}GuardMandatoryFields` | 1 | Validates {Field1} > 0, {Field2} set; aborts on failure |
129-
| `{ActionName}` | {nr} | {short description} |
144+
| `{CC}GuardMandatoryFields` | 1 | Validates {Field1} > 0, {Field2} set, Lookup[{Year}] exists; AbortExecution on failure |
145+
| `{CC}Calculate{WageTypeName}` | {nr} | {short description} |
130146

131147
### Case Validate Actions (`Scripts/CaseValidateFunction.Action.cs`)
132148

133149
| Action | Case | Description |
134150
|:---|:---|:---|
135-
| `{ValidateAction1}` | `{CC}.{Case1}` | {short description} |
136-
| `{ValidateAction2}` | `{CC}.{Case2}` | {short description} |
151+
| `{CC}ValidateNationalId` | `{CC}.{Case1}` | {short description} |
137152

138153
---
139154

TEMPLATE.md

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ YYYY/Tests/CC.Test.CompanyCases.json → 2026/Tests/DE.Test.CompanyCases.
6363
Test.YYYY.pecmd → Test.2026.pecmd
6464
```
6565

66+
Rename test folders (replace `{CC}`, `{nn}`, `{Scope}` with actual values):
67+
```
68+
YYYY/Tests/WT-TC{nn}-{CC}-{Scope}/ → 2026/Tests/WT-TC1000-DE-BaseSalary/
69+
YYYY/Tests/GUARD-TC{n}-{CC}-{Scope}/ → 2026/Tests/GUARD-TC1-DE-MandatoryFields/
70+
```
71+
72+
Rename script files (replace `{Scope}` and `{Domain}` with actual domain names):
73+
```
74+
YYYY/Scripts/WageTypeValueFunction.{Scope}.Action.cs → 2026/Scripts/WageTypeValueFunction.Gross.Action.cs
75+
YYYY/Scripts/{CC}{Domain}Algorithm.cs → 2026/Scripts/DE{Domain}Algorithm.cs
76+
```
77+
6678
Update `.sln`: replace `YYYY` folder references and `.csproj` filenames throughout.
6779

6880
### 3. Configure `YYYY/Directory.Build.props`
@@ -80,8 +92,26 @@ Update `.sln`: replace `YYYY` folder references and `.csproj` filenames througho
8092
```
8193

8294
### 5. Configure `YYYY/regulation-package.json`
83-
Update `packageId`, `regulationName`, and `installFiles` order.
84-
Scripts must be listed before Cases and WageTypes.
95+
Update `packageId`, `regulationName`, and `installFiles`.
96+
97+
Scripts must be listed **before** Cases and WageTypes (PE processes files in order).
98+
99+
Split Cases and WageTypes into separate files by domain:
100+
```json
101+
"installFiles": [
102+
"Regulation/{CC}.{RegulationName}.{YYYY}.json",
103+
"Regulation/{CC}.{RegulationName}.Scripts.{YYYY}.json",
104+
"Regulation/{CC}.{RegulationName}.Collectors.{YYYY}.json",
105+
"Regulation/{CC}.{RegulationName}.Cases.Company.{YYYY}.json",
106+
"Regulation/{CC}.{RegulationName}.Cases.Employee.Core.{YYYY}.json",
107+
"Regulation/{CC}.{RegulationName}.WageTypes.Guard.{YYYY}.json",
108+
"Regulation/{CC}.{RegulationName}.WageTypes.Gross.{YYYY}.json",
109+
"Regulation/{CC}.{RegulationName}.WageTypes.Deductions.{YYYY}.json",
110+
"Regulation/{CC}.{RegulationName}.WageTypes.Employer.{YYYY}.json"
111+
]
112+
```
113+
114+
Add further `Cases.Employee.{Scope}` or `WageTypes.{Scope}` splits as needed.
85115

86116
### 6. Configure `YYYY/Regulation.CC.RegulationName.YYYY.csproj`
87117
Update `PackageId`, `Description`, and `PackageTags`.
@@ -107,28 +137,73 @@ Copy `PayrollEngine.Exchange.schema.json` into:
107137
### 10. Create `YYYY/Docs/`
108138
Add analysis and design documentation:
109139
```
110-
YYYY/Docs/{CC}.{RegulationName}-Analysis.md — system analysis, regulation overview
111-
YYYY/Docs/{CC}.{RegulationName}-NoCodeDesign.md — No-Code/Low-Code action specification
112-
YYYY/Docs/{CC}.{RegulationName}-TestSpec.md — test case calculations with source references
140+
YYYY/Docs/{CC}.{RegulationName}-Analysis.md — system analysis, regulation overview
141+
YYYY/Docs/{CC}.{RegulationName}-NoCodeDesign.md — No-Code/Low-Code action specification
142+
YYYY/Docs/{CC}.{RegulationName}-TestSpec.md — test case calculations with source references
143+
YYYY/Docs/{CC}.{RegulationName}-UpdateWorkflow.md — year-over-year update process
113144
```
114145

115146
### 11. Implement regulation objects
116147
Follow the [Country Bootstrap Guide](https://github.com/Payroll-Engine/Regulation.COM.Base/blob/main/Docs/Country-Bootstrap.md).
117148

118149
Implement JSON files in `YYYY/Regulation/`:
119-
- `{CC}.{RegulationName}.{YYYY}.json` — regulation definition (name, attributes)
120-
- `{CC}.{RegulationName}.Scripts.{YYYY}.json` — script references
150+
- `{CC}.{RegulationName}.{YYYY}.json` — regulation definition (name, namespace, validFrom)
151+
- `{CC}.{RegulationName}.Scripts.{YYYY}.json` — script registrations (see Step 11a)
121152
- `{CC}.{RegulationName}.Collectors.{YYYY}.json` — collector definitions
122-
- `{CC}.{RegulationName}.Cases.{YYYY}.json` — employee + company case definitions
123-
- `{CC}.{RegulationName}.WageTypes.{YYYY}.json` — wage type definitions with actions
153+
- `{CC}.{RegulationName}.Cases.Company.{YYYY}.json` — company case definitions
154+
- `{CC}.{RegulationName}.Cases.Employee.Core.{YYYY}.json` — core employee cases
155+
- `{CC}.{RegulationName}.Cases.Employee.{Scope}.{YYYY}.json` — additional employee case splits
156+
- `{CC}.{RegulationName}.WageTypes.Guard.{YYYY}.json` — guard WTs (WT 1–9)
157+
- `{CC}.{RegulationName}.WageTypes.Gross.{YYYY}.json` — gross income WTs
158+
- `{CC}.{RegulationName}.WageTypes.Deductions.{YYYY}.json` — employee deduction WTs
159+
- `{CC}.{RegulationName}.WageTypes.Employer.{YYYY}.json` — employer cost WTs
124160

125161
Implement data file in `Data.Tax.YYYY/Regulation/`:
126162
- `{CC}.{RegulationName}.Data.Tax.{YYYY}.json` — tax brackets and rates as lookups
127163

128-
### 12. Update `YYYY/Tests/TC01/TC01-BaseSalary.et.json`
129-
Replace case field names with actual field names from your regulation.
130-
Calculate and fill in the expected `wageTypeResults` and `collectorResults`.
131-
Document the derivation in `YYYY/Tests/TC01/README.md`.
164+
### 11a. Register scripts in `Scripts.{YYYY}.json`
165+
166+
Every `.cs` file in `YYYY/Scripts/` must be registered in
167+
`{CC}.{RegulationName}.Scripts.{YYYY}.json`. The order matters:
168+
**Shared → Guard → domain Actions → CaseValidate → Algorithms**
169+
170+
```json
171+
{ "name": "WageTypeValue.Shared", "functionTypes": ["WageTypeValue"], "valueFile": "../Scripts/WageTypeValueFunction.Shared.Action.cs" },
172+
{ "name": "WageTypeValue.Guard", "functionTypes": ["WageTypeValue"], "valueFile": "../Scripts/WageTypeValueFunction.Guard.Action.cs" },
173+
{ "name": "WageTypeValue.{Scope}", "functionTypes": ["WageTypeValue"], "valueFile": "../Scripts/WageTypeValueFunction.{Scope}.Action.cs" },
174+
{ "name": "CaseValidate", "functionTypes": ["CaseValidate"], "valueFile": "../Scripts/CaseValidateFunction.Action.cs" },
175+
{ "name": "Algorithm.{CC}{Domain}Algorithm", "functionTypes": ["WageTypeValue"], "valueFile": "../Scripts/{CC}{Domain}Algorithm.cs" }
176+
```
177+
178+
Unregistered scripts are silently ignored by PE — a missing entry causes
179+
all actions defined in that file to return `0` with no error.
180+
181+
### 12. Implement test cases
182+
183+
**TC naming conventions (non-negotiable):**
184+
```
185+
Wage type tests: WT-TC{nn}-{CC}-{Scope} e.g. WT-TC1000-DE-BaseSalary
186+
Guard tests: GUARD-TC{n}-{CC}-{Scope} e.g. GUARD-TC1-DE-MandatoryFields
187+
```
188+
189+
Each TC lives in its own folder:
190+
```
191+
YYYY/Tests/WT-TC{nn}-{CC}-{Scope}/
192+
WT-TC{nn}-{CC}-{Scope}-{YYYY}.et.json — payrun employee test
193+
WT-TC{nn}-{CC}-{Scope}.pecmd — single-TC runner
194+
README.md — purpose, scenario, derivation
195+
```
196+
197+
For guard TCs the expected result is always empty:
198+
```json
199+
"wageTypeResults": [],
200+
"collectorResults": []
201+
```
202+
203+
Document the full derivation (formula + statutory source) in each TC's `README.md`.
204+
205+
Update `YYYY/Test.All.pecmd` with all TCs grouped by phase (Guards first,
206+
Company Case setters last — see `YYYY/Tests/README.md`).
132207

133208
### 13. First release
134209
Remove `.dev` suffix in `YYYY/Directory.Build.props`:

YYYY/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Regulation.{CC}.{RegulationName} {YYYY}
2+
3+
Functional regulation sub-project for year {YYYY}.
4+
5+
## Setup
6+
7+
```pecmd
8+
{YYYY}/Setup.pecmd
9+
```
10+
11+
Full setup: deletes existing data, imports regulation + data regulation + test tenant.
12+
13+
## Run All Tests
14+
15+
```pecmd
16+
{YYYY}/Test.All.pecmd
17+
```
18+
19+
Or from repo root:
20+
21+
```pecmd
22+
Test.{YYYY}.pecmd
23+
```
24+
25+
---
26+
27+
## WageType Test Cases
28+
29+
### Guards
30+
31+
| TC | Folder | Focus |
32+
|:---|:---|:---|
33+
| GUARD-TC1 | [GUARD-TC1-{CC}-{Scope}](Tests/GUARD-TC1-{CC}-{Scope}/) | Abort when mandatory CaseField missing |
34+
35+
### Technical
36+
37+
| TC | Folder | Focus |
38+
|:---|:---|:---|
39+
| WT-TC{nn} | [WT-TC{nn}-{CC}-{Scope}](Tests/WT-TC{nn}-{CC}-{Scope}/) | {Description — e.g. contribution base calculation} |
40+
41+
### Gross
42+
43+
| TC | Folder | Focus |
44+
|:---|:---|:---|
45+
| WT-TC{nn} | [WT-TC{nn}-{CC}-{Scope}](Tests/WT-TC{nn}-{CC}-{Scope}/) | {Description} |
46+
47+
### Deductions / Net
48+
49+
| TC | Folder | Focus |
50+
|:---|:---|:---|
51+
| WT-TC{nn} | [WT-TC{nn}-{CC}-{Scope}](Tests/WT-TC{nn}-{CC}-{Scope}/) | {Description} |
52+
53+
### Employer
54+
55+
| TC | Folder | Focus |
56+
|:---|:---|:---|
57+
| WT-TC{nn} | [WT-TC{nn}-{CC}-{Scope}](Tests/WT-TC{nn}-{CC}-{Scope}/) | {Description} |
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"$schema": "../Schemas/PayrollEngine.Exchange.schema.json",
3+
"createdObjectDate": "{YYYY}-01-01T00:00:00.0Z",
4+
"tenants": [
5+
{
6+
"identifier": "{CC}.{RegulationName}",
7+
"regulations": [
8+
{
9+
"name": "{CC}.{RegulationName}",
10+
"updateMode": "NoUpdate",
11+
"validFrom": "{YYYY}-01-01T00:00:00Z",
12+
"scripts": [
13+
{
14+
"name": "WageTypeValue.Shared",
15+
"functionTypes": [ "WageTypeValue" ],
16+
"valueFile": "../Scripts/WageTypeValueFunction.Shared.Action.cs",
17+
"clusters": [ "{CC}" ]
18+
},
19+
{
20+
"name": "WageTypeValue.Guard",
21+
"functionTypes": [ "WageTypeValue" ],
22+
"valueFile": "../Scripts/WageTypeValueFunction.Guard.Action.cs",
23+
"clusters": [ "{CC}" ]
24+
},
25+
{
26+
"name": "WageTypeValue.{Scope}",
27+
"functionTypes": [ "WageTypeValue" ],
28+
"valueFile": "../Scripts/WageTypeValueFunction.{Scope}.Action.cs",
29+
"clusters": [ "{CC}" ]
30+
},
31+
{
32+
"name": "CaseValidate",
33+
"functionTypes": [ "CaseValidate" ],
34+
"valueFile": "../Scripts/CaseValidateFunction.Action.cs",
35+
"clusters": [ "{CC}" ]
36+
},
37+
{
38+
"name": "Algorithm.{CC}{Domain}Algorithm",
39+
"functionTypes": [ "WageTypeValue" ],
40+
"valueFile": "../Scripts/{CC}{Domain}Algorithm.cs",
41+
"clusters": [ "{CC}" ]
42+
}
43+
]
44+
}
45+
]
46+
}
47+
]
48+
}

YYYY/Scripts/WageTypeValueFunction.Action.cs

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)