Add sales tracking system with customers, analytics, and inventory management
All checks were successful
Deploy / deploy (push) Successful in 2m26s

- Add customers table (021) and sales/sale_items tables (022) migrations
- Add customer CRUD, sale CRUD (transactional with auto inventory decrement/restore),
  and analytics API endpoints (overview, top sellers, revenue chart, inventory alerts)
- Add sales page with NewSaleModal (customer autocomplete, multi-item form,
  color-based pricing, stock validation) and SaleDetailModal
- Add customers page with search, inline editing, and purchase history
- Add analytics dashboard with recharts (revenue line chart, top sellers bar,
  refill vs spulna pie chart, inventory alerts table with stockout estimates)
- Add customerService, saleService, analyticsService to frontend API layer
- Update sidebar navigation on all admin pages
This commit is contained in:
DaX
2026-03-04 23:58:57 +01:00
parent e9afe8bc35
commit ff6abdeef0
12 changed files with 2881 additions and 30 deletions

View File

@@ -0,0 +1,16 @@
-- Add customers table for tracking buyers
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE customers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
phone VARCHAR(50),
city VARCHAR(255),
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Phone is the natural dedup key
CREATE UNIQUE INDEX idx_customers_phone ON customers (phone) WHERE phone IS NOT NULL;
CREATE INDEX idx_customers_name ON customers (name);

View File

@@ -0,0 +1,24 @@
-- Add sales and sale_items tables for tracking transactions
CREATE TABLE sales (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID REFERENCES customers(id) ON DELETE SET NULL,
total_amount INTEGER NOT NULL DEFAULT 0,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE sale_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sale_id UUID NOT NULL REFERENCES sales(id) ON DELETE CASCADE,
filament_id UUID NOT NULL REFERENCES filaments(id) ON DELETE RESTRICT,
item_type VARCHAR(10) NOT NULL CHECK (item_type IN ('refill', 'spulna')),
quantity INTEGER NOT NULL DEFAULT 1 CHECK (quantity > 0),
unit_price INTEGER NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_sales_customer_id ON sales (customer_id);
CREATE INDEX idx_sales_created_at ON sales (created_at);
CREATE INDEX idx_sale_items_sale_id ON sale_items (sale_id);
CREATE INDEX idx_sale_items_filament_id ON sale_items (filament_id);