Skip to main content
The BMS POS system uses PostgreSQL via Supabase with Entity Framework Core for ORM and migrations. The schema includes 14 entities organized into core transactions, configuration, and audit tables.

Core tables

employees

User accounts with role-based access control and hashed PINs.
ColumnTypeDescription
idintPrimary key
employee_idstring(10)Unique employee identifier
pinstring(60)BCrypt hashed PIN
namestring(100)Employee full name
rolestring(20)Manager, Cashier, or Inventory
is_managerboolBackward compatibility flag
is_activeboolAccount active status
created_datedatetimeAccount creation timestamp

products

Product catalog with pricing, stock levels, and categorization.
ColumnTypeDescription
idintPrimary key
barcodestring(50)Unique product barcode
namestring(200)Product name
descriptionstring(500)Product description (nullable)
pricedecimal(10,2)Selling price
costdecimal(10,2)Cost price
stock_quantityintCurrent stock level
min_stock_levelintLow stock threshold (default: 5)
variantstring(100)Product variant (nullable)
brandstring(100)Brand name (nullable)
categorystring(100)Product category (nullable)
image_urlstring(500)Product image URL (nullable)
unitstring(20)Unit of measure (default: “pcs”)
is_activeboolProduct active status
created_datedatetimeCreation timestamp
last_updateddatetimeLast modification timestamp

product_batches

Batch tracking with expiration monitoring and supplier information.
ColumnTypeDescription
idintPrimary key
product_idintForeign key to products
batch_numberstring(100)Unique batch identifier
quantityintBatch quantity
cost_per_unitdecimal(10,2)Unit cost for this batch
received_datedatetimeDate batch was received
expiration_datedatetimeExpiration date (nullable)
manufacturing_datedatetimeManufacturing date (nullable)
supplierstring(100)Supplier name (nullable)
lot_numberstring(100)Supplier’s lot number (nullable)
is_expiredboolManual expiration flag
is_recalledboolRecall status
recall_reasonstring(500)Reason for recall (nullable)
days_until_expirycomputedCalculated days until expiration
expiry_statuscomputedGOOD, CAUTION, WARNING, CRITICAL, EXPIRED
created_datedatetimeCreation timestamp
last_updateddatetimeLast modification timestamp
Expiry status thresholds:
  • EXPIRED - 0 days or less
  • CRITICAL - 1-7 days
  • WARNING - 8-30 days
  • CAUTION - 31-60 days
  • GOOD - More than 60 days
  • NO_EXPIRY - No expiration date set

sales

Transaction records with payment details and status tracking.
ColumnTypeDescription
idintPrimary key
transaction_idstringUnique transaction identifier
employee_idintForeign key to employees
sale_datedatetimeTransaction timestamp
subtotaldecimalPre-tax subtotal
tax_ratedecimalTax percentage applied
tax_amountdecimalCalculated tax amount
discount_amountdecimalDiscount applied (default: 0)
discount_reasonstringReason for discount (nullable)
totaldecimalFinal total amount
amount_paiddecimalAmount tendered by customer
changedecimalChange returned
payment_methodstringCash, Card, or ETF/Digital
statusstringCompleted, Voided, or Refunded
notesstringAdditional notes (nullable)

sale_items

Line items for each transaction with product details at time of sale.
ColumnTypeDescription
idintPrimary key
sale_idintForeign key to sales
product_idintForeign key to products
quantityintQuantity sold
unit_pricedecimalPrice per unit at time of sale
line_totaldecimalTotal for this line item
product_namestringProduct name snapshot
product_barcodestringBarcode snapshot (nullable)

returns

Return records with approval workflow.
ColumnTypeDescription
idintPrimary key
return_idstringUnique return identifier
original_sale_idintForeign key to original sale
return_datedatetimeReturn timestamp
statusstringCompleted, Pending, or Cancelled
total_refund_amountdecimalTotal amount refunded
processed_by_employee_idintEmployee who processed return
approved_by_employee_idintManager who approved (nullable)
manager_approval_requiredboolWhether approval was needed
notesstringAdditional notes (nullable)

return_items

