Data Models
Comprehensive overview of all data models in the E-Invoice API system
Data Models
This section provides a comprehensive overview of all data models used in the E-Invoice management system, including their structure, relationships, and constraints. These models represent the core entities for Malaysian e-invoicing compliance using the MyInvois API.
Core Models
User Model
The User model represents individual users in the system with support for multiple authentication methods including Shopify integration, license-based authentication, and traditional password authentication.
interface User {
id: number // Unique identifier
fullName: string | null // Full name of the user
email: string // Email address (unique)
password: string | null // Encrypted password (hidden in serialization)
apiKey: string | null // API key for programmatic access
authType: 'password' | 'license' | 'shopify' | 'api' | null // Authentication method
externalId: string | null // External ID from license auth service (UUID)
createdAt: DateTime // Creation timestamp
updatedAt: DateTime // Last update timestamp
// Relationships
companies: Company[] // Companies owned by this user
shopifyStores: ShopifyStore[] // Shopify stores linked to this user
invoices: Invoice[] // Invoices created by this user
adjustmentNotes: AdjustmentNote[] // Adjustment notes created by this user
submittedDocuments: SubmittedDocument[] // Documents submitted by this user
documentSubmissions: DocumentSubmission[] // Document submissions by this user
}Key Features:
- Multi-authentication support for different user types
- API key generation for programmatic access
- External ID support for license-based authentication
- Comprehensive relationship tracking for all user activities
Authentication Types:
- password: Traditional email/password authentication
- license: NextJS/better-auth for SaaS users
- shopify: Shopify app authentication for store owners
- api: Legacy API key authentication for integrations
Company Model
The Company model represents business entities that issue e-invoices, storing comprehensive business information required for Malaysian e-invoicing compliance and MyInvois API integration.
interface Company {
id: number // Unique identifier
userId: number // Foreign key to User (owner)
// MyInvois API Configuration
clientId: string // MyInvois API client ID
clientSecret: string // MyInvois API client secret (encrypted)
scope: string | null // API scope permissions
accessToken: string | null // Current OAuth access token
tokenExpiresIn: number | null // Token expiration duration (seconds)
tokenExpiresAt: DateTime | null // Token expiration timestamp
// Malaysian Business Information
name: string // Company or individual name
tinCode: string // Tax Identification Number (e.g., C25845632020)
registrationNumber: string // Business registration number (e.g., 201901234567)
registrationType: RegistrationType // BRN, PASSPORT, NRIC, etc.
sstRegistrationNumber: string // SST (Sales and Service Tax) registration
tourismTaxRegistrationNumber: string // Tourism tax registration
businessActivityDescription: string // Description of business activities
msicCode: string // Malaysian Standard Industrial Classification code
// Address Information
country: string // Country name (e.g., "Malaysia")
state: string // State/province name (e.g., "Kuala Lumpur")
zipCode: string // Postal code
city: string // City name
address: string // Street address
// Contact Information
phone: string // Contact phone number
email: string // Contact email address
bankAccount: string // Bank account details
exporterCertifiedNumber: string // For exporting companies only
// App Configuration
defaultTaxTypesAndRates: TaxRate[] // Default tax settings
setting: CompanyAppFeatureSetting // App-specific feature settings
createdAt: DateTime
updatedAt: DateTime
// Computed Properties
isCompanyReady: boolean // Whether company profile is complete for e-invoicing
asBuyer: Buyer // Company details formatted as UBL buyer
asSupplier: Supplier // Company details formatted as UBL supplier
// Relationships
user: User // Owner of this company
invoices: Invoice[] // Invoices issued by this company
adjustmentNotes: AdjustmentNote[] // Adjustment notes for this company
submittedDocuments: SubmittedDocument[] // Documents submitted by this company
}Key Features:
- Complete Malaysian business registration information
- MyInvois API integration with OAuth token management
- Automatic UBL (Universal Business Language) formatting
- Comprehensive tax and compliance settings
- Ready-state validation for e-invoicing capability
Invoice Model
The Invoice model represents e-invoices with comprehensive UBL structure for Malaysian e-invoicing compliance. It supports various invoice types and integrates with the MyInvois API for submission to LHDN (Malaysian tax authority).
interface Invoice {
id: number // Unique identifier
companyId: number // Foreign key to Company (issuer)
userId: number // Foreign key to User (creator)
consolidatedInvoiceId: number | null // Reference to consolidated invoice
// Status and Identification
isSubmittedToLhdn: boolean // Whether submitted to LHDN
isReady: boolean // Whether invoice is ready for submission
invoiceCode: number // Unique invoice code (cannot be repeated)
externalId: string // External reference ID (e.g., Shopify order ID)
type: InvoiceType // Invoice type (see enum below)
invoiceCodeWithPrefixAndDigits: string // Formatted invoice code with prefix
// UBL (Universal Business Language) Structure Fields
buyer: Buyer // Buyer information (customer)
supplier: Supplier // Supplier information (issuer)
lineItems: LineItem[] // Invoice line items with products/services
deliveryDetails?: DeliveryDetails // Delivery information (optional)
invoiceDateTime: InvoiceDateTime // Invoice date and time
foreignCurrency?: ForeignCurrency // Foreign currency details (optional)
billingPeriod?: BillingPeriod // Billing period information (optional)
payment?: Payment // Payment terms (optional)
prePayment?: Prepayment // Prepayment details (optional)
billingReferenceNumber?: string // Reference number (optional)
invoiceLevelAllowanceCharge?: InvoiceLevelAllowanceCharge // Discounts/charges (optional)
additionalDocumentReference?: AdditionalDocumentReference[] // Additional documents (optional)
createdAt: DateTime
updatedAt: DateTime
// Computed Properties
finalAdjustedAmount: number // Final amount after adjustments
status: InvoiceStatus // Current status (Draft, Pending, Submitted, Valid, Invalid, Cancelled)
latestAdjustmentNoteStatus: AdjustmentNoteStatus // Status of latest adjustment
legalMonetaryTotal: LegalMonetaryTotal // Calculated totals (tax-inclusive, tax-exclusive, etc.)
invoiceLevelLineItemTaxes: InvoiceLevelLineItemTaxes // Tax calculations
isTotalExceedOrEqual10k: boolean // Whether total exceeds RM10,000 (affects consolidation)
asEinvoice: EInvoiceV1 // UBL format properties representation for MyInvois API
isSubmittedAsConsolidatedInvoice: boolean // Whether part of consolidated invoice
// Relationships
company: Company // Issuing company
user: User // User who created the invoice
consolidatedInvoice: ConsolidatedInvoice // Parent consolidated invoice
submittedDocuments: SubmittedDocument[] // Submission records to MyInvois
adjustmentNotes: AdjustmentNote[] // Related adjustment notes
}Invoice Types:
enum InvoiceType {
INVOICE = 'INVOICE', // Standard invoice
SELF_BILLED_INVOICE = 'SELF_BILLED_INVOICE', // Self-billed invoice
PENDING_FINALIZE_INVOICE = 'PENDING_FINALIZE_INVOICE', // Pending finalization
PENDING_FINALIZE_SELF_BILLED_INVOICE = 'PENDING_FINALIZE_SELF_BILLED_INVOICE',
}Key Features:
- Full UBL compliance for Malaysian e-invoicing
- Automatic tax calculations and monetary totals
- Support for various invoice types including self-billed
- Integration with MyInvois API submission tracking
- Invoices automated consolidation support, including automated splitting of invoices into multiple line items depending on the conditions such as inconsistent tax rate for a tax type for multiple invoices, and automated splitting into another consolidated invoice due to total amount of consolidated invoices > RM 10,000.
AdjustmentNote Model
The AdjustmentNote model represents credit notes, debit notes, and refund notes that adjust previously issued invoices. These are essential for correcting or modifying invoice amounts after submission to LHDN.
interface AdjustmentNote {
id: number // Unique identifier
companyId: number // Foreign key to Company
userId: number // Foreign key to User
invoiceId: number | null // Reference to affected invoice
consolidatedInvoiceId: number | null // Reference to affected consolidated invoice
code: number // Adjustment note code (unique within company)
type: AdjustmentNoteType // Type of adjustment (see enum below)
lineItems: LineItem[] // Adjustment line items
issueDate: DateTime // Date of issue
invoiceCodeWithPrefixAndDigits: string // Formatted code with prefix
createdAt: DateTime
updatedAt: DateTime
// Computed Properties
status: AdjustmentStatus // Current status (Pending, Submitted, Valid, Invalid, Cancelled)
legalMonetaryTotal: LegalMonetaryTotal // Calculated totals
invoiceLevelLineItemTaxes: InvoiceLevelLineItemTaxes // Tax calculations
asEinvoice: EInvoiceV1 // UBL format representation
// Relationships
company: Company // Issuing company
user: User // User who created the note
invoice: Invoice // Target invoice (if applicable)
consolidatedInvoice: ConsolidatedInvoice // Target consolidated invoice (if applicable)
submittedDocuments: SubmittedDocument[] // Submission records
}Adjustment Note Types:
enum AdjustmentNoteType {
CREDIT_NOTE = 'CREDIT_NOTE', // Reduces invoice amount (refunds, discounts)
DEBIT_NOTE = 'DEBIT_NOTE', // Increases invoice amount (additional charges)
REFUND_NOTE = 'REFUND_NOTE', // Handles returns and refunds
}Key Features:
- Support for credit, debit, and refund adjustments
- References to original invoices with MyInvois UUID tracking
- UBL compliance for submission to LHDN
- Automatic calculation of adjustment amounts
ConsolidatedInvoice Model
The ConsolidatedInvoice model represents invoices that consolidate multiple individual invoices. This is used when buyer/supplier information is unavailable at the time of individual invoice creation, allowing businesses to submit consolidated invoices by month-end.
interface ConsolidatedInvoice {
id: number // Unique identifier
companyId: number // Foreign key to Company
userId: number // Foreign key to User
invoiceCode: number // Unique consolidated invoice code
externalId: string // External reference ID
type: ConsolidatedInvoiceType // Type of consolidated invoice
invoiceCodeWithPrefixAndDigits: string // Formatted code with prefix
// UBL Structure Fields (similar to Invoice)
buyer: Buyer // Consolidated buyer information
supplier: Supplier // Supplier information
lineItems: LineItem[] // Aggregated line items from individual invoices
deliveryDetails?: DeliveryDetails // Delivery information
invoiceDateTime: InvoiceDateTime // Invoice date and time
foreignCurrency?: ForeignCurrency // Foreign currency details
billingPeriod?: BillingPeriod // Billing period information
payment?: Payment // Payment terms
prePayment?: Prepayment // Prepayment details
billingReferenceNumber?: string // Reference number
invoiceLevelAllowanceCharge?: InvoiceLevelAllowanceCharge // Discounts/charges
additionalDocumentReference?: AdditionalDocumentReference[] // Additional documents
createdAt: DateTime
updatedAt: DateTime
// Computed Properties
status: ConsolidatedInvoiceStatus // Status based on submissions
latestAdjustmentNoteStatus: AdjustmentNoteStatus // Latest adjustment status
legalMonetaryTotal: LegalMonetaryTotal // Calculated totals
invoiceLevelLineItemTaxes: InvoiceLevelLineItemTaxes // Tax calculations
asEinvoice: EInvoiceV1 // UBL format representation
// Relationships
company: Company // Issuing company
user: User // User who created the consolidated invoice
invoices: Invoice[] // Individual invoices consolidated
submittedDocuments: SubmittedDocument[] // Submission records
adjustmentNotes: AdjustmentNote[] // Related adjustment notes
}Consolidated Invoice Types:
enum ConsolidatedInvoiceType {
CONSOLIDATED_INVOICE = 'CONSOLIDATED_INVOICE',
CONSOLIDATED_SELF_BILLED_INVOICE = 'CONSOLIDATED_SELF_BILLED_INVOICE',
}BusinessParty Model
The BusinessParty model stores information about business entities that can be used as buyers or suppliers in invoices. This provides a reusable repository of business party information.
interface BusinessParty {
id: number // Unique identifier
name: string // Company or individual name
tinCode: string // Tax Identification Number
registrationNumber: string // Business registration number
registrationType: RegistrationType // Type of registration
sstRegistrationNumber: string // SST registration number
tourismTaxRegistrationNumber: string // Tourism tax registration
businessActivityDescription: string // Business activity description
msicCode: string // Malaysian Standard Industrial Classification code
// Address Information
country: string // Country name
state: string // State/province name
zipCode: string // Postal code
city: string // City name
address: string // Street address
// Contact Information
phone: string // Contact phone number
email: string // Contact email address
bankAccount: string // Bank account details
exporterCertifiedNumber: string // For exporting companies only
createdAt: DateTime
updatedAt: DateTime
}ShopifyStore Model
The ShopifyStore model represents Shopify stores connected to the e-invoice system for automated invoice generation from Shopify orders.
interface ShopifyStore {
id: number // Unique identifier
shopDomain: string // Shopify store domain (e.g., "mystore.myshopify.com")
shopName: string | null // Store display name
accessToken: string | null // Shopify API access token
webhookTopic: string | null // Webhook event type (e.g., "orders/paid")
webhookAddress: string | null // Webhook endpoint URL
userId: number // Foreign key to User (store owner)
createdAt: DateTime
updatedAt: DateTime
// Relationships
user: User // Owner of this store connection
}Key Features:
- Shopify API integration for automated invoice generation
- Webhook support for real-time order processing
- Secure token storage for API access
DocumentSubmission Model
The DocumentSubmission model tracks batch submissions of documents to the MyInvois API. This provides audit trails and submission management.
interface DocumentSubmission {
id: number // Unique identifier
userId: number // Foreign key to User (submitter)
companyId: number // Foreign key to Company
submissionUid: string // MyInvois submission identifier (empty if failed)
totalDocuments: number // Number of documents in submission batch
createdAt: DateTime // Submission timestamp
updatedAt: DateTime
// Relationships
user: User // User who initiated submission
company: Company // Company the documents belong to
submittedDocuments: SubmittedDocument[] // Individual document records in this submission
}SubmittedDocument Model
The SubmittedDocument model tracks individual documents submitted to MyInvois and their current status with LHDN.
interface SubmittedDocument {
id: number // Unique identifier
documentSubmissionId: number // Foreign key to DocumentSubmission
adjustmentNoteId: number // Foreign key to AdjustmentNote
invoiceId: number // Foreign key to Invoice
companyId: number // Foreign key to Company
userId: number // Foreign key to User
consolidatedInvoiceId: number // Foreign key to ConsolidatedInvoice
code: string // Document code (invoice/adjustment note code)
uuid: string | null // MyInvois UUID for the document
status: DocumentStatus // Current status (see enum below)
failReason: string // Reason for failure (if status is Invalid)
failDetails: any[] // Detailed failure information from MyInvois
documentDetails: Object // UBL format snapshot of the document
type: DocumentType // Document type (invoice, adjustment note, etc.)
cancelReason: string // Reason for cancellation (if status is Cancelled)
longId: string // MyInvois long ID for anonymous queries
createdAt: DateTime // Submission timestamp
updatedAt: DateTime
// Relationships
submission: DocumentSubmission // Parent submission batch
invoice: Invoice // Related invoice (if applicable)
consolidatedInvoice: ConsolidatedInvoice // Related consolidated invoice (if applicable)
adjustmentNote: AdjustmentNote // Related adjustment note (if applicable)
company: Company // Issuing company
user: User // Submitting user
}Document Status:
type DocumentStatus = 'Submitted' | 'Cancelled' | 'Valid' | 'Invalid'EinvoiceRequest Model
The EinvoiceRequest model handles requests for e-invoice documents, typically from buyers requesting copies of invoices.
interface EinvoiceRequest {
id: number // Unique identifier
companyId: number // Foreign key to Company (processor)
invoiceCode: string // Requested invoice code
documentDetails: PartialEinvoiceV1 // Partial document information provided
status: 'Pending' | 'Reject' | 'Approve' // Request status
createdAt: DateTime // Request timestamp
updatedAt: DateTime
// Relationships
company: Company // Company processing the request
}Entity Relationships
erDiagram
User ||--o{ Company : "owns"
User ||--o{ ShopifyStore : "manages"
User ||--o{ Invoice : "creates"
User ||--o{ AdjustmentNote : "creates"
User ||--o{ DocumentSubmission : "submits"
Company ||--o{ Invoice : "issues"
Company ||--o{ AdjustmentNote : "issues"
Company ||--o{ ConsolidatedInvoice : "issues"
Company ||--o{ SubmittedDocument : "owns"
Company ||--o{ EinvoiceRequest : "processes"
Invoice ||--o{ AdjustmentNote : "adjusted by"
Invoice ||--o{ SubmittedDocument : "submitted as"
Invoice }o--|| ConsolidatedInvoice : "consolidated into"
ConsolidatedInvoice ||--o{ AdjustmentNote : "adjusted by"
ConsolidatedInvoice ||--o{ SubmittedDocument : "submitted as"
AdjustmentNote ||--o{ SubmittedDocument : "submitted as"
DocumentSubmission ||--o{ SubmittedDocument : "contains"
User {
int id PK
string fullName
string email UK
string password
string apiKey UK
string authType
string externalId UK
datetime createdAt
datetime updatedAt
}
Company {
int id PK
int userId FK
string clientId
string clientSecret
string name
string tinCode UK
string registrationNumber
string registrationType
string email
string phone
datetime createdAt
datetime updatedAt
}
Invoice {
int id PK
int companyId FK
int userId FK
int consolidatedInvoiceId FK
int invoiceCode UK
string externalId
string type
boolean isSubmittedToLhdn
boolean isReady
datetime createdAt
datetime updatedAt
}
AdjustmentNote {
int id PK
int companyId FK
int userId FK
int invoiceId FK
int consolidatedInvoiceId FK
int code UK
string type
datetime issueDate
datetime createdAt
datetime updatedAt
}
ConsolidatedInvoice {
int id PK
int companyId FK
int userId FK
int invoiceCode UK
string externalId
string type
datetime createdAt
datetime updatedAt
}
SubmittedDocument {
int id PK
int documentSubmissionId FK
int invoiceId FK
int adjustmentNoteId FK
int consolidatedInvoiceId FK
int companyId FK
int userId FK
string code
string uuid UK
string status
string type
datetime createdAt
datetime updatedAt
}
DocumentSubmission {
int id PK
int userId FK
int companyId FK
string submissionUid
int totalDocuments
datetime createdAt
datetime updatedAt
}
BusinessParty {
int id PK
string name
string tinCode UK
string registrationNumber
string registrationType
string email
string phone
datetime createdAt
datetime updatedAt
}
ShopifyStore {
int id PK
int userId FK
string shopDomain UK
string shopName
string accessToken
datetime createdAt
datetime updatedAt
}
EinvoiceRequest {
int id PK
int companyId FK
string invoiceCode
string status
datetime createdAt
datetime updatedAt
}Data Constraints and Validation
User Constraints
- Email: Must be unique across the system
- API Key: Must be unique when provided, generated using secure random bytes
- Auth Type: Must be one of: password, license, shopify, api
- External ID: Must be unique when provided (for license auth integration)
Company Constraints
- TIN Code: Must be unique across companies for the same user, follows Malaysian TIN format
- Invoice Code: Must be unique and sequential within each company
- Client ID/Secret: Required for MyInvois API integration
- Registration Type: Must be valid RegistrationType enum value
- Email: Must be valid email format
- MSIC Code: Must be valid Malaysian Standard Industrial Classification code
Invoice Constraints
- Invoice Code: Must be unique within the company scope, auto-incremented
- External ID: Must be unique when provided (e.g., Shopify order ID)
- Type: Must be valid InvoiceType enum value
- Line Items: Must contain at least one line item with valid UBL structure
- Buyer/Supplier: Must contain valid business party information
- Status Transitions: Cannot modify submitted invoices (isSubmittedToLhdn = true)
Business Logic Rules
Invoice Lifecycle
- Draft: Invoice created but not ready for submission (
isReady = false) - Pending: Invoice ready but not yet submitted to LHDN (
isReady = true, isSubmittedToLhdn = false) - Submitted: Submitted to MyInvois API, awaiting validation
- Valid: Accepted by LHDN, legally compliant
- Invalid: Rejected by LHDN, requires correction
- Cancelled: Cancelled after submission
Consolidation Rules
- Invoices exceeding RM10,000 cannot be consolidated
- Only pending invoices can be included in consolidated invoices
- Consolidated invoices must be submitted by month-end for previous month's pending invoices
- Self-billed invoices follow separate consolidation rules
Adjustment Note Rules
- Can only adjust valid or submitted invoices
- Credit notes reduce the original invoice amount
- Debit notes increase the original invoice amount
- Refund notes handle returns and refunds
- Must reference the original invoice's MyInvois UUID
API Response Formats
Standard Success Response
interface SuccessResponse<T> {
success: boolean // Always true for success
data: T // Response data
message?: string // Optional success message
}Paginated Response
interface PaginatedResponse<T> {
data: T[] // Array of items
meta: {
total: number // Total number of items
per_page: number // Items per page
current_page: number // Current page number
last_page: number // Last page number
from: number // First item number on page
to: number // Last item number on page
path: string // Base URL path
url: string // Current page URL
next_page_url: string | null // Next page URL
prev_page_url: string | null // Previous page URL
}
}Error Response
interface ErrorResponse {
errors: {
// Validation errors
[field: string]: string[] // Array of error messages per field
}
message: string // Primary error message
}Example API Responses
User with Companies
{
"success": true,
"data": {
"id": 1,
"full_name": "John Doe",
"email": "john@example.com",
"auth_type": "password",
"created_at": "2024-01-15T10:30:00.000Z",
"companies": [
{
"id": 1,
"name": "Acme Corporation Sdn Bhd",
"tin_code": "C12345678901",
"registration_number": "201901234567",
"is_company_ready": true
}
]
}
}Invoice with Relationships
{
"success": true,
"data": {
"id": 123,
"invoice_code": 1001,
"invoice_code_with_prefix_and_digits": "INV-001001",
"external_id": "shopify-order-456",
"type": "INVOICE",
"status": "Valid",
"is_ready": true,
"is_submitted_to_lhdn": true,
"final_adjusted_amount": 1060.0,
"legal_monetary_total": {
"line_extension_amount": 1000.0,
"tax_exclusive_amount": 1000.0,
"tax_inclusive_amount": 1060.0,
"payable_amount": 1060.0
},
"buyer": {
"name": "Customer Company Sdn Bhd",
"tin": "C11111111111",
"registration_number": "202111111111",
"address": {
"address_line_0": "123 Business Street",
"city_name": "Kuala Lumpur",
"postal_zone": "50000",
"country": "MYS",
"state": "14"
}
},
"supplier": {
"name": "Acme Corporation Sdn Bhd",
"tin": "C12345678901",
"registration_number": "201901234567"
},
"line_items": [
{
"id": "1",
"classification": "003",
"description": "Professional Services",
"unit_price": 1000.0,
"quantity": 1,
"measurement": "C62"
}
],
"submitted_documents": [
{
"id": 1,
"uuid": "ABC123-DEF456-GHI789",
"status": "Valid",
"long_id": "LIJAF97HJJKH8298KHADH09908570FDKK9S2LSIU"
}
]
}
}Document Submission Status
{
"success": true,
"data": {
"id": 1,
"submission_uid": "SUB123456789",
"total_documents": 5,
"created_at": "2024-01-15T10:30:00.000Z",
"submitted_documents": [
{
"id": 1,
"code": "INV-001001",
"uuid": "ABC123-DEF456-GHI789",
"status": "Valid",
"type": "INVOICE",
"fail_reason": null,
"fail_details": []
},
{
"id": 2,
"code": "INV-001002",
"uuid": null,
"status": "Invalid",
"type": "INVOICE",
"fail_reason": "Invalid TIN format",
"fail_details": [
{
"target": "Supplier.TIN",
"code": "MS-E-00008",
"error": "TIN format is invalid"
}
]
}
]
}
}Security and Performance
Data Security
- Client secrets encrypted at rest using application-level encryption
- API keys hashed and stored securely with rate limiting
- Access tokens short-lived with automatic refresh
- User data isolation ensures users can only access their own data
Performance Optimization
- Database indexes on frequently queried fields (user_id, company_id, invoice_code)
- Foreign key constraints ensure data integrity
- JSON column optimization for efficient UBL document storage
- Computed properties calculated on-demand for accuracy
- Pagination support for large result sets
Audit and Compliance
- Complete audit trail for all document submissions
- Status change tracking in submitted_documents table
- MyInvois API response storage for compliance and debugging
- User action logging with timestamp and user association
Next Steps
- Authentication - Learn about API authentication methods
- Companies - Configure company profiles for e-invoicing
- Invoices - Create and manage e-invoices
- Shopify Integration - Automate invoice generation