Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions revenue-recognition-close/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Revenue Recognition Close

Dependency-free finance-close controls for the SCIBASE revenue infrastructure bounty.

This module focuses on what happens after subscription, compute, and licensing systems emit invoice and delivery evidence. It builds a deterministic close packet that answers:

- how much revenue is earned in the current period
- how much remains deferred
- which balances are still receivable
- which overdue invoices need dunning
- which credit, refund, or collection risks should hold close certification

## Run

```bash
npm run check
npm test
npm run demo
```

## Demo Output

```text
Close: scibase-apr-2026-close
Status: attention-needed
Recognized: US$7,936.30
Deferred after close: US$13,304.79
Receivable: US$12,200.00
Dunning queue: 1
Close holds: 2
Top action: finance-review for INV-2026-0391
```

## Files

- `src/revenue-close.js` builds the close packet, journal entries, dunning queue, holds, dashboard, audit trail, and stable digest.
- `data/sample-close.json` contains synthetic subscription, compute, and licensing contracts.
- `test/revenue-close.test.js` verifies recognition, deferral, receivable, dunning, hold, and digest behavior.
- `docs/requirement-map.md` maps the slice to issue #20.
- `docs/demo.svg` and `docs/demo.mp4` provide a short visual artifact for review.

No real payment processor, customer secret, private research content, or external API credential is used.
115 changes: 115 additions & 0 deletions revenue-recognition-close/data/sample-close.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{
"closeId": "scibase-apr-2026-close",
"asOf": "2026-04-30T23:59:59Z",
"periodStart": "2026-04-01",
"periodEnd": "2026-05-01",
"currency": "USD",
"policies": {
"paymentGraceDays": 5,
"dunningSteps": [
{
"afterDays": 5,
"action": "send-reminder",
"owner": "revenue-ops"
},
{
"afterDays": 15,
"action": "finance-review",
"owner": "finance"
},
{
"afterDays": 30,
"action": "pause-api-access",
"owner": "customer-success"
}
],
"recognitionTolerance": 0.01
},
"contracts": [
{
"id": "sub-lab-annual",
"customer": "Northstar Systems Lab",
"stream": "subscription",
"invoiceId": "INV-2026-0410",
"invoiceDate": "2026-01-01",
"dueDate": "2026-01-15",
"paidAt": "2026-01-06T14:20:00Z",
"amount": 12000,
"serviceStart": "2026-01-01",
"serviceEnd": "2027-01-01",
"notes": "Annual lab subscription with ratable recognition."
},
{
"id": "compute-foundation-burst",
"customer": "Helix BioCompute Group",
"stream": "compute",
"invoiceId": "INV-2026-0444",
"invoiceDate": "2026-04-20",
"dueDate": "2026-05-10",
"paidAt": null,
"amount": 3200,
"serviceStart": "2026-04-01",
"serviceEnd": "2026-05-01",
"usageEvents": [
{
"id": "gpu-job-7781",
"occurredAt": "2026-04-09T11:00:00Z",
"units": 42,
"unitPrice": 20,
"billable": true
},
{
"id": "repro-run-9032",
"occurredAt": "2026-04-27T18:45:00Z",
"units": 37,
"unitPrice": 30,
"billable": true
},
{
"id": "may-training-001",
"occurredAt": "2026-05-02T08:00:00Z",
"units": 50,
"unitPrice": 25,
"billable": true
}
],
"notes": "Usage-based compute invoice with unconsumed April capacity deferred."
},
{
"id": "license-policy-api",
"customer": "Public Research Policy Office",
"stream": "license",
"invoiceId": "INV-2026-0391",
"invoiceDate": "2026-03-25",
"dueDate": "2026-04-15",
"paidAt": null,
"amount": 9000,
"serviceStart": "2026-04-01",
"serviceEnd": "2026-06-30",
"licenseDeliverables": [
{
"id": "citation-network-april",
"deliveredAt": "2026-04-10T10:30:00Z",
"amount": 5000,
"accepted": true
},
{
"id": "grant-trend-dashboard",
"deliveredAt": "2026-04-28T16:00:00Z",
"amount": 4000,
"accepted": false
}
],
"credits": [
{
"id": "credit-redaction-review",
"amount": 500,
"requestedAt": "2026-04-29T12:00:00Z",
"status": "pending",
"reason": "Customer asked finance to review a delayed redaction memo."
}
],
"notes": "Analytics licensing package with partial acceptance and an open credit review."
}
]
}
Binary file added revenue-recognition-close/docs/demo.mp4
Binary file not shown.
29 changes: 29 additions & 0 deletions revenue-recognition-close/docs/demo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions revenue-recognition-close/docs/requirement-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Requirement Map

