Founder: there is no Tecnostac in this application. Replaced the seed default
company.name ('Tecnostac' -> 'SiMS'), demo-seed data, ~22 test fixtures/emails, and
docs (Tecnostac -> SiMS, @tecnostac.com -> @sims.com). Live DB company.name also
updated to 'SiMS' (shows on dashboard, documents, letterhead, reminder emails). Owner
email was already SiMS (simssoftware13@gmail.com). Full suite 416 green.
// Company + template letterhead data (what the Document Template page edits).
// Company + template letterhead data (what the Document Template page edits).
constsettings: Record<string,string>={
constsettings: Record<string,string>={
'company.name':'Tecnostac Solutions Pvt Ltd',
'company.name':'SiMS Solutions Pvt Ltd',
'company.address':'2nd Floor, Cyber Park, Kakkanad, Kochi, Kerala 682030',
'company.address':'2nd Floor, Cyber Park, Kakkanad, Kochi, Kerala 682030',
'company.gstin':'32ABCDE1234F1Z9',
'company.gstin':'32ABCDE1234F1Z9',
'company.state_code':'32',
'company.state_code':'32',
'company.phone':'+91 98470 12345',
'company.phone':'+91 98470 12345',
'company.email':'accounts@tecnostac.com',
'company.email':'accounts@sims.com',
'company.bank':'HDFC Bank · A/c 50200012345678 · IFSC HDFC0001234 · Kakkanad',
'company.bank':'HDFC Bank · A/c 50200012345678 · IFSC HDFC0001234 · Kakkanad',
'template.accent':'#1e3a5f',
'template.accent':'#1e3a5f',
'template.logo':LOGO,
'template.logo':LOGO,
'template.terms':'1. Prices are valid for 15 days from the date of this quotation.\n2. 50% advance on confirmation, balance before go-live.\n3. Annual subscription renews on the anniversary of activation.',
'template.terms':'1. Prices are valid for 15 days from the date of this quotation.\n2. 50% advance on confirmation, balance before go-live.\n3. Annual subscription renews on the anniversary of activation.',
'template.declaration':'We declare that this invoice shows the actual price of the services described and that all particulars are true and correct.',
'template.declaration':'We declare that this invoice shows the actual price of the services described and that all particulars are true and correct.',
'template.jurisdiction':'Subject to Ernakulam jurisdiction',
'template.jurisdiction':'Subject to Ernakulam jurisdiction',
'template.footer_note':'Thank you for your business. For support: support@tecnostac.com · +91 98470 12345',
'template.footer_note':'Thank you for your business. For support: support@sims.com · +91 98470 12345',
- `seedIfEmpty(db): void` — if no `staff_user`: owner `admin@tecnostac.com` with a random 12-char password **printed to console once**; settings `company.*` placeholders + `company.state_code='32'`; `tax_class` row `('GST18', 1800, '2017-07-01')`.
- `seedIfEmpty(db): void` — if no `staff_user`: owner `admin@sims.com` with a random 12-char password **printed to console once**; settings `company.*` placeholders + `company.state_code='32'`; `tax_class` row `('GST18', 1800, '2017-07-01')`.
- `stageCsv(db, kind: 'clients'|'invoices', csvText: string): { staged: number }` — tiny CSV parser (header row, comma, double-quote escaping — ~20 lines, no dependency); per-row problems collected into `problems` JSON: missing name, GSTIN checksum failure, bad date, duplicate code/doc_no.
- `stageCsv(db, kind: 'clients'|'invoices', csvText: string): { staged: number }` — tiny CSV parser (header row, comma, double-quote escaping — ~20 lines, no dependency); per-row problems collected into `problems` JSON: missing name, GSTIN checksum failure, bad date, duplicate code/doc_no.
- `commitImport(db, userId): { clients: number; invoices: number; seeded: { fy: string; lastSeq: number } | null }` — inserts clients (`source='apex'`), invoices as issued documents (`source='apex'`, status `paid` when `paid=1` else `sent`, payload lines empty — history-only), then **seeds the INVOICE series**: parse the max numeric tail of current-FY staged doc numbers → `seedSeries(db,'INVOICE', fy, lastSeq)`. Refuses to run when any staged row has problems.
- `commitImport(db, userId): { clients: number; invoices: number; seeded: { fy: string; lastSeq: number } | null }` — inserts clients (`source='apex'`), invoices as issued documents (`source='apex'`, status `paid` when `paid=1` else `sent`, payload lines empty — history-only), then **seeds the INVOICE series**: parse the max numeric tail of current-FY staged doc numbers → `seedSeries(db,'INVOICE', fy, lastSeq)`. Refuses to run when any staged row has problems.
- [ ] **Step 2: Browser-verify** (owner login → **Dashboard**, with at least one sendable reminder in the queue — an overdue invoice reminder is easiest to seed):
- [ ] **Step 2: Browser-verify** (owner login → **Dashboard**, with at least one sendable reminder in the queue — an overdue invoice reminder is easiest to seed):
- Click **Preview** on an overdue reminder → the exact subject (e.g. `Payment reminder — Invoice INV/… (Tecnostac)`) and body appear inline, matching what Send would email; **Hide** collapses it.
- Click **Preview** on an overdue reminder → the exact subject (e.g. `Payment reminder — Invoice INV/… (SiMS)`) and body appear inline, matching what Send would email; **Hide** collapses it.
- Internal-only rows (follow-up / bounced) show no Preview/Send button (only Dismiss), unchanged.
- Internal-only rows (follow-up / bounced) show no Preview/Send button (only Dismiss), unchanged.
**Verify commands** (run from repo root `C:\SiMS\hq`):
**Verify commands** (run from repo root `C:\SiMS\hq`):
- Typecheck: `npm run typecheck` → exits 0
- Typecheck: `npm run typecheck` → exits 0
- Tests: `npm test` → all pass
- Tests: `npm test` → all pass
- Dev app: terminal A `cd apps/hq && npm start` (API :5182), terminal B `cd apps/hq-web && npm run dev` (Vite :5183). Login `admin@tecnostac.com` (owner password known to the user; ask them if a login is needed for visual checks).
- Dev app: terminal A `cd apps/hq && npm start` (API :5182), terminal B `cd apps/hq-web && npm run dev` (Vite :5183). Login `admin@sims.com` (owner password known to the user; ask them if a login is needed for visual checks).