@devx-retailos/cms 0.0.1 → 0.1.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/.medusa/server/src/api/admin/retailos/cms/accumulation/[storeId]/route.js +3 -5
- package/.medusa/server/src/api/admin/retailos/cms/export/route.js +2 -2
- package/.medusa/server/src/api/admin/retailos/cms/handovers/[id]/route.js +2 -2
- package/.medusa/server/src/api/admin/retailos/cms/handovers/route.js +72 -7
- package/.medusa/server/src/api/admin/retailos/cms/petty-cash/route.js +35 -4
- package/.medusa/server/src/api/admin/retailos/cms/reconciliation/route.js +42 -0
- package/.medusa/server/src/modules/cms/migrations/Migration20260626000000.js +16 -0
- package/.medusa/server/src/modules/cms/models/cms-handover.js +3 -1
- package/.medusa/server/src/modules/cms/permissions.js +6 -1
- package/.medusa/server/src/modules/cms/services/cms-module-service.js +137 -42
- package/README.md +116 -0
- package/package.json +3 -3
- package/src/api/admin/retailos/cms/accumulation/[storeId]/__tests__/route.test.ts +27 -9
- package/src/api/admin/retailos/cms/accumulation/[storeId]/route.ts +2 -4
- package/src/api/admin/retailos/cms/export/__tests__/route.test.ts +9 -9
- package/src/api/admin/retailos/cms/export/route.ts +1 -1
- package/src/api/admin/retailos/cms/handovers/[id]/__tests__/route.test.ts +5 -5
- package/src/api/admin/retailos/cms/handovers/[id]/route.ts +1 -1
- package/src/api/admin/retailos/cms/handovers/__tests__/route.test.ts +22 -11
- package/src/api/admin/retailos/cms/handovers/route.ts +78 -6
- package/src/api/admin/retailos/cms/petty-cash/__tests__/route.test.ts +18 -12
- package/src/api/admin/retailos/cms/petty-cash/route.ts +46 -4
- package/src/api/admin/retailos/cms/reconciliation/__tests__/route.test.ts +124 -0
- package/src/api/admin/retailos/cms/reconciliation/route.ts +47 -0
- package/src/modules/cms/__tests__/cms-module-service.test.ts +219 -78
- package/src/modules/cms/__tests__/permissions.test.ts +3 -2
- package/src/modules/cms/migrations/Migration20260626000000.ts +17 -0
- package/src/modules/cms/models/cms-handover.ts +2 -0
- package/src/modules/cms/permissions.ts +5 -0
- package/src/modules/cms/services/cms-module-service.ts +217 -41
|
@@ -10,10 +10,10 @@ const cms_accumulation_1 = __importDefault(require("../models/cms-accumulation")
|
|
|
10
10
|
const petty_cash_1 = __importDefault(require("../models/petty-cash"));
|
|
11
11
|
const petty_cash_transaction_1 = __importDefault(require("../models/petty-cash-transaction"));
|
|
12
12
|
class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
RetailosCmsHandover: cms_handover_1.default,
|
|
14
|
+
RetailosCmsAccumulation: cms_accumulation_1.default,
|
|
15
|
+
RetailosPettyCash: petty_cash_1.default,
|
|
16
|
+
RetailosPettyCashTransaction: petty_cash_transaction_1.default,
|
|
17
17
|
}) {
|
|
18
18
|
constructor(...args) {
|
|
19
19
|
super(...args);
|
|
@@ -26,14 +26,16 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
26
26
|
if (opening_amount < 0) {
|
|
27
27
|
throw new Error("[retailos/cms] opening_amount must be >= 0");
|
|
28
28
|
}
|
|
29
|
-
const existing = await this.
|
|
29
|
+
const existing = await this.listRetailosCmsAccumulations({ store_id: [store_id] });
|
|
30
30
|
if (existing.length === 0) {
|
|
31
|
-
await this.
|
|
31
|
+
await this.createRetailosCmsAccumulations([{ store_id, cash_in_store: opening_amount }]);
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
await this.
|
|
34
|
+
await this.updateRetailosCmsAccumulations([{ id: existing[0].id, cash_in_store: opening_amount }]);
|
|
35
35
|
}
|
|
36
|
-
await this.
|
|
36
|
+
const pettyCashes = await this.listRetailosPettyCashes({ store_id: [store_id] });
|
|
37
|
+
const petty_cash_balance = pettyCashes[0] ? pettyCashes[0].balance : 0;
|
|
38
|
+
await this.createRetailosPettyCashTransactions([{
|
|
37
39
|
store_id,
|
|
38
40
|
employee_id,
|
|
39
41
|
transaction_type: "open",
|
|
@@ -49,19 +51,21 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
49
51
|
reason: null,
|
|
50
52
|
image_url: null,
|
|
51
53
|
date: new Date(),
|
|
52
|
-
metadata:
|
|
54
|
+
metadata: { petty_cash_balance },
|
|
53
55
|
}]);
|
|
54
|
-
this.logger_.info("cms.day_started", { store_id, employee_id, opening_amount });
|
|
56
|
+
this.logger_.info("cms.day_started", { store_id, employee_id, opening_amount, petty_cash_balance });
|
|
55
57
|
}
|
|
56
58
|
async dayEnd(input) {
|
|
57
59
|
const { store_id, employee_id, closing_amount } = input;
|
|
58
60
|
if (closing_amount < 0) {
|
|
59
61
|
throw new Error("[retailos/cms] closing_amount must be >= 0");
|
|
60
62
|
}
|
|
61
|
-
const accumulations = await this.
|
|
63
|
+
const accumulations = await this.listRetailosCmsAccumulations({ store_id: [store_id] });
|
|
62
64
|
const current_cash = accumulations[0] ? accumulations[0].cash_in_store : 0;
|
|
63
65
|
const difference = closing_amount - current_cash;
|
|
64
|
-
await this.
|
|
66
|
+
const pettyCashes = await this.listRetailosPettyCashes({ store_id: [store_id] });
|
|
67
|
+
const petty_cash_balance = pettyCashes[0] ? pettyCashes[0].balance : 0;
|
|
68
|
+
await this.createRetailosPettyCashTransactions([{
|
|
65
69
|
store_id,
|
|
66
70
|
employee_id,
|
|
67
71
|
transaction_type: "close",
|
|
@@ -77,46 +81,51 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
77
81
|
reason: null,
|
|
78
82
|
image_url: null,
|
|
79
83
|
date: new Date(),
|
|
80
|
-
metadata:
|
|
84
|
+
metadata: { petty_cash_balance },
|
|
81
85
|
}]);
|
|
82
|
-
this.logger_.info("cms.day_ended", { store_id, employee_id, closing_amount, difference });
|
|
86
|
+
this.logger_.info("cms.day_ended", { store_id, employee_id, closing_amount, difference, petty_cash_balance });
|
|
83
87
|
}
|
|
84
88
|
async handover(input) {
|
|
85
89
|
const { store_id, handover_amount, type } = input;
|
|
86
90
|
if (handover_amount < 0) {
|
|
87
91
|
throw new Error("[retailos/cms] handover_amount must be >= 0");
|
|
88
92
|
}
|
|
89
|
-
const
|
|
93
|
+
const accumulations = await this.listRetailosCmsAccumulations({ store_id: [store_id] });
|
|
94
|
+
if (accumulations.length === 0) {
|
|
95
|
+
throw new Error("[retailos/cms] Day Start must be completed before creating a handover");
|
|
96
|
+
}
|
|
97
|
+
const opening_balance = accumulations[0].cash_in_store;
|
|
98
|
+
let closing_balance = opening_balance;
|
|
99
|
+
if (type === "CR") {
|
|
100
|
+
closing_balance = opening_balance + handover_amount;
|
|
101
|
+
}
|
|
102
|
+
else if (type === "DB") {
|
|
103
|
+
if (handover_amount > opening_balance) {
|
|
104
|
+
throw new Error(`[retailos/cms] Insufficient cash in store: cannot debit ${handover_amount}, current balance is ${opening_balance}`);
|
|
105
|
+
}
|
|
106
|
+
closing_balance = opening_balance - handover_amount;
|
|
107
|
+
}
|
|
108
|
+
const [created] = await this.createRetailosCmsHandovers([{
|
|
90
109
|
store_id,
|
|
91
110
|
employee_id: input.employee_id,
|
|
92
111
|
handover_id: input.handover_id ?? null,
|
|
93
112
|
handover_amount,
|
|
94
|
-
total_cash:
|
|
113
|
+
total_cash: closing_balance,
|
|
114
|
+
opening_balance,
|
|
115
|
+
closing_balance,
|
|
95
116
|
type: type ?? null,
|
|
96
117
|
image_url: input.image_url ?? null,
|
|
97
118
|
remark: input.remark ?? null,
|
|
98
119
|
metadata: input.metadata ?? null,
|
|
99
120
|
}]);
|
|
100
|
-
|
|
101
|
-
const current = accumulations[0] ? accumulations[0].cash_in_store : 0;
|
|
102
|
-
let updated_cash = current;
|
|
103
|
-
if (type === "CR") {
|
|
104
|
-
updated_cash = current + handover_amount;
|
|
105
|
-
}
|
|
106
|
-
else if (type === "DB") {
|
|
107
|
-
updated_cash = current - handover_amount;
|
|
108
|
-
}
|
|
109
|
-
if (accumulations.length === 0) {
|
|
110
|
-
await this.createCmsAccumulations([{ store_id, cash_in_store: updated_cash }]);
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
await this.updateCmsAccumulations([{ id: accumulations[0].id, cash_in_store: updated_cash }]);
|
|
114
|
-
}
|
|
121
|
+
await this.updateRetailosCmsAccumulations([{ id: accumulations[0].id, cash_in_store: closing_balance }]);
|
|
115
122
|
this.logger_.info("[retailos/cms] handover created", {
|
|
116
123
|
id: created?.id,
|
|
117
124
|
store_id,
|
|
118
125
|
handover_amount,
|
|
119
126
|
type,
|
|
127
|
+
opening_balance,
|
|
128
|
+
closing_balance,
|
|
120
129
|
});
|
|
121
130
|
return created;
|
|
122
131
|
}
|
|
@@ -125,16 +134,31 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
125
134
|
if (amount <= 0) {
|
|
126
135
|
throw new Error("[retailos/cms] amount must be > 0");
|
|
127
136
|
}
|
|
128
|
-
const existing = await this.
|
|
137
|
+
const existing = await this.listRetailosPettyCashes({ store_id: [store_id] });
|
|
129
138
|
const current_balance = existing[0] ? existing[0].balance : 0;
|
|
130
139
|
const new_balance = current_balance + amount;
|
|
131
140
|
if (existing.length === 0) {
|
|
132
|
-
await this.
|
|
141
|
+
await this.createRetailosPettyCashes([{ store_id, balance: new_balance }]);
|
|
133
142
|
}
|
|
134
143
|
else {
|
|
135
|
-
await this.
|
|
144
|
+
await this.updateRetailosPettyCashes([{ id: existing[0].id, balance: new_balance }]);
|
|
145
|
+
}
|
|
146
|
+
// When funded from store cash, deduct the amount from cms_accumulation
|
|
147
|
+
if (source === "from_petty_cash") {
|
|
148
|
+
const accumulations = await this.listRetailosCmsAccumulations({ store_id: [store_id] });
|
|
149
|
+
const current_store_cash = accumulations[0] ? accumulations[0].cash_in_store : 0;
|
|
150
|
+
const new_store_cash = current_store_cash - amount;
|
|
151
|
+
if (accumulations.length === 0) {
|
|
152
|
+
await this.createRetailosCmsAccumulations([{ store_id, cash_in_store: new_store_cash }]);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
await this.updateRetailosCmsAccumulations([{ id: accumulations[0].id, cash_in_store: new_store_cash }]);
|
|
156
|
+
}
|
|
157
|
+
this.logger_.info("[retailos/cms] store cash deducted for petty cash transfer", {
|
|
158
|
+
store_id, amount, new_store_cash,
|
|
159
|
+
});
|
|
136
160
|
}
|
|
137
|
-
const [tx] = await this.
|
|
161
|
+
const [tx] = await this.createRetailosPettyCashTransactions([{
|
|
138
162
|
store_id,
|
|
139
163
|
employee_id,
|
|
140
164
|
transaction_type: "petty_cash",
|
|
@@ -160,16 +184,16 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
160
184
|
if (amount <= 0) {
|
|
161
185
|
throw new Error("[retailos/cms] expense amount must be > 0");
|
|
162
186
|
}
|
|
163
|
-
const existing = await this.
|
|
187
|
+
const existing = await this.listRetailosPettyCashes({ store_id: [store_id] });
|
|
164
188
|
const current_balance = existing[0] ? existing[0].balance : 0;
|
|
165
189
|
const new_balance = current_balance - amount;
|
|
166
190
|
if (existing.length === 0) {
|
|
167
|
-
await this.
|
|
191
|
+
await this.createRetailosPettyCashes([{ store_id, balance: new_balance }]);
|
|
168
192
|
}
|
|
169
193
|
else {
|
|
170
|
-
await this.
|
|
194
|
+
await this.updateRetailosPettyCashes([{ id: existing[0].id, balance: new_balance }]);
|
|
171
195
|
}
|
|
172
|
-
const [tx] = await this.
|
|
196
|
+
const [tx] = await this.createRetailosPettyCashTransactions([{
|
|
173
197
|
store_id,
|
|
174
198
|
employee_id,
|
|
175
199
|
transaction_type: "petty_cash",
|
|
@@ -191,15 +215,86 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
191
215
|
return tx;
|
|
192
216
|
}
|
|
193
217
|
async getAccumulation(store_id) {
|
|
194
|
-
const rows = await this.
|
|
218
|
+
const rows = await this.listRetailosCmsAccumulations({ store_id: [store_id] });
|
|
195
219
|
return rows[0] ?? null;
|
|
196
220
|
}
|
|
221
|
+
async getEnrichedAccumulation(store_id) {
|
|
222
|
+
const accumulation = await this.getAccumulation(store_id);
|
|
223
|
+
const pettyCashes = await this.listRetailosPettyCashes({ store_id: [store_id] });
|
|
224
|
+
const petty_cash = pettyCashes[0] ? pettyCashes[0].balance : 0;
|
|
225
|
+
const now = new Date();
|
|
226
|
+
const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
|
|
227
|
+
const start = new Date(`${dateStr}T00:00:00.000Z`);
|
|
228
|
+
const end = new Date(`${dateStr}T23:59:59.999Z`);
|
|
229
|
+
const todayTxns = await this.listRetailosPettyCashTransactions({ store_id: [store_id], created_at: { $gte: start, $lte: end } }, { take: 10, order: { created_at: "ASC" } });
|
|
230
|
+
const txnList = todayTxns;
|
|
231
|
+
const openTx = txnList.find((t) => t.transaction_type === "open");
|
|
232
|
+
const closeTx = txnList.find((t) => t.transaction_type === "close");
|
|
233
|
+
return {
|
|
234
|
+
...(accumulation ? accumulation : { store_id, cash_in_store: 0 }),
|
|
235
|
+
petty_cash,
|
|
236
|
+
opening_store_cash: openTx ? openTx.amount : null,
|
|
237
|
+
opening_petty_cash: openTx?.metadata?.petty_cash_balance ?? null,
|
|
238
|
+
closing_store_cash: closeTx ? closeTx.amount : null,
|
|
239
|
+
closing_petty_cash: closeTx?.metadata?.petty_cash_balance ?? null,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
async getReconciliationReport(input) {
|
|
243
|
+
const { store_id, date, net_cash_sales = 0 } = input;
|
|
244
|
+
const start = new Date(`${date}T00:00:00.000Z`);
|
|
245
|
+
const end = new Date(`${date}T23:59:59.999Z`);
|
|
246
|
+
const dateFilter = { $gte: start, $lte: end };
|
|
247
|
+
const txns = await this.listRetailosPettyCashTransactions({ store_id: [store_id], created_at: dateFilter }, { take: 1000, order: { created_at: "ASC" } });
|
|
248
|
+
const handovers = await this.listRetailosCmsHandovers({ store_id: [store_id], created_at: dateFilter }, { take: 1000, order: { created_at: "ASC" } });
|
|
249
|
+
const accumulation = await this.getAccumulation(store_id);
|
|
250
|
+
const txnList = txns;
|
|
251
|
+
const handoverList = handovers;
|
|
252
|
+
const openTx = txnList.find((t) => t.transaction_type === "open");
|
|
253
|
+
const closeTx = txnList.find((t) => t.transaction_type === "close");
|
|
254
|
+
const opening_balance = openTx ? openTx.amount : 0;
|
|
255
|
+
const closing_balance = closeTx ? closeTx.amount : null;
|
|
256
|
+
const pettyCashTxns = txnList.filter((t) => t.transaction_type === "petty_cash");
|
|
257
|
+
const petty_cash_in = pettyCashTxns
|
|
258
|
+
.filter((t) => t.entry_type === "CR")
|
|
259
|
+
.reduce((sum, t) => sum + t.amount, 0);
|
|
260
|
+
const petty_cash_out = pettyCashTxns
|
|
261
|
+
.filter((t) => t.entry_type === "DB")
|
|
262
|
+
.reduce((sum, t) => sum + t.amount, 0);
|
|
263
|
+
const total_handovers_in = handoverList
|
|
264
|
+
.filter((h) => h.type === "CR")
|
|
265
|
+
.reduce((sum, h) => sum + h.handover_amount, 0);
|
|
266
|
+
const total_handovers_out = handoverList
|
|
267
|
+
.filter((h) => h.type === "DB")
|
|
268
|
+
.reduce((sum, h) => sum + h.handover_amount, 0);
|
|
269
|
+
const expected_closing_balance = opening_balance + net_cash_sales + petty_cash_in - petty_cash_out + total_handovers_in - total_handovers_out;
|
|
270
|
+
const variance = closing_balance !== null ? closing_balance - expected_closing_balance : null;
|
|
271
|
+
const is_balanced = variance !== null ? variance === 0 : null;
|
|
272
|
+
const shift_logs = txnList.filter((t) => t.transaction_type === "open" || t.transaction_type === "close");
|
|
273
|
+
this.logger_.info("[retailos/cms] reconciliation report generated", { store_id, date });
|
|
274
|
+
return {
|
|
275
|
+
date,
|
|
276
|
+
store_id,
|
|
277
|
+
opening_balance,
|
|
278
|
+
net_cash_sales,
|
|
279
|
+
total_handovers_in,
|
|
280
|
+
total_handovers_out,
|
|
281
|
+
petty_cash_in,
|
|
282
|
+
petty_cash_out,
|
|
283
|
+
expected_closing_balance,
|
|
284
|
+
closing_balance,
|
|
285
|
+
cms_balance: accumulation ? accumulation.cash_in_store : null,
|
|
286
|
+
variance,
|
|
287
|
+
is_balanced,
|
|
288
|
+
handovers: handoverList,
|
|
289
|
+
shift_logs,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
197
292
|
async getShiftLogs(filters) {
|
|
198
293
|
const dbFilters = {};
|
|
199
294
|
if (filters.store_id)
|
|
200
295
|
dbFilters.store_id = [filters.store_id];
|
|
201
296
|
dbFilters.transaction_type = ["open", "close"];
|
|
202
|
-
const rows = await this.
|
|
297
|
+
const rows = await this.listRetailosPettyCashTransactions(dbFilters, {
|
|
203
298
|
take: filters.limit ?? 100,
|
|
204
299
|
order: { created_at: "DESC" },
|
|
205
300
|
});
|
|
@@ -207,4 +302,4 @@ class CmsModuleService extends (0, utils_1.MedusaService)({
|
|
|
207
302
|
}
|
|
208
303
|
}
|
|
209
304
|
exports.default = CmsModuleService;
|
|
210
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY21zLW1vZHVsZS1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvY21zL3NlcnZpY2VzL2Ntcy1tb2R1bGUtc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFEQUF5RDtBQUN6RCw4Q0FBbUU7QUFDbkUsMEVBQWdEO0FBQ2hELGtGQUF3RDtBQUN4RCxzRUFBNEM7QUFDNUMsOEZBQW1FO0FBd0RuRSxNQUFNLGdCQUFpQixTQUFRLElBQUEscUJBQWEsRUFBQztJQUMzQyxXQUFXLEVBQVgsc0JBQVc7SUFDWCxlQUFlLEVBQWYsMEJBQWU7SUFDZixTQUFTLEVBQVQsb0JBQVM7SUFDVCxvQkFBb0IsRUFBcEIsZ0NBQW9CO0NBQ3JCLENBQUM7SUFHQSxZQUFZLEdBQUcsSUFBVztRQUN4QixLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQTtRQUNkLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBd0IsQ0FBQTtRQUN4RCxJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxNQUFNLElBQUksSUFBQSx1QkFBZ0IsR0FBRSxDQUFBO1FBQ3JELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUE7SUFDMUQsQ0FBQztJQUVELEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBb0I7UUFDakMsTUFBTSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLEdBQUcsS0FBSyxDQUFBO1FBQ3ZELElBQUksY0FBYyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sSUFBSSxLQUFLLENBQUMsNENBQTRDLENBQUMsQ0FBQTtRQUMvRCxDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFB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
|
|
305
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY21zLW1vZHVsZS1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvY21zL3NlcnZpY2VzL2Ntcy1tb2R1bGUtc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFEQUF5RDtBQUN6RCw4Q0FBbUU7QUFDbkUsMEVBQWdEO0FBQ2hELGtGQUF3RDtBQUN4RCxzRUFBNEM7QUFDNUMsOEZBQW1FO0FBZ0duRSxNQUFNLGdCQUFpQixTQUFRLElBQUEscUJBQWEsRUFBQztJQUMzQyxtQkFBbUIsRUFBRSxzQkFBVztJQUNoQyx1QkFBdUIsRUFBRSwwQkFBZTtJQUN4QyxpQkFBaUIsRUFBRSxvQkFBUztJQUM1Qiw0QkFBNEIsRUFBRSxnQ0FBb0I7Q0FDbkQsQ0FBQztJQUdBLFlBQVksR0FBRyxJQUFXO1FBQ3hCLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO1FBQ2QsTUFBTSxTQUFTLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUF3QixDQUFBO1FBQ3hELElBQUksQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLE1BQU0sSUFBSSxJQUFBLHVCQUFnQixHQUFFLENBQUE7UUFDckQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQTtJQUMxRCxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFvQjtRQUNqQyxNQUFNLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQUUsR0FBRyxLQUFLLENBQUE7UUFDdkQsSUFBSSxjQUFjLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFBO1FBQy9ELENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLFFBQVEs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
|
package/README.md
CHANGED
|
@@ -126,8 +126,21 @@ const logs = await cmsService.getShiftLogs({
|
|
|
126
126
|
to: new Date("2024-01-31"),
|
|
127
127
|
limit: 50,
|
|
128
128
|
})
|
|
129
|
+
|
|
130
|
+
// Daily cash reconciliation report
|
|
131
|
+
const report = await cmsService.getReconciliationReport({
|
|
132
|
+
store_id: "store_01",
|
|
133
|
+
date: "2026-06-23", // YYYY-MM-DD (UTC)
|
|
134
|
+
net_cash_sales: 28450, // optional — cash collected from orders (default 0)
|
|
135
|
+
})
|
|
136
|
+
// report.expected_closing_balance = opening + net_cash_sales
|
|
137
|
+
// + petty_cash_in - petty_cash_out + total_handovers_in - total_handovers_out
|
|
138
|
+
// report.variance = closing_balance - expected (null until day_end runs)
|
|
139
|
+
// report.is_balanced = variance === 0
|
|
129
140
|
```
|
|
130
141
|
|
|
142
|
+
> **`net_cash_sales`** comes from your order module. Pass it from the brand's order query or via `sdk-client`. When omitted the report uses 0 and computes everything from CMS data only.
|
|
143
|
+
|
|
131
144
|
---
|
|
132
145
|
|
|
133
146
|
## Permissions
|
|
@@ -140,6 +153,109 @@ const logs = await cmsService.getShiftLogs({
|
|
|
140
153
|
| `cms.petty_cash.read` | View petty cash balance and transactions |
|
|
141
154
|
| `cms.petty_cash.operate` | Add petty cash or record expenses |
|
|
142
155
|
| `cms.accumulation.read` | View current cash accumulation for a store |
|
|
156
|
+
| `cms.reconciliation.read` | View daily cash reconciliation report with variance analysis |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## HTTP API
|
|
161
|
+
|
|
162
|
+
All routes are mounted under `/admin/retailos/cms` and require a valid Medusa admin session.
|
|
163
|
+
|
|
164
|
+
### Handovers
|
|
165
|
+
|
|
166
|
+
| Method | Path | Description |
|
|
167
|
+
|--------|------|-------------|
|
|
168
|
+
| `GET` | `/admin/retailos/cms/handovers` | List handovers with filtering, pagination, and linked employee/store data |
|
|
169
|
+
| `POST` | `/admin/retailos/cms/handovers` | Create a cash handover |
|
|
170
|
+
| `GET` | `/admin/retailos/cms/handovers/:id` | Retrieve a single handover by ID |
|
|
171
|
+
|
|
172
|
+
**GET /admin/retailos/cms/handovers** query params:
|
|
173
|
+
|
|
174
|
+
| Param | Type | Description |
|
|
175
|
+
|-------|------|-------------|
|
|
176
|
+
| `store_id` | string | Filter by store |
|
|
177
|
+
| `employee_id` | string | Filter by employee |
|
|
178
|
+
| `type` | `CR` \| `DB` | Filter by direction |
|
|
179
|
+
| `handover_id` | string | Exact match on handover_id |
|
|
180
|
+
| `q` | string | Full-text search on handover_id (`ILIKE`) |
|
|
181
|
+
| `created_at` | string / object | Date range filter |
|
|
182
|
+
| `limit` | number | Max 500, default 20 |
|
|
183
|
+
| `offset` | number | Default 0 |
|
|
184
|
+
| `order` | string | Field name; prefix `-` for DESC (e.g. `-created_at`) |
|
|
185
|
+
|
|
186
|
+
Response includes `handovers[]` and `count`. Each handover carries an embedded `employee` (`id`, `first_name`, `last_name`) and `store` (`id`, `name`, `store_code`) when module links resolve.
|
|
187
|
+
|
|
188
|
+
**POST /admin/retailos/cms/handovers** body (Zod-validated):
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"store_id": "store_01",
|
|
193
|
+
"employee_id": "emp_01",
|
|
194
|
+
"handover_amount": 2000,
|
|
195
|
+
"type": "CR",
|
|
196
|
+
"remark": "shift change",
|
|
197
|
+
"handover_id": null,
|
|
198
|
+
"image_url": null,
|
|
199
|
+
"metadata": null
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### Petty cash
|
|
206
|
+
|
|
207
|
+
| Method | Path | Description |
|
|
208
|
+
|--------|------|-------------|
|
|
209
|
+
| `GET` | `/admin/retailos/cms/petty-cash` | List petty cash transactions with employee enrichment |
|
|
210
|
+
|
|
211
|
+
Query params: `store_id`, `limit` (max 500, default 100), `offset`.
|
|
212
|
+
|
|
213
|
+
Each transaction includes an embedded `employee` object when the `employee` module is available.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### Reconciliation
|
|
218
|
+
|
|
219
|
+
| Method | Path | Description |
|
|
220
|
+
|--------|------|-------------|
|
|
221
|
+
| `GET` | `/admin/retailos/cms/reconciliation` | Daily cash reconciliation report |
|
|
222
|
+
|
|
223
|
+
Required params: `store_id`, `date` (YYYY-MM-DD). Optional: `net_cash_sales` (number).
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### Export
|
|
228
|
+
|
|
229
|
+
| Method | Path | Description |
|
|
230
|
+
|--------|------|-------------|
|
|
231
|
+
| `GET` | `/admin/retailos/cms/export` | Download all handovers as a CSV file |
|
|
232
|
+
|
|
233
|
+
Query params: `store_id` (optional). Returns `text/csv` with `Content-Disposition: attachment`.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## sdk-client
|
|
238
|
+
|
|
239
|
+
The `cms` namespace on `RetailOSClient` exposes typed wrappers for all routes above. Key methods:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
// Reconciliation report
|
|
243
|
+
const report = await client.cms.getReconciliationReport({
|
|
244
|
+
store_id: "store_01",
|
|
245
|
+
date: "2026-06-26",
|
|
246
|
+
net_cash_sales: 28450,
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
// List handovers (paginated)
|
|
250
|
+
const { handovers, count } = await client.cms.listHandovers({
|
|
251
|
+
store_id: "store_01",
|
|
252
|
+
limit: 20,
|
|
253
|
+
offset: 0,
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// Export CSV (returns raw text)
|
|
257
|
+
const csv = await client.cms.exportHandovers({ store_id: "store_01" })
|
|
258
|
+
```
|
|
143
259
|
|
|
144
260
|
---
|
|
145
261
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devx-retailos/cms",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Cash Management System for retailOS: shift ops, handovers, petty cash, accumulation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./.medusa/server/src/modules/cms/index.js",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@devx-retailos/
|
|
28
|
+
"@devx-retailos/rbac": "0.0.2",
|
|
29
29
|
"@devx-retailos/employee": "0.0.3",
|
|
30
|
-
"@devx-retailos/
|
|
30
|
+
"@devx-retailos/core": "0.0.2"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@medusajs/framework": "^2.15.0",
|
|
@@ -3,7 +3,7 @@ import { GET } from "../route"
|
|
|
3
3
|
|
|
4
4
|
function makeService() {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
getEnrichedAccumulation: vi.fn(),
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -28,35 +28,53 @@ function makeRes() {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
describe("GET /accumulation/[storeId]", () => {
|
|
31
|
-
it("returns accumulation when it exists", async () => {
|
|
31
|
+
it("returns enriched accumulation when it exists", async () => {
|
|
32
32
|
const service = makeService()
|
|
33
|
-
const accumulation = {
|
|
34
|
-
|
|
33
|
+
const accumulation = {
|
|
34
|
+
id: "cmsa_1",
|
|
35
|
+
store_id: "s1",
|
|
36
|
+
cash_in_store: 750,
|
|
37
|
+
petty_cash: 200,
|
|
38
|
+
opening_store_cash: 500,
|
|
39
|
+
opening_petty_cash: 150,
|
|
40
|
+
closing_store_cash: null,
|
|
41
|
+
closing_petty_cash: null,
|
|
42
|
+
}
|
|
43
|
+
service.getEnrichedAccumulation.mockResolvedValue(accumulation)
|
|
35
44
|
const req = makeReq({ storeId: "s1" }, service)
|
|
36
45
|
const res = makeRes()
|
|
37
46
|
|
|
38
47
|
await GET(req as any, res as any)
|
|
39
48
|
|
|
40
|
-
expect(service.
|
|
49
|
+
expect(service.getEnrichedAccumulation).toHaveBeenCalledWith("s1")
|
|
41
50
|
expect(res.status).toHaveBeenCalledWith(200)
|
|
42
51
|
expect(res.json).toHaveBeenCalledWith({ accumulation })
|
|
43
52
|
})
|
|
44
53
|
|
|
45
|
-
it("returns default zero accumulation when
|
|
54
|
+
it("returns default zero accumulation when no day has started", async () => {
|
|
46
55
|
const service = makeService()
|
|
47
|
-
|
|
56
|
+
const accumulation = {
|
|
57
|
+
store_id: "s1",
|
|
58
|
+
cash_in_store: 0,
|
|
59
|
+
petty_cash: 0,
|
|
60
|
+
opening_store_cash: null,
|
|
61
|
+
opening_petty_cash: null,
|
|
62
|
+
closing_store_cash: null,
|
|
63
|
+
closing_petty_cash: null,
|
|
64
|
+
}
|
|
65
|
+
service.getEnrichedAccumulation.mockResolvedValue(accumulation)
|
|
48
66
|
const req = makeReq({ storeId: "s1" }, service)
|
|
49
67
|
const res = makeRes()
|
|
50
68
|
|
|
51
69
|
await GET(req as any, res as any)
|
|
52
70
|
|
|
53
71
|
expect(res.status).toHaveBeenCalledWith(200)
|
|
54
|
-
expect(res.json).toHaveBeenCalledWith({ accumulation
|
|
72
|
+
expect(res.json).toHaveBeenCalledWith({ accumulation })
|
|
55
73
|
})
|
|
56
74
|
|
|
57
75
|
it("returns 500 when service throws", async () => {
|
|
58
76
|
const service = makeService()
|
|
59
|
-
service.
|
|
77
|
+
service.getEnrichedAccumulation.mockRejectedValue(new Error("db error"))
|
|
60
78
|
const req = makeReq({ storeId: "s1" }, service)
|
|
61
79
|
const res = makeRes()
|
|
62
80
|
|
|
@@ -21,10 +21,8 @@ export const GET = async (req: AuthenticatedMedusaRequest, res: MedusaResponse)
|
|
|
21
21
|
const { storeId } = req.params
|
|
22
22
|
try {
|
|
23
23
|
const service = getService(req)
|
|
24
|
-
const accumulation = await service.
|
|
25
|
-
return res.status(200).json({
|
|
26
|
-
accumulation: accumulation ?? { store_id: storeId, cash_in_store: 0 },
|
|
27
|
-
})
|
|
24
|
+
const accumulation = await service.getEnrichedAccumulation(storeId)
|
|
25
|
+
return res.status(200).json({ accumulation })
|
|
28
26
|
} catch (err) {
|
|
29
27
|
getLogger(req).error("[retailos/cms] get accumulation failed", {
|
|
30
28
|
store_id: storeId,
|
|
@@ -3,7 +3,7 @@ import { GET } from "../route"
|
|
|
3
3
|
|
|
4
4
|
function makeService() {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
listAndCountRetailosCmsHandovers: vi.fn().mockResolvedValue([[], 0]),
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -34,7 +34,7 @@ function makeRes() {
|
|
|
34
34
|
describe("GET /export", () => {
|
|
35
35
|
it("returns CSV with correct headers row", async () => {
|
|
36
36
|
const service = makeService()
|
|
37
|
-
service.
|
|
37
|
+
service.listAndCountRetailosCmsHandovers.mockResolvedValue([[], 0])
|
|
38
38
|
const req = makeReq({}, service)
|
|
39
39
|
const res = makeRes()
|
|
40
40
|
|
|
@@ -55,7 +55,7 @@ describe("GET /export", () => {
|
|
|
55
55
|
const handovers = [
|
|
56
56
|
{ id: "cmsh_1", store_id: "s1", employee_id: "e1", handover_id: null, handover_amount: 500, total_cash: null, type: "CR", remark: null, created_at: "2026-06-22T00:00:00Z" },
|
|
57
57
|
]
|
|
58
|
-
service.
|
|
58
|
+
service.listAndCountRetailosCmsHandovers.mockResolvedValue([handovers, 1])
|
|
59
59
|
const req = makeReq({}, service)
|
|
60
60
|
const res = makeRes()
|
|
61
61
|
|
|
@@ -74,7 +74,7 @@ describe("GET /export", () => {
|
|
|
74
74
|
const handovers = [
|
|
75
75
|
{ id: "cmsh_2", store_id: "s1", employee_id: "e1", handover_id: null, handover_amount: 100, total_cash: null, type: "DB", remark: 'cash, "extra"', created_at: "2026-06-22T00:00:00Z" },
|
|
76
76
|
]
|
|
77
|
-
service.
|
|
77
|
+
service.listAndCountRetailosCmsHandovers.mockResolvedValue([handovers, 1])
|
|
78
78
|
const req = makeReq({}, service)
|
|
79
79
|
const res = makeRes()
|
|
80
80
|
|
|
@@ -86,13 +86,13 @@ describe("GET /export", () => {
|
|
|
86
86
|
|
|
87
87
|
it("filters by store_id when provided in query", async () => {
|
|
88
88
|
const service = makeService()
|
|
89
|
-
service.
|
|
89
|
+
service.listAndCountRetailosCmsHandovers.mockResolvedValue([[], 0])
|
|
90
90
|
const req = makeReq({ store_id: "s1" }, service)
|
|
91
91
|
const res = makeRes()
|
|
92
92
|
|
|
93
93
|
await GET(req as any, res as any)
|
|
94
94
|
|
|
95
|
-
expect(service.
|
|
95
|
+
expect(service.listAndCountRetailosCmsHandovers).toHaveBeenCalledWith(
|
|
96
96
|
expect.objectContaining({ store_id: ["s1"] }),
|
|
97
97
|
expect.any(Object)
|
|
98
98
|
)
|
|
@@ -100,13 +100,13 @@ describe("GET /export", () => {
|
|
|
100
100
|
|
|
101
101
|
it("does not filter by store_id when not in query", async () => {
|
|
102
102
|
const service = makeService()
|
|
103
|
-
service.
|
|
103
|
+
service.listAndCountRetailosCmsHandovers.mockResolvedValue([[], 0])
|
|
104
104
|
const req = makeReq({}, service)
|
|
105
105
|
const res = makeRes()
|
|
106
106
|
|
|
107
107
|
await GET(req as any, res as any)
|
|
108
108
|
|
|
109
|
-
expect(service.
|
|
109
|
+
expect(service.listAndCountRetailosCmsHandovers).toHaveBeenCalledWith(
|
|
110
110
|
expect.not.objectContaining({ store_id: expect.anything() }),
|
|
111
111
|
expect.any(Object)
|
|
112
112
|
)
|
|
@@ -114,7 +114,7 @@ describe("GET /export", () => {
|
|
|
114
114
|
|
|
115
115
|
it("returns 500 when service throws", async () => {
|
|
116
116
|
const service = makeService()
|
|
117
|
-
service.
|
|
117
|
+
service.listAndCountRetailosCmsHandovers.mockRejectedValue(new Error("db error"))
|
|
118
118
|
const req = makeReq({}, service)
|
|
119
119
|
const res = makeRes()
|
|
120
120
|
|
|
@@ -35,7 +35,7 @@ export const GET = async (req: AuthenticatedMedusaRequest, res: MedusaResponse)
|
|
|
35
35
|
const filters: Record<string, unknown> = {}
|
|
36
36
|
if (store_id) filters.store_id = [store_id]
|
|
37
37
|
|
|
38
|
-
const [handovers] = await service.
|
|
38
|
+
const [handovers] = await service.listAndCountRetailosCmsHandovers(filters, {
|
|
39
39
|
take: 10000,
|
|
40
40
|
order: { created_at: "DESC" },
|
|
41
41
|
})
|