initial commit

This commit is contained in:
2026-09-28 17:24:00 +05:30
commit 9706fcc520
213 changed files with 53142 additions and 0 deletions

100
src/api/uploads.test.ts Normal file
View File

@@ -0,0 +1,100 @@
/**
* The receipt, and the two things it has to get right.
*
* A receipt exists because the ingest service's batch id is the only credential
* for reading a result back, it is handed out once, and an unreviewed drop is
* deleted after seven days. So the tests that matter are about not losing that
* window, and about the label their admin reads when deciding whether to
* approve the file.
*/
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { buildSender, daysUntilExpiry, DROP_RETENTION_DAYS, type UploadReceipt } from './uploads';
function receipt(overrides: Partial<UploadReceipt> = {}): UploadReceipt {
return {
uploadid: 1,
tenantid: 1141,
locationid: 1180,
categoryid: 2,
batchid: '49a82536866a483a9189954d3c749243',
runid: '',
filename: 'kmart-opening.xlsx',
sender: 'Kmart · Peelamedu · abhishek',
uploadedby: 1475,
uploadedname: 'abhishek',
rowcount: 20,
laststatus: 'pending',
inserted: 0,
backfilled: 0,
skipped: 0,
rejected: 0,
shelvedcount: 0,
skippedcount: 0,
shelvedat: null,
created: new Date().toISOString(),
updated: new Date().toISOString(),
...overrides,
};
}
const daysAgo = (n: number) => new Date(Date.now() - n * 86_400_000).toISOString();
test('a drop uploaded today has the full window left', () => {
assert.equal(daysUntilExpiry(receipt()), DROP_RETENTION_DAYS);
});
test('the window closes as the drop sits unreviewed', () => {
assert.equal(daysUntilExpiry(receipt({ created: daysAgo(5) })), 2);
});
// Never negative. A drop past the deadline is gone, and "-3 days left" would
// read as a countdown that is still running.
test('an expired drop reports zero, not a negative', () => {
assert.equal(daysUntilExpiry(receipt({ created: daysAgo(30) })), 0);
});
/*
Retention applies to a drop nobody acted on. Once an admin releases it the run
is the record and the drop's own expiry is irrelevant — showing a countdown on
a released upload would push someone to chase a deadline that has already been
met.
*/
test('a released drop has no expiry to report', () => {
assert.equal(daysUntilExpiry(receipt({ runid: '8dcef8a2ad94', laststatus: 'retired' })), null);
assert.equal(daysUntilExpiry(receipt({ laststatus: 'done' })), null);
});
test('a receipt with an unreadable date reports nothing rather than guessing', () => {
assert.equal(daysUntilExpiry(receipt({ created: 'not a date' })), null);
});
/*
The sender label. Free text on their side, capped at 60 characters, and shown to
the admin who decides whether to run the file — so it has to identify the shop,
not the console.
*/
test('the sender names the merchant, the branch and the person', () => {
assert.equal(
buildSender({ tenantname: 'Kmart', locationname: 'Peelamedu', username: 'abhishek' }),
'Kmart · Peelamedu · abhishek',
);
});
// The tenant name is truncated, not the whole label. Cutting the tail would
// drop the branch and the person — the two parts that say WHICH shelf and WHO —
// and leave only a long restaurant name that identifies neither.
test('a long merchant name is trimmed so the branch and person survive', () => {
const sender = buildSender({
tenantname: 'Ninhao The New Age Chinese Restaurant',
locationname: 'Race Course',
username: 'abhishek',
});
assert.ok(sender.length <= 60, `sender was ${sender.length} chars: ${sender}`);
assert.ok(sender.includes('Race Course'), sender);
assert.ok(sender.includes('abhishek'), sender);
});
test('a sender with nothing to say still labels the console', () => {
assert.equal(buildSender({}), 'nearle-console');
});