Skip to main content

@happyvertical/smrt-commerce

Commerce models for the s-m-r-t framework. Covers customers, vendors, contracts (5 STI types), invoices with ledger integration, payments, and fulfillment tracking.

Installation

pnpm add @happyvertical/smrt-commerce

Usage

import {
Customer, CustomerCollection,
Order, ContractCollection,
Invoice, InvoiceCollection,
Payment, PaymentCollection,
ContractStatus, InvoiceStatus, PaymentMethod
} from '@happyvertical/smrt-commerce';

// Create a customer linked to a profile
const customers = await CustomerCollection.create({ db });
const customer = await customers.create({
profileId: 'profile-uuid',
creditLimit: 1000000, // $10,000.00 — money is integer minor units
paymentTerms: 'Net 30',
});
await customer.save();

// Create an order (STI contract type)
const contracts = await ContractCollection.create({ db });
const order = await contracts.create({
_meta_type: 'Order',
customerId: customer.id,
subtotal: 100000, // $1,000.00
taxAmount: 5000, // $50.00
totalAmount: 105000, // $1,050.00
currency: 'CAD',
});
await order.save();

// Create an invoice for the order
const invoices = await InvoiceCollection.create({ db });
const invoiceNumber = await invoices.generateInvoiceNumber();
const invoice = await invoices.create({
customerId: customer.id,
contractId: order.id,
invoiceNumber,
subtotal: 100000, // $1,000.00
taxAmount: 5000, // $50.00
totalAmount: 105000, // $1,050.00
});
await invoice.save();

// Recognize revenue (creates balanced journal in smrt-ledgers)
await invoice.recognizeRevenue({
arAccountId: 'ar-account-id',
revenueAccountId: 'revenue-account-id',
taxAccountId: 'tax-account-id',
});

// Record a payment
const payments = await PaymentCollection.create({ db });
const payment = await payments.create({
contractId: order.id,
customerId: customer.id,
amount: 105000,
method: PaymentMethod.CREDIT_CARD,
});
await payment.save();

// Record payment with ledger integration
await payment.recordPayment({
ledgerId: 'ledger-id',
receivablesAccountId: 'ar-account-id',
cashAccountId: 'bank-account-id',
});

API

Models

ExportDescription
CustomerCustomer record with creditLimit, paymentTerms, tax exemption, addresses
VendorVendor/supplier with leadTimeDays, minimumOrderAmount, currency
ContractSTI base class for all commercial agreements
EstimateQuote or proposal sent to a customer
OrderCustomer purchase order
LeaseRental or lease agreement
AgreementService or maintenance agreement
PurchaseOrderOrder sent to a vendor/supplier
ContractLineItemLine item within a contract
InvoiceBilling document with status lifecycle and ledger integration
InvoiceLineItemIndividual invoice line item
PaymentPayment record with method, status, and optional ledger journal
PaymentAllocationPayment-to-invoice allocation
FulfillmentShipment/delivery tracking with carrier and address
FulfillmentLineItemIndividual fulfillment line item

Collections

CustomerCollection, VendorCollection, ContractCollection, InvoiceCollection, InvoiceLineItemCollection, PaymentCollection, PaymentAllocationCollection, FulfillmentCollection

Enums

ExportValues
ContractTypeestimate, order, lease, agreement, purchase_order
ContractStatusdraft, sent, accepted, declined, completed, cancelled
CustomerStatusactive, inactive, suspended
VendorStatusactive, inactive, suspended
InvoiceStatusdraft, sent, viewed, partial, paid, overdue, cancelled, written_off
PaymentMethodcash, check, credit_card, bank_transfer, crypto, other
PaymentStatuspending, completed, failed, refunded, cancelled
FulfillmentStatuspending, processing, shipped, delivered, cancelled
FulfillmentTypeshipment, delivery, pickup, digital, service

Types and Constants

ExportDescription
AddressShared address interface (street1, street2, city, state, postalCode, country)
RecognizeRevenueOptionsAccount IDs for invoice revenue recognition
RecordPaymentOptionsLedger and account IDs for payment recording
InvoiceNumberOptionsOptions for generateInvoiceNumber() (prefix, format)
UNPAID_STATUSESArray of invoice statuses considered unpaid (sent, viewed, partial, overdue)
COMMERCE_MODULE_METAUI module metadata
COMMERCE_UI_SLOTSUI slot definitions

Ledger Integration

Invoice and Payment integrate with @happyvertical/smrt-ledgers via dynamic import (optional dependency). Invoice stores arJournalId and revenueJournalId as plain string references to ledger journals. recognizeRevenue() creates a balanced AR entry (DR: Accounts Receivable, CR: Revenue, CR: Tax Payable). recordPayment() creates a balanced cash receipt entry (DR: Cash, CR: Accounts Receivable). Both methods return null or throw if the ledgers package is not installed.

Cross-Package References

Customer and Vendor link to @happyvertical/smrt-profiles via plain profileId string. Invoice and Payment reference @happyvertical/smrt-ledgers journals via plain string IDs (arJournalId, revenueJournalId, journalId). All models use @TenantScoped({ mode: 'optional' }) with nullable tenantId.

Dependencies

  • @happyvertical/smrt-core -- ORM and code generation
  • @happyvertical/smrt-tenancy -- multi-tenant scoping
  • @happyvertical/smrt-types -- shared type definitions
  • Peer: @happyvertical/smrt-ledgers, @happyvertical/smrt-profiles, @happyvertical/smrt-svelte

Contributor guide

See AGENTS.md for package architecture, invariants, validation, and contributor guidance.