@mostajs/compta-budget 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/README.md +19 -0
- package/llms.txt +34 -0
- package/package.json +29 -0
- package/src/index.js +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @mostajs/compta-budget
|
|
2
|
+
|
|
3
|
+
**Auteur** : Dr Hamid MADANI <drmdh@msn.com> · **Licence** : AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
Comptabilité **budgétaire** (couche logique) — suit chaque ligne de budget sur 4 temps :
|
|
6
|
+
**alloué → engagé → réalisé → écart**, et détecte le **surengagement**. **Compose** des sources
|
|
7
|
+
injectées (DEVRULES §10) ; ne réimplémente ni `aid-grants` ni `compta`.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { createComptaBudget } from '@mostajs/compta-budget';
|
|
11
|
+
const cb = createComptaBudget({ sources: {
|
|
12
|
+
budgetLines: () => repos.aidGrants.budgets.find(),
|
|
13
|
+
aids: () => repos.aidGrants.aids.find(),
|
|
14
|
+
}});
|
|
15
|
+
await cb.status('aide-mensuelle'); // { allocated, engaged, realized, available, outstanding, variance, overcommitted }
|
|
16
|
+
await cb.summary();
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Tests & exemple (§11.1 / §12) : `npm install && npm test`. Proposition & livrables : `docs/`. Fiche LLM : `llms.txt`.
|
package/llms.txt
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @mostajs/compta-budget — fiche LLM
|
|
2
|
+
> Comptabilité budgétaire : allocation → engagement → réalisation → écart, par composition (DB-agnostique).
|
|
3
|
+
|
|
4
|
+
- Version: 0.1.0 · Licence: AGPL-3.0-or-later · Auteur: Dr Hamid MADANI <drmdh@msn.com>
|
|
5
|
+
- Stack: mosta-gestion-stack · Voisins: @mostajs/compta, @mostajs/compta-analytique
|
|
6
|
+
|
|
7
|
+
## RÔLE
|
|
8
|
+
Suit chaque ligne de budget sur 4 temps : ALLOUÉ → ENGAGÉ (aides approuvées+versées) →
|
|
9
|
+
RÉALISÉ (versées) → ÉCART. Détecte le surengagement. Compose des SOURCES injectées (§10) ;
|
|
10
|
+
ne réimplémente ni aid-grants ni compta.
|
|
11
|
+
|
|
12
|
+
## EXPORTS
|
|
13
|
+
- createComptaBudget({ sources, now? }) -> { all, status, summary }
|
|
14
|
+
|
|
15
|
+
## API
|
|
16
|
+
- all() -> Ligne[] Ligne = { line, allocated, engaged, realized, available, outstanding, variance, consumptionRate, overcommitted }
|
|
17
|
+
- status(line) -> Ligne | null
|
|
18
|
+
- summary() -> { allocated, engaged, realized, available, outstanding, variance, consumptionRate, lines }
|
|
19
|
+
|
|
20
|
+
## DÉFINITIONS
|
|
21
|
+
- engaged = somme des aides au statut 'approved' OU 'paid'
|
|
22
|
+
- realized = somme des aides 'paid'
|
|
23
|
+
- available = allocated - engaged ; outstanding = engaged - realized ; variance = allocated - realized
|
|
24
|
+
- overcommitted = engaged > allocated
|
|
25
|
+
|
|
26
|
+
## SOURCES injectées
|
|
27
|
+
- budgetLines() -> { line, allocated }[]
|
|
28
|
+
- aids() -> { budgetLine, amount, status }[] (toutes aides)
|
|
29
|
+
|
|
30
|
+
## COMPOSITION (Salsabil)
|
|
31
|
+
createComptaBudget({ sources: {
|
|
32
|
+
budgetLines: () => repos.aidGrants.budgets.find(),
|
|
33
|
+
aids: () => repos.aidGrants.aids.find(),
|
|
34
|
+
}})
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mostajs/compta-budget",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Comptabilité budgétaire — allocation → engagement → réalisation → écart, par composition de sources (DB-agnostique).",
|
|
5
|
+
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
|
+
"license": "AGPL-3.0-or-later",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./src/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"README.md",
|
|
15
|
+
"llms.txt"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"comptabilite",
|
|
19
|
+
"budget",
|
|
20
|
+
"engagement",
|
|
21
|
+
"mostajs"
|
|
22
|
+
],
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@mostajs/mjs-unit": "^0.3.0"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"test": "node test-scripts/unit/compta-budget.test.mjs && node examples/run.mjs"
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @mostajs/compta-budget — comptabilité BUDGÉTAIRE (couche logique). MVP.
|
|
2
|
+
// Au-delà du simple « alloué/consommé » : suit ALLOCATION → ENGAGEMENT → RÉALISATION → ÉCART.
|
|
3
|
+
// COMPOSE par INJECTION (DEVRULES §10) : reçoit des SOURCES (lignes de budget + aides) ;
|
|
4
|
+
// DB-agnostique, ne réimplémente ni aid-grants ni compta.
|
|
5
|
+
// @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
6
|
+
|
|
7
|
+
const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
|
|
8
|
+
const ENGAGED = new Set(['approved', 'paid']); // engagé = approuvé OU versé
|
|
9
|
+
const REALIZED = 'paid'; // réalisé = versé
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {object} opts
|
|
13
|
+
* @param {object} opts.sources
|
|
14
|
+
* - budgetLines() -> { line, allocated }[]
|
|
15
|
+
* - aids() -> { budgetLine, amount, status }[] (toutes aides, tous statuts)
|
|
16
|
+
* @param {() => Date} [opts.now]
|
|
17
|
+
*/
|
|
18
|
+
export function createComptaBudget({ sources = {}, now = () => new Date() } = {}) {
|
|
19
|
+
const budgetLines = sources.budgetLines || (async () => []);
|
|
20
|
+
const aids = sources.aids || (async () => []);
|
|
21
|
+
|
|
22
|
+
/** Situation budgétaire de toutes les lignes. */
|
|
23
|
+
async function all() {
|
|
24
|
+
const lines = await budgetLines();
|
|
25
|
+
const allAids = await aids();
|
|
26
|
+
return lines.map((b) => {
|
|
27
|
+
const onLine = allAids.filter((a) => a.budgetLine === b.line);
|
|
28
|
+
const engaged = onLine.filter((a) => ENGAGED.has(a.status)).reduce((s, a) => s + num(a.amount), 0);
|
|
29
|
+
const realized = onLine.filter((a) => a.status === REALIZED).reduce((s, a) => s + num(a.amount), 0);
|
|
30
|
+
const allocated = num(b.allocated);
|
|
31
|
+
return {
|
|
32
|
+
line: b.line,
|
|
33
|
+
allocated,
|
|
34
|
+
engaged, // engagé (approuvé + versé)
|
|
35
|
+
realized, // réalisé (versé)
|
|
36
|
+
available: allocated - engaged, // disponible (non engagé)
|
|
37
|
+
outstanding: engaged - realized, // engagé non décaissé
|
|
38
|
+
variance: allocated - realized, // écart allocation ↔ réalisation
|
|
39
|
+
consumptionRate: allocated ? realized / allocated : 0,
|
|
40
|
+
overcommitted: engaged > allocated, // dépassement d'engagement
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Situation d'une ligne. */
|
|
46
|
+
async function status(line) { return (await all()).find((x) => x.line === line) || null; }
|
|
47
|
+
|
|
48
|
+
/** Totaux consolidés. */
|
|
49
|
+
async function summary() {
|
|
50
|
+
const rows = await all();
|
|
51
|
+
const t = rows.reduce((acc, x) => ({
|
|
52
|
+
allocated: acc.allocated + x.allocated, engaged: acc.engaged + x.engaged,
|
|
53
|
+
realized: acc.realized + x.realized, available: acc.available + x.available,
|
|
54
|
+
outstanding: acc.outstanding + x.outstanding,
|
|
55
|
+
}), { allocated: 0, engaged: 0, realized: 0, available: 0, outstanding: 0 });
|
|
56
|
+
return { ...t, variance: t.allocated - t.realized, consumptionRate: t.allocated ? t.realized / t.allocated : 0, lines: rows.length };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { now, all, status, summary };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default createComptaBudget;
|