@goweekdays/core 2.13.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/CLAUDE.md +274 -0
- package/dist/index.d.ts +252 -39
- package/dist/index.js +6528 -4402
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5783 -3680
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @goweekdays/core
|
|
2
2
|
|
|
3
|
+
## 2.15.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 770a91a: Finance business profile initial release
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- c54c430: Integrate account balance tracker
|
|
12
|
+
- b31181e: Support updating journal entries with line diffing
|
|
13
|
+
|
|
14
|
+
## 2.14.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- a604a6f: Initial release for finance journal and ledger
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 29b0676: Add indexes, search and fields for journal lines
|
|
23
|
+
|
|
3
24
|
## 2.13.0
|
|
4
25
|
|
|
5
26
|
### Minor Changes
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# server-core-module (`@goweekdays/core`)
|
|
2
|
+
|
|
3
|
+
Shared server module exported as a package consumed by all app servers.
|
|
4
|
+
Built with Express + MongoDB (Atlas) + TypeScript.
|
|
5
|
+
|
|
6
|
+
## Resource Layer Pattern
|
|
7
|
+
|
|
8
|
+
Each resource lives under `src/resources/<resource-name>/` and follows this structure:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
resource-name/
|
|
12
|
+
resource.model.ts # Types and validation schema
|
|
13
|
+
resource.repository.ts # Direct database interaction
|
|
14
|
+
resource.service.ts # Business logic (optional — see below)
|
|
15
|
+
resource.controller.ts # API request handler
|
|
16
|
+
index.ts # Barrel export
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### `.model.ts`
|
|
20
|
+
|
|
21
|
+
Defines the TypeScript type and Joi validation schema for the resource. This is the source of truth for the shape of the data.
|
|
22
|
+
|
|
23
|
+
### `.repository.ts`
|
|
24
|
+
|
|
25
|
+
Contains all functions that directly interact with the database (MongoDB). No business logic here — only reads and writes.
|
|
26
|
+
|
|
27
|
+
### `.service.ts`
|
|
28
|
+
|
|
29
|
+
Builds business logic by composing repository functions and third-party integrations (e.g. hashing, email, S3, transactions). Never accesses the database directly — all DB interaction goes through the repository. **This layer is optional** — if a resource only needs basic CRUD with no business logic, a service file is not required.
|
|
30
|
+
|
|
31
|
+
### `.controller.ts`
|
|
32
|
+
|
|
33
|
+
Handles incoming API requests. Validates the request input, then delegates to the service layer if business logic exists, or calls the repository directly if the resource has no service.
|
|
34
|
+
|
|
35
|
+
### `index.ts`
|
|
36
|
+
|
|
37
|
+
Re-exports all layers so consumers can import from the resource folder directly.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
export * from "./user.model";
|
|
41
|
+
export * from "./user.repository";
|
|
42
|
+
export * from "./user.service";
|
|
43
|
+
export * from "./user.controller";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Naming Conventions
|
|
49
|
+
|
|
50
|
+
| Layer | Pattern | Example |
|
|
51
|
+
| ---------- | --------------------------- | ---------------------------------------------------- |
|
|
52
|
+
| File | `<resource>.<layer>.ts` | `user.model.ts`, `finance.journal.config.service.ts` |
|
|
53
|
+
| Type | `T<Resource>` | `TUser`, `TJobPost` |
|
|
54
|
+
| Schema | `schema<Resource>` | `schemaUser`, `schemaJobPost` |
|
|
55
|
+
| Model fn | `model<Resource>()` | `modelUser()`, `modelJobPost()` |
|
|
56
|
+
| Repository | `use<Resource>Repo()` | `useUserRepo()`, `useOrgRepo()` |
|
|
57
|
+
| Service | `use<Resource>Service()` | `useUserService()`, `useOrgService()` |
|
|
58
|
+
| Controller | `use<Resource>Controller()` | `useUserController()` |
|
|
59
|
+
|
|
60
|
+
Multi-word resource names use dot notation in file names: `finance.journal.config.model.ts`, `job.post.repository.ts`.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Error Handling
|
|
65
|
+
|
|
66
|
+
Always use the typed error classes from `@goweekdays/utils` — never throw a generic `new Error()`.
|
|
67
|
+
|
|
68
|
+
- `BadRequestError` — invalid input or a violated business rule
|
|
69
|
+
- `NotFoundError` — resource does not exist
|
|
70
|
+
- `InternalServerError` — unexpected DB or system failure
|
|
71
|
+
- `AppError` — base class; use `instanceof AppError` in catch blocks to re-throw typed errors as-is
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Controller Input Extraction
|
|
76
|
+
|
|
77
|
+
Validate the entire `req.body` against a Joi schema to ensure no unexpected keys are passed. Extract only the fields you need after validation.
|
|
78
|
+
|
|
79
|
+
1. Define a Joi schema that describes exactly the expected shape
|
|
80
|
+
2. Validate `req.body` (or `req.params` / `req.query`) against it — reject if invalid
|
|
81
|
+
3. Destructure only the needed fields from the validated result
|
|
82
|
+
4. Delegate to the service or repository
|
|
83
|
+
|
|
84
|
+
This prevents unexpected or extra fields from leaking into the database.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Transactions
|
|
89
|
+
|
|
90
|
+
Use a MongoDB session whenever a service function writes to more than one collection. The pattern is always:
|
|
91
|
+
|
|
92
|
+
1. Start session and transaction
|
|
93
|
+
2. Pass `session` down to every repo call
|
|
94
|
+
3. Commit on success, abort on error, and always end the session in `finally`
|
|
95
|
+
|
|
96
|
+
Transactions belong in the service layer only — never in a controller or repository.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## What Not To Do
|
|
101
|
+
|
|
102
|
+
- **No business logic in controllers** — controllers only handle HTTP input/output and delegate
|
|
103
|
+
- **No direct DB access in controllers or services** — all DB interaction belongs in the repository only
|
|
104
|
+
- **No generic `Error` throws** — use the typed error classes above
|
|
105
|
+
- **No Zod** — validation is done with Joi throughout this module
|
|
106
|
+
- **No extra fields into the DB** — always validate the full request body before using any of it
|
|
107
|
+
|
|
108
|
+
# Monthly Account Balance Tracking — Instruction Set
|
|
109
|
+
|
|
110
|
+
## Objective
|
|
111
|
+
|
|
112
|
+
Maintain a monthly balance tracker for each account using the structure:
|
|
113
|
+
|
|
114
|
+
(accountId, fiscalYear, month)
|
|
115
|
+
|
|
116
|
+
Each record must contain:
|
|
117
|
+
|
|
118
|
+
- openingDebit
|
|
119
|
+
- openingCredit
|
|
120
|
+
- movementDebit
|
|
121
|
+
- movementCredit
|
|
122
|
+
- closingDebit
|
|
123
|
+
- closingCredit
|
|
124
|
+
- netBalance
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
# 1. When Posting a Journal Entry
|
|
129
|
+
|
|
130
|
+
For each journal line in a transaction:
|
|
131
|
+
|
|
132
|
+
1. Identify:
|
|
133
|
+
|
|
134
|
+
- accountId
|
|
135
|
+
- transactionDate
|
|
136
|
+
- month
|
|
137
|
+
- fiscalYear
|
|
138
|
+
- debitAmount
|
|
139
|
+
- creditAmount
|
|
140
|
+
|
|
141
|
+
2. Locate the balance record:
|
|
142
|
+
|
|
143
|
+
(accountId, fiscalYear, month)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
# 2. If Balance Record Exists
|
|
148
|
+
|
|
149
|
+
Update the movement values.
|
|
150
|
+
|
|
151
|
+
If the journal line is debit:
|
|
152
|
+
|
|
153
|
+
movementDebit += debitAmount
|
|
154
|
+
|
|
155
|
+
If the journal line is credit:
|
|
156
|
+
|
|
157
|
+
movementCredit += creditAmount
|
|
158
|
+
|
|
159
|
+
Then recompute the closing balance.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
# 3. If Balance Record Does NOT Exist
|
|
164
|
+
|
|
165
|
+
Create a new balance record.
|
|
166
|
+
|
|
167
|
+
Determine the opening balance using the following rules.
|
|
168
|
+
|
|
169
|
+
## Rule A — Previous Month Record Exists
|
|
170
|
+
|
|
171
|
+
Find the latest previous balance record for the same account.
|
|
172
|
+
|
|
173
|
+
(accountId, previousMonth, fiscalYear)
|
|
174
|
+
|
|
175
|
+
Set the opening balance:
|
|
176
|
+
|
|
177
|
+
openingDebit = previousRecord.closingDebit
|
|
178
|
+
openingCredit = previousRecord.closingCredit
|
|
179
|
+
|
|
180
|
+
## Rule B — No Previous Record Exists
|
|
181
|
+
|
|
182
|
+
This means the account is used for the first time.
|
|
183
|
+
|
|
184
|
+
Set:
|
|
185
|
+
|
|
186
|
+
openingDebit = 0
|
|
187
|
+
openingCredit = 0
|
|
188
|
+
|
|
189
|
+
## Initialize Movement
|
|
190
|
+
|
|
191
|
+
After determining the opening balance:
|
|
192
|
+
|
|
193
|
+
movementDebit = debitAmount
|
|
194
|
+
movementCredit = creditAmount
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
# 4. Recompute Closing Balance
|
|
199
|
+
|
|
200
|
+
After movement updates, compute the net balance.
|
|
201
|
+
|
|
202
|
+
netBalance = (openingDebit + movementDebit) - (openingCredit + movementCredit)
|
|
203
|
+
|
|
204
|
+
If netBalance > 0:
|
|
205
|
+
|
|
206
|
+
closingDebit = netBalance
|
|
207
|
+
closingCredit = 0
|
|
208
|
+
|
|
209
|
+
If netBalance < 0:
|
|
210
|
+
|
|
211
|
+
closingDebit = 0
|
|
212
|
+
closingCredit = abs(netBalance)
|
|
213
|
+
|
|
214
|
+
If netBalance == 0:
|
|
215
|
+
|
|
216
|
+
closingDebit = 0
|
|
217
|
+
closingCredit = 0
|
|
218
|
+
|
|
219
|
+
The `netBalance` field should always store the computed value so the system can quickly determine whether the account has a debit or credit balance without recalculating.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
# 5. Month-to-Month Carry Forward Rule
|
|
224
|
+
|
|
225
|
+
When a new month record is created:
|
|
226
|
+
|
|
227
|
+
opening balance = previous month closing balance
|
|
228
|
+
|
|
229
|
+
Example:
|
|
230
|
+
|
|
231
|
+
January closing = 8,000 debit
|
|
232
|
+
February opening = 8,000 debit
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
# 6. Summary of Posting Flow
|
|
237
|
+
|
|
238
|
+
For each journal line:
|
|
239
|
+
|
|
240
|
+
1. Determine account, fiscalYear, and month
|
|
241
|
+
2. Find balance record
|
|
242
|
+
3. If record exists → update movement
|
|
243
|
+
4. If record does not exist
|
|
244
|
+
|
|
245
|
+
- find previous balance record
|
|
246
|
+
- set opening = previous closing (or zero)
|
|
247
|
+
- create new balance record
|
|
248
|
+
|
|
249
|
+
5. Update movement values
|
|
250
|
+
6. Recompute closing balance
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
# 7. Important Principle
|
|
255
|
+
|
|
256
|
+
Opening balance always represents:
|
|
257
|
+
|
|
258
|
+
balance before the period starts
|
|
259
|
+
|
|
260
|
+
Therefore:
|
|
261
|
+
|
|
262
|
+
opening = previous closing
|
|
263
|
+
|
|
264
|
+
If no previous record exists:
|
|
265
|
+
|
|
266
|
+
opening = 0
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
This logic ensures:
|
|
271
|
+
|
|
272
|
+
- continuous balance tracking
|
|
273
|
+
- correct month-to-month carry over
|
|
274
|
+
- efficient financial reporting without recalculating all journal entries
|