Database Schema

Last updated: December 16, 2025 MySQL 8.x

QR Igniter uses MySQL 8.x with a normalized schema designed for multi-tenant QR code management.

Entity Relationship

┌──────────┐     ┌──────────┐     ┌───────────┐     ┌──────────┐
│  Client  │────▶│  Brand   │────▶│ Campaign  │────▶│ QR Code  │
└──────────┘     └──────────┘     └───────────┘     └────┬─────┘
                      │                                   │
                      │ (logo)                            │
                      ▼                                   ▼
                ┌──────────┐                        ┌──────────┐
                │   File   │                        │   Scan   │
                │ Storage  │                        └──────────┘
                └──────────┘

Core Tables

clients

Column Type Description
idBIGINT UNSIGNEDPrimary key
nameVARCHAR(255)Client name
emailVARCHAR(255)Contact email
phoneVARCHAR(50)Contact phone
addressTEXTBusiness address
statusENUMactive, inactive
notesTEXTInternal notes
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update

brands

Column Type Description
idBIGINT UNSIGNEDPrimary key
client_idBIGINT UNSIGNEDFK to clients
nameVARCHAR(255)Brand name
logo_pathVARCHAR(255)Path to logo file
descriptionTEXTBrand description
websiteVARCHAR(255)Brand website URL
statusENUMactive, inactive
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update

campaigns

Column Type Description
idBIGINT UNSIGNEDPrimary key
brand_idBIGINT UNSIGNEDFK to brands
nameVARCHAR(255)Campaign name
descriptionTEXTCampaign details
start_dateDATEStart date
end_dateDATEEnd date (nullable)
statusENUMactive, paused, completed
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update

qr_codes

Column Type Description
idBIGINT UNSIGNEDPrimary key
campaign_idBIGINT UNSIGNEDFK to campaigns
gtinVARCHAR(14)GS1 GTIN (AI 01)
batch_lotVARCHAR(20)Batch/Lot (AI 10)
serial_numberVARCHAR(20)Serial (AI 21)
expiry_dateVARCHAR(6)YYMMDD (AI 17)
cpvVARCHAR(20)CPV (AI 22)
destination_urlVARCHAR(2048)Redirect URL
digital_link_uriVARCHAR(2048)Generated GS1 URI
use_interim_selectorBOOLEANShow selector page
embed_logoBOOLEANEmbed brand logo
statusENUMactive, inactive
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update

scans

Column Type Description
idBIGINT UNSIGNEDPrimary key
qr_code_idBIGINT UNSIGNEDFK to qr_codes
ip_addressVARCHAR(45)Client IP
user_agentTEXTBrowser/device info
device_typeENUMmobile, tablet, desktop
countryVARCHAR(100)Country name
cityVARCHAR(100)City name
languageVARCHAR(10)Accept-Language
referrerVARCHAR(2048)HTTP Referer
scanned_atTIMESTAMPScan timestamp

gtin_data

Column Type Description
idBIGINT UNSIGNEDPrimary key
gtinVARCHAR(14)Product GTIN
product_nameVARCHAR(255)Product name
brand_nameVARCHAR(255)Brand name
descriptionTEXTProduct description
image_urlVARCHAR(2048)Product image
categoryVARCHAR(255)Product category
metadataJSONAdditional data
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update

Indexes

-- QR Code lookups
INDEX idx_qr_codes_gtin (gtin)
INDEX idx_qr_codes_digital_link (digital_link_uri)
INDEX idx_qr_codes_campaign (campaign_id)

-- Scan analytics
INDEX idx_scans_qr_code (qr_code_id)
INDEX idx_scans_timestamp (scanned_at)
INDEX idx_scans_country (country)

-- GTIN lookups
UNIQUE INDEX idx_gtin_data_gtin (gtin)

Relationships

clients    1 ────── * brands
brands     1 ────── * campaigns
campaigns  1 ────── * qr_codes
qr_codes   1 ────── * scans

Next Steps