Line items for returns with condition and restock tracking.
ColumnTypeDescription
idintPrimary key
return_idintForeign key to returns
original_sale_item_idintOriginal sale item reference
product_idintForeign key to products
product_namestringProduct name
return_quantityintQuantity being returned
unit_pricedecimalUnit price from original sale
line_totaldecimalTotal for this return line
conditionstring”good” or “defective”
reasonstringReturn reason
restocked_to_inventoryboolWhether item was restocked

Inventory management

inventory_counts

Inventory count sessions for physical stock verification.
ColumnTypeDescription
idintPrimary key
count_namestring(100)Descriptive name for count
count_typestring(50)FULL, CYCLE, SPOT, or ANNUAL
started_datedatetimeCount start timestamp
completed_datedatetimeCount completion timestamp (nullable)
statusstring(20)IN_PROGRESS, COMPLETED, or CANCELLED
started_by_employee_idintEmployee who started count
completed_by_employee_idintEmployee who completed (nullable)
notesstring(500)Count notes (nullable)
total_items_countedintNumber of items counted
total_discrepanciesintNumber of items with variance
total_shrinkage_valuedecimal(10,2)Total value of missing stock
total_overage_valuedecimal(10,2)Total value of excess stock
net_variance_valuedecimal(10,2)Net financial impact

inventory_count_items

Individual product counts with variance tracking.
ColumnTypeDescription
idintPrimary key
inventory_count_idintForeign key to inventory_counts
product_idintForeign key to products
product_batch_idintForeign key to product_batches (nullable)
system_quantityintQuantity per system records
counted_quantityintPhysically counted quantity
varianceintDifference (counted - system)
cost_per_unitdecimal(10,2)Unit cost
variance_valuedecimal(10,2)Financial impact of variance
discrepancy_reasonstring(200)Reason for variance (nullable)
notesstring(500)Additional notes (nullable)
counted_by_employee_idintEmployee who counted
counted_datedatetimeCount timestamp
is_verifiedboolVerification status
verified_by_employee_idintVerifying employee (nullable)
verified_datedatetimeVerification timestamp (nullable)

stock_adjustments

Manual stock corrections with approval workflow and audit trail.
ColumnTypeDescription
idintPrimary key
product_idintForeign key to products
adjustment_typestring(50)DAMAGE, THEFT, EXPIRED, FOUND, CORRECTION, RETURN
quantity_changeintQuantity adjustment (can be negative)
quantity_beforeintStock level before adjustment
quantity_afterintStock level after adjustment
reasonstring(500)Reason for adjustment
notesstring(1000)Additional notes (nullable)
adjusted_by_employee_idintEmployee who made adjustment
cost_impactdecimal(10,2)Financial impact
adjustment_datedatetimeAdjustment timestamp
reference_numberstring(200)External reference (nullable)
requires_approvalboolWhether approval is needed
is_approvedboolApproval status
approved_by_employee_idintApproving employee (nullable)
approved_datedatetimeApproval timestamp (nullable)

Configuration tables

tax_settings

Tax rates and business information for receipts.
ColumnTypeDescription
idintPrimary key
business_namestringBusiness name for receipts
tax_numberstringTax registration number
business_addressstringBusiness address
enable_taxboolWhether tax is enabled (default: true)
tax_namestringPrimary tax name (default: “Sales Tax”)
tax_ratedecimalPrimary tax rate 0-100% (default: 10)
enable_secondary_taxboolEnable second tax (default: false)
secondary_tax_namestringSecondary tax name
secondary_tax_ratedecimalSecondary tax rate 0-100%
enable_tax_exemptionsboolAllow tax exemptions
notesstringAdditional notes (nullable)
created_datedatetimeCreation timestamp
last_updateddatetimeLast modification timestamp

system_settings

