Practitionist / Practitionist/elluminar_web

🏢 B2B tax invoices for enterprise license contracts

Open
#46 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement enterprise payments
Dominant language
TypeScript
Stars
1
Forks
0
Avg merge
17h 2m
Merged PRs (30d)
18

Description

Context

Enterprise/university licenses are purchased sales-led: a platform admin records the contract payment via recordLicensePayment (src/actions/license.ts), which creates a MANUAL-provider Payment + PLATFORM ADJUSTMENT ledger entry and flips the OrgLicense DRAFT → ACTIVE.

Gap: no Invoice is generated for B2B contracts, even though:

  • Invoice/InvoiceSeries models exist (prisma/models/commerce.prisma) with partial unique indexes
  • Tenant.gstin is captured on the org tenant but never used
  • Retail checkout already writes TAX_INVOICE JSON snapshots (src/lib/commerce/fulfillment.ts)
  • Indian GST rules require a tax invoice for B2B supplies; enterprises will demand GST invoices with their own GSTIN as bill-to before paying contracts

Proposed implementation

  1. Bill-to resolution — invoice data JSON gains an org bill-to block: legal entity name, billing address, GSTIN (from Tenant), PO/reference number (add OrgLicense.poNumber String? if approved — additive).
  2. Series — reuse the existing row-locked InvoiceSeries counter; decide whether B2B contract invoices share series CN/default or get their own series (recommend shared TAX_INVOICE numbering per GST practice — one sequential series).
  3. Action — extend recordLicensePayment to create the Invoice in the same transaction as the Payment + ledger entry; amount = contractValueMinor, GST split per configured rate or reverse-charge flag for B2B (input credit model — line items show base + IGST 18% unless tenant config overrides).
  4. PDF + email — coordinate with issue #24 (compliance pack): once PDF generation lands, contract invoices render through the same pipeline; until then the numbered DB row + /org license page display is acceptable internally.
  5. Placeholders gate — seller entity details come from src/lib/brand.ts placeholders (#37); must be filled before real contracts are invoiced.

Acceptance

  • Recording a license payment produces a numbered TAX_INVOICE carrying buyer GSTIN + PO ref
  • Invoice appears on /org licenses page and /admin queues
  • No schema restructuring — additive only (schema freeze, #43)

Advances #24, #38. Part of epic #42.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with recordLicensePayment in src/actions/license.ts, then inspect Invoice and InvoiceSeries in prisma/models/commerce.prisma and the TAX_INVOICE snapshot flow in src/lib/commerce/fulfillment.ts. Review the related constraints from issues #24, #37, #42 and #43 before resolving the series, GST, and PO-number decisions. Done means a transactional, numbered TAX_INVOICE appears with buyer GSTIN and PO reference on the organization licenses page and admin queues.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, payments
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.