Database Schema

Database Documentation

Complete database schema reference for ExportReady-Battery. The database is PostgreSQL hosted on Supabase.

Entity Relationships


┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ TENANTS │ │ BATCHES │ │ PASSPORTS │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ id (PK) │──┐ │ id (PK) │──┐ │ uuid (PK) │
│ company_name │ │ │ tenant_id(FK)│◄─┘ │ batch_id(FK) │◄─┐
│ email (UK) │ │ │ batch_name │ │ serial_number│ │
│ password_hash│ └───►│ specs (JSONB)│ │ manufacture_ │ │
│ epr_number │ │ market_region│ │ date │ │
│ bis_r_number │ │ pli_compliant│ │ status │ │
│ iec_code │ │ domestic_va │ │ created_at │ │
│ created_at │ │ created_at │ └──────────────┘ │
└──────────────┘ └──────────────┘ │
 │
┌──────────────┐ ┌──────────────┐ │
│ TEMPLATES │ │ SCAN_EVENTS │ │
├──────────────┤ ├──────────────┤ │
│ id (PK) │ │ id (PK) │ │
│ tenant_id(FK)│ │ passport_id │─────────────────────────┘
│ name │ │ (FK) │
│ specs (JSONB)│ │ ip_address │
│ created_at │ │ city │
└──────────────┘ │ country │
 │ device_type │
 │ scanned_at │
 └──────────────┘
 

PK = Primary Key, FK = Foreign Key, UK = Unique Key

Table Specifications

tenants

Stores company/organization information for multi-tenant support

ColumnTypeNullableDescription
idUUIDNOT NULLPrimary key, auto-generated
company_nameVARCHAR(255)NOT NULLCompany display name
emailVARCHAR(255)NOT NULLUnique login email
password_hashVARCHAR(255)NOT NULLbcrypt hashed password
addressTEXTNULLCompany address
logo_urlVARCHAR(500)NULLCompany logo URL
support_emailVARCHAR(255)NULLSupport contact email
websiteVARCHAR(255)NULLCompany website
epr_registration_numberVARCHAR(100)NULLCPCB EPR registration
bis_r_numberVARCHAR(50)NULLBIS CRS R-number
iec_codeVARCHAR(20)NULLImport Export Code
reset_tokenVARCHAR(255)NULLPassword reset token
reset_token_expiresTIMESTAMPTZNULLToken expiry time
quota_balanceINTNOT NULLPassport quota remaining
created_atTIMESTAMPTZNOT NULLAccount creation time

batches

Production batches containing battery specifications

ColumnTypeNullableDescription
idUUIDNOT NULLPrimary key
tenant_idUUIDNOT NULLFK to tenants.id
batch_nameVARCHAR(100)NOT NULLUser-defined name
specsJSONBNOT NULLBattery specifications
market_regionVARCHAR(20)NOT NULLINDIA, EU, or GLOBAL
pli_compliantBOOLEANNULLPLI eligibility (India)
domestic_value_addDECIMAL(5,2)NULLDVA percentage
cell_sourceVARCHAR(20)NULLIMPORTED or DOMESTIC
bill_of_entry_noVARCHAR(50)NULLCustoms entry no.
country_of_originVARCHAR(100)NULLCell origin country
customs_dateDATENULLCustoms clearance date
deleted_atTIMESTAMPTZNULLSoft delete timestamp
created_atTIMESTAMPTZNOT NULLBatch creation time

passports

Individual battery passports with unique identifiers

ColumnTypeNullableDescription
uuidUUIDNOT NULLPrimary key, passport ID
batch_idUUIDNOT NULLFK to batches.id
serial_numberVARCHAR(100)NOT NULLBattery serial no.
manufacture_dateDATENOT NULLManufacturing date
statusVARCHAR(50)NOT NULLCREATED, ACTIVE, SHIPPED, IN_SERVICE, RECALLED, RECYCLED, END_OF_LIFE
created_atTIMESTAMPTZNOT NULLCreation timestamp

templates

Reusable battery specification templates

ColumnTypeNullableDescription
idUUIDNOT NULLPrimary key
tenant_idUUIDNOT NULLFK to tenants.id
nameVARCHAR(100)NOT NULLTemplate name
specsJSONBNOT NULLSaved specifications
created_atTIMESTAMPTZNOT NULLCreation timestamp

scan_events

QR code scan tracking with geolocation

ColumnTypeNullableDescription
idUUIDNOT NULLPrimary key
passport_idUUIDNOT NULLFK to passports.uuid
ip_addressVARCHAR(45)NULLScanner IP address
cityVARCHAR(100)NULLGeolocated city
countryVARCHAR(100)NULLGeolocated country
device_typeVARCHAR(50)NULLMobile/Desktop
user_agentTEXTNULLBrowser user agent
scanned_atTIMESTAMPTZNOT NULLScan timestamp

transactions

Quota purchase and usage history

ColumnTypeNullableDescription
idUUIDNOT NULLPrimary key
tenant_idUUIDNOT NULLFK to tenants.id
descriptionVARCHAR(255)NOT NULLReason for transaction
quota_changeINTNOT NULLQuota amount (+/-)
batch_idUUIDNULLRelated batch (optional)
created_atTIMESTAMPTZNOT NULLTransaction time

JSONB Schema: specs

The specs column stores battery specifications as JSONB:

BatchSpec JSONB Structure
json
{
 "chemistry": "Li-ion NMC",
 "voltage": "48V",
 "capacity": "100Ah",
 "manufacturer": "Acme Batteries",
 "manufacturer_address": "Industrial Area, Delhi",
 "weight": "45kg",
 "carbon_footprint": "45 kg CO2e/kWh",
 "country_of_origin": "India",
 "recyclable": true,
 
 // EU-specific fields
 "materials": {
 "cobalt": { "percentage": 8.5, "recycled": 12 },
 "lithium": { "percentage": 3.2, "recycled": 4 },
 "nickel": { "percentage": 25.0, "recycled": 8 }
 },
 "certifications": ["CE", "UN38.3"],
 "eu_representative": "EU Rep GmbH",
 "eu_representative_email": "contact@eurep.eu"
}

Indexes

Database Indexes
sql
-- Performance indexes
CREATE INDEX idx_batches_tenant_id ON batches(tenant_id);
CREATE INDEX idx_passports_batch_id ON passports(batch_id);
CREATE INDEX idx_passports_serial_number ON passports(serial_number);
CREATE INDEX idx_passports_status ON passports(status);
CREATE INDEX idx_scan_events_passport_id ON scan_events(passport_id);
CREATE INDEX idx_scan_events_scanned_at ON scan_events(scanned_at);

-- Unique constraints
CREATE UNIQUE INDEX idx_tenants_email ON tenants(email);
CREATE UNIQUE INDEX idx_passports_batch_serial 
 ON passports(batch_id, serial_number);

-- Password reset lookup
CREATE INDEX idx_tenants_reset_token ON tenants(reset_token) 
 WHERE reset_token IS NOT NULL;

Migration History

000001initial_schemaCore tables: tenants, batches, passports
000002create_batch_templatesTemplates table for saved specs
000003create_scan_eventsQR scan tracking table
000004add_dual_modeMarket region, PLI, DVA fields
000005add_tenant_detailsProfile fields (address, website)
000006add_soft_delete_batchesdeleted_at for soft delete
000007add_india_complianceEPR, BIS, IEC, customs fields
000008add_quota_systemQuota balance and transactions
000009add_password_resetReset token fields