System-wide configuration for POS behavior, receipts, and returns.
ColumnTypeDescription
idintPrimary key
date_formatstringDate format (default: “MM/DD/YYYY”)
decimal_separatorstringDecimal separator (default: ”.”)
thousands_separatorstringThousands separator (default: ”,“)
auto_logout_minutesintAuto-logout timeout (default: 30)
default_payment_methodstringDefault payment method (default: “Cash”)
available_payment_methodsstringComma-separated payment methods
sound_effects_enabledboolEnable sound effects (default: true)
require_manager_approval_for_discountboolRequire manager approval for discounts
themestringUI theme (default: “light”)
font_scalingdoubleFont size multiplier (default: 1.0)
receipt_header_textstringReceipt header (nullable)
receipt_footer_textstringReceipt footer (nullable)
store_locationstringStore location (nullable)
phone_numberstringStore phone number (nullable)
print_receipt_automaticallyboolAuto-print receipts (default: true)
receipt_copiesintNumber of receipt copies (default: 1)
receipt_paper_sizestring58mm or 80mm (default: “80mm”)
show_receipt_previewboolShow preview before print
email_receipt_enabledboolEnable email receipts
default_receipt_emailstringDefault email for receipts (nullable)
receipt_font_sizestringSmall, Normal, or Large (default: “Normal”)
receipt_template_layoutstringCompact, Standard, or Detailed (default: “Standard”)
show_receipt_barcodeboolShow barcode on receipt (default: true)
enable_returnsboolEnable returns feature (default: true)
require_receipt_for_returnsboolRequire receipt for returns (default: true)
require_manager_approval_for_returnsboolRequire manager approval
restock_returned_itemsboolAuto-restock returned items (default: true)
allow_defective_item_returnsboolAllow defective returns (default: true)
return_time_limit_daysintReturn window in days (default: 7)
return_manager_approval_amountdecimalApproval threshold amount (default: 1000.00)
return_reasonsstringComma-separated return reasons
product_categoriesstringComma-separated product categories
created_datedatetimeCreation timestamp
last_updateddatetimeLast modification timestamp

admin_settings

Administrative settings for updates, security, and database management.
ColumnTypeDescription
idintPrimary key
current_versionstringCurrent system version (default: “1.2.0”)
update_statusstringchecking, up-to-date, available, downloading, ready, error
available_versionstringAvailable update version (nullable)
update_descriptionstringUpdate description (nullable)
require_strong_pinsboolEnforce strong PIN policy
max_failed_login_attemptsintLogin attempt limit (default: 5)
log_levelstringerror, warning, info, debug (default: “info”)
performance_metrics_enabledboolEnable metrics (default: true)
cache_enabledboolEnable caching (default: true)
database_statusstringDatabase connection status
last_backupdatetimeLast backup timestamp (nullable)
last_backup_methodstringCLI, Dashboard, or Manual (nullable)
last_backup_sizestringBackup file size (nullable)
last_backup_pathstringBackup file path (nullable)
created_datedatetimeCreation timestamp
last_updateddatetimeLast modification timestamp

Audit tables

user_activities

Complete audit trail of all user actions in the system.
ColumnTypeDescription
idintPrimary key
user_idintForeign key to employees (nullable)
user_namestring(100)User name at time of action
actionstring(200)Action description
detailsstringDetailed action information (nullable)
ip_addressstring(45)IP address (nullable)
timestampdatetimeAction timestamp
entity_typestring(50)Type of entity affected (nullable)
entity_idintID of entity affected (nullable)
action_typestring(20)CREATE, UPDATE, DELETE, VIEW, LOGIN, etc.

Relationships

One-to-many relationships

  • employeessales (one employee processes many sales)
  • employeesreturns (one employee processes many returns)
  • employeesstock_adjustments (one employee makes many adjustments)
  • productsproduct_batches (one product has many batches)
  • productssale_items (one product appears in many sales)
  • salessale_items (one sale has many line items)
  • salesreturns (one sale can have one return)
  • returnsreturn_items (one return has many line items)
  • inventory_countsinventory_count_items (one count has many items)

Foreign key constraints

All foreign key relationships enforce referential integrity with appropriate cascade rules:
  • Delete cascades for dependent records (e.g., sale_items when sale is deleted)
  • Restrict deletes for referenced records (e.g., cannot delete employee with active sales)
  • Nullable foreign keys for optional relationships (e.g., approved_by_employee_id)

Build docs developers (and LLMs) love