This module contributes a focused month-end revenue recognition and collection-control slice for issue #20.

| Issue area | Covered by this module |
| --- | --- |
| Tiered subscription billing | Ratable recognition for annual subscription service periods, deferred-revenue carry-forward, collected cash tracking |
| AI compute billing | Usage-event recognition inside the close window, deferred unused invoice capacity, receivable tracking |
| Licensing APIs & analytics | Accepted-deliverable recognition for analytics licensing packages, deferred undelivered value, partial acceptance evidence |
| Institutional invoicing | Invoice due-date aging, accounts receivable at close, finance-owned dunning escalation |
| Revenue operations | Journal-entry packet, audit trail, close certification dashboard, credit/refund/collection holds |

## Distinctness

Existing submissions for #20 cover billing engines, entitlement decisions, metering ledgers, procurement controls, anomaly reconciliation, and privacy-safe analytics licensing gates. This module focuses on the finance close boundary after those systems emit invoices and usage/deliverable evidence:

- How much revenue is earned in the current close period
- What remains deferred after the period
- Which invoices remain receivable
- Which overdue accounts need dunning
- Which credit/refund/collectability risks should block close certification

## Verification

```bash
cd revenue-recognition-close
npm run check
npm test
npm run demo
```
18 changes: 18 additions & 0 deletions revenue-recognition-close/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "revenue-recognition-close",
"version": "1.0.0",
"private": true,
"description": "Dependency-free revenue recognition close controls for SCIBASE revenue infrastructure.",
"scripts": {
"check": "node --check src/revenue-close.js && node --check scripts/demo.js && node --check test/revenue-close.test.js",
"demo": "node scripts/demo.js",
"test": "node test/revenue-close.test.js"
},
"keywords": [
"revenue-recognition",
"deferred-revenue",
"dunning",
"finance-close"
],
"license": "MIT"
}
17 changes: 17 additions & 0 deletions revenue-recognition-close/scripts/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const fs = require("node:fs");
const path = require("node:path");
const { buildRevenueClose } = require("../src/revenue-close");

const samplePath = path.join(__dirname, "..", "data", "sample-close.json");
const closeInput = JSON.parse(fs.readFileSync(samplePath, "utf8"));
const close = buildRevenueClose(closeInput);

console.log(`Close: ${close.closeId}`);
console.log(`Status: ${close.dashboard.status}`);
console.log(`Recognized: US$${close.totals.recognizedThisPeriod.toLocaleString("en-US", { minimumFractionDigits: 2 })}`);
console.log(`Deferred after close: US$${close.totals.deferredAfterClose.toLocaleString("en-US", { minimumFractionDigits: 2 })}`);
console.log(`Receivable: US$${close.totals.receivableAtClose.toLocaleString("en-US", { minimumFractionDigits: 2 })}`);
console.log(`Dunning queue: ${close.dunningQueue.length}`);
console.log(`Close holds: ${close.creditAndRefundHolds.length}`);
console.log(`Top action: ${close.dashboard.highPriority[0].nextAction}`);
console.log(`Digest: ${close.digest}`);
Loading