chore: upload parte 2 - assets
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
-- Create categories table
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create components table
|
||||
CREATE TABLE IF NOT EXISTS components (
|
||||
id SERIAL PRIMARY KEY,
|
||||
part_number VARCHAR(100) NOT NULL UNIQUE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
category_id INTEGER REFERENCES categories(id) ON DELETE SET NULL,
|
||||
manufacturer VARCHAR(255),
|
||||
package_type VARCHAR(100),
|
||||
unit_price NUMERIC(12, 4) DEFAULT 0,
|
||||
stock_quantity INTEGER DEFAULT 0,
|
||||
min_stock_level INTEGER DEFAULT 0,
|
||||
datasheet_url TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create products table
|
||||
CREATE TABLE IF NOT EXISTS products (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
sku VARCHAR(100) NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
version VARCHAR(50) DEFAULT '1.0',
|
||||
status VARCHAR(50) DEFAULT 'draft',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create bom_items table (links components to products)
|
||||
CREATE TABLE IF NOT EXISTS bom_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
product_id INTEGER NOT NULL REFERENCES products(id) ON DELETE CASCADE,
|
||||
component_id INTEGER NOT NULL REFERENCES components(id) ON DELETE CASCADE,
|
||||
quantity INTEGER NOT NULL DEFAULT 1,
|
||||
reference_designator VARCHAR(255),
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(product_id, component_id, reference_designator)
|
||||
);
|
||||
|
||||
-- Seed some default categories
|
||||
INSERT INTO categories (name, description) VALUES
|
||||
('Resistors', 'Fixed and variable resistors'),
|
||||
('Capacitors', 'Ceramic, electrolytic, and film capacitors'),
|
||||
('Inductors', 'Coils, chokes, and transformers'),
|
||||
('Diodes', 'Signal, rectifier, Zener, and Schottky diodes'),
|
||||
('Transistors', 'BJT, MOSFET, and JFET transistors'),
|
||||
('ICs', 'Integrated circuits and microcontrollers'),
|
||||
('Connectors', 'Headers, sockets, and plug connectors'),
|
||||
('Crystals & Oscillators', 'Quartz crystals and oscillator modules'),
|
||||
('LEDs', 'Light emitting diodes and displays'),
|
||||
('Sensors', 'Temperature, pressure, and motion sensors')
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Add supplier fields to components table
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS supplier VARCHAR(255);
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS supplier_part_number VARCHAR(255);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS shelf_location VARCHAR(100);
|
||||
@@ -0,0 +1,17 @@
|
||||
CREATE TABLE IF NOT EXISTS stock_transactions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
component_id INTEGER NOT NULL REFERENCES components(id) ON DELETE CASCADE,
|
||||
transaction_type VARCHAR(20) NOT NULL DEFAULT 'purchase',
|
||||
quantity INTEGER NOT NULL,
|
||||
unit_cost NUMERIC(12,4) DEFAULT 0,
|
||||
total_cost NUMERIC(12,4) DEFAULT 0,
|
||||
supplier VARCHAR(255),
|
||||
supplier_part_number VARCHAR(100),
|
||||
order_reference VARCHAR(255),
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_stock_tx_component ON stock_transactions(component_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_stock_tx_created ON stock_transactions(created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_stock_tx_type ON stock_transactions(transaction_type);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE stock_transactions RENAME COLUMN order_reference TO supplier_order_ref;
|
||||
ALTER TABLE stock_transactions DROP COLUMN IF EXISTS supplier_part_number;
|
||||
@@ -0,0 +1,45 @@
|
||||
-- Customers table
|
||||
CREATE TABLE IF NOT EXISTS customers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
code VARCHAR(50) UNIQUE NOT NULL,
|
||||
email VARCHAR(255),
|
||||
phone VARCHAR(50),
|
||||
address TEXT,
|
||||
contact_person VARCHAR(255),
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Purchase Orders table
|
||||
CREATE TABLE IF NOT EXISTS purchase_orders (
|
||||
id SERIAL PRIMARY KEY,
|
||||
po_number VARCHAR(100) UNIQUE NOT NULL,
|
||||
customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
|
||||
status VARCHAR(20) DEFAULT 'draft' CHECK (status IN ('draft', 'confirmed', 'in_production', 'completed', 'cancelled')),
|
||||
order_date DATE DEFAULT CURRENT_DATE,
|
||||
due_date DATE,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Purchase Order Items (line items linking products with quantities)
|
||||
CREATE TABLE IF NOT EXISTS purchase_order_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
purchase_order_id INTEGER NOT NULL REFERENCES purchase_orders(id) ON DELETE CASCADE,
|
||||
product_id INTEGER NOT NULL REFERENCES products(id) ON DELETE RESTRICT,
|
||||
quantity INTEGER NOT NULL DEFAULT 1,
|
||||
unit_price NUMERIC(12, 4) DEFAULT 0,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_orders_customer_id ON purchase_orders(customer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_orders_status ON purchase_orders(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_orders_po_number ON purchase_orders(po_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_order_items_po_id ON purchase_order_items(purchase_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_order_items_product_id ON purchase_order_items(product_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_customers_code ON customers(code);
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Add missing customer_ref column
|
||||
ALTER TABLE purchase_orders ADD COLUMN IF NOT EXISTS customer_ref VARCHAR(255);
|
||||
|
||||
-- Update status check constraint to include 'shipped'
|
||||
ALTER TABLE purchase_orders DROP CONSTRAINT IF EXISTS purchase_orders_status_check;
|
||||
ALTER TABLE purchase_orders ADD CONSTRAINT purchase_orders_status_check
|
||||
CHECK (status IN ('draft', 'confirmed', 'in_production', 'shipped', 'completed', 'cancelled'));
|
||||
@@ -0,0 +1,30 @@
|
||||
-- Packing lists for shipping finished products
|
||||
CREATE TABLE IF NOT EXISTS packing_lists (
|
||||
id SERIAL PRIMARY KEY,
|
||||
packing_list_number VARCHAR(100) UNIQUE NOT NULL,
|
||||
purchase_order_id INTEGER NOT NULL REFERENCES purchase_orders(id),
|
||||
customer_id INTEGER NOT NULL REFERENCES customers(id),
|
||||
product_id INTEGER NOT NULL,
|
||||
quantity_shipped INTEGER NOT NULL DEFAULT 0,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'finalized')),
|
||||
shipped_date DATE,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Serial numbers for each packing list
|
||||
CREATE TABLE IF NOT EXISTS packing_list_serials (
|
||||
id SERIAL PRIMARY KEY,
|
||||
packing_list_id INTEGER NOT NULL REFERENCES packing_lists(id) ON DELETE CASCADE,
|
||||
serial_number VARCHAR(200) NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_packing_lists_po ON packing_lists(purchase_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_packing_lists_customer ON packing_lists(customer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_packing_list_serials_pl ON packing_list_serials(packing_list_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_packing_list_serials_sn ON packing_list_serials(serial_number);
|
||||
|
||||
-- Add shipped_quantity column to purchase_order_items to track how many units have been shipped
|
||||
ALTER TABLE purchase_order_items ADD COLUMN IF NOT EXISTS shipped_quantity INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,25 @@
|
||||
-- Drop the old packing_lists table and recreate with correct schema
|
||||
DROP TABLE IF EXISTS packing_list_serials CASCADE;
|
||||
DROP TABLE IF EXISTS packing_lists CASCADE;
|
||||
|
||||
CREATE TABLE packing_lists (
|
||||
id SERIAL PRIMARY KEY,
|
||||
purchase_order_id INTEGER NOT NULL REFERENCES purchase_orders(id),
|
||||
po_item_id INTEGER NOT NULL REFERENCES purchase_order_items(id),
|
||||
packing_number VARCHAR(50) NOT NULL UNIQUE,
|
||||
quantity INTEGER NOT NULL DEFAULT 0,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE packing_list_serials (
|
||||
id SERIAL PRIMARY KEY,
|
||||
packing_list_id INTEGER NOT NULL REFERENCES packing_lists(id) ON DELETE CASCADE,
|
||||
serial_number VARCHAR(200) NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_packing_lists_po ON packing_lists(purchase_order_id);
|
||||
CREATE INDEX idx_packing_lists_item ON packing_lists(po_item_id);
|
||||
CREATE INDEX idx_packing_serials_list ON packing_list_serials(packing_list_id);
|
||||
CREATE UNIQUE INDEX idx_packing_serials_unique ON packing_list_serials(serial_number);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE products ADD COLUMN IF NOT EXISTS stock_quantity INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
code VARCHAR(50) UNIQUE NOT NULL,
|
||||
email VARCHAR(255),
|
||||
phone VARCHAR(50),
|
||||
address TEXT,
|
||||
contact_person VARCHAR(255),
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_code ON suppliers(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_name ON suppliers(name);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS is_internal BOOLEAN NOT NULL DEFAULT false;
|
||||
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE IF NOT EXISTS supplier_packing_lists (
|
||||
id SERIAL PRIMARY KEY,
|
||||
supplier_id INTEGER NOT NULL REFERENCES suppliers(id),
|
||||
packing_number VARCHAR(255) NOT NULL UNIQUE,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS supplier_packing_list_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
supplier_packing_list_id INTEGER NOT NULL REFERENCES supplier_packing_lists(id) ON DELETE CASCADE,
|
||||
component_id INTEGER NOT NULL REFERENCES components(id),
|
||||
quantity INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_spl_supplier ON supplier_packing_lists(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_spli_packing ON supplier_packing_list_items(supplier_packing_list_id);
|
||||
@@ -0,0 +1,25 @@
|
||||
CREATE TABLE IF NOT EXISTS pick_lists (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(50) NOT NULL DEFAULT 'accepted',
|
||||
products_json JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pick_list_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
pick_list_id INTEGER NOT NULL REFERENCES pick_lists(id) ON DELETE CASCADE,
|
||||
component_id INTEGER NOT NULL REFERENCES components(id),
|
||||
part_number VARCHAR(255) NOT NULL,
|
||||
component_name VARCHAR(255) NOT NULL,
|
||||
category_name VARCHAR(255),
|
||||
package_type VARCHAR(100),
|
||||
shelf_location VARCHAR(100),
|
||||
quantity_needed NUMERIC NOT NULL DEFAULT 0,
|
||||
is_internal BOOLEAN NOT NULL DEFAULT false,
|
||||
sources_json JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_pick_list_items_pick_list ON pick_list_items(pick_list_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_pick_lists_created ON pick_lists(created_at DESC);
|
||||
@@ -0,0 +1,37 @@
|
||||
-- Drop old pick_lists tables
|
||||
DROP TABLE IF EXISTS pick_list_items CASCADE;
|
||||
DROP TABLE IF EXISTS pick_lists CASCADE;
|
||||
|
||||
-- Planning history: one row per accepted production plan
|
||||
CREATE TABLE IF NOT EXISTS planning_history (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(50) DEFAULT 'accepted',
|
||||
products_json JSONB,
|
||||
summary_json JSONB,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Planning history items: every BOM component for that plan
|
||||
CREATE TABLE IF NOT EXISTS planning_history_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
planning_id INTEGER NOT NULL REFERENCES planning_history(id) ON DELETE CASCADE,
|
||||
component_id INTEGER REFERENCES components(id),
|
||||
part_number VARCHAR(100),
|
||||
component_name VARCHAR(255),
|
||||
category_name VARCHAR(255),
|
||||
package_type VARCHAR(100),
|
||||
shelf_location VARCHAR(100),
|
||||
quantity_needed NUMERIC DEFAULT 0,
|
||||
stock_at_time NUMERIC DEFAULT 0,
|
||||
shortage NUMERIC DEFAULT 0,
|
||||
unit_price NUMERIC DEFAULT 0,
|
||||
is_internal BOOLEAN DEFAULT false,
|
||||
manufacturer VARCHAR(255),
|
||||
supplier VARCHAR(255),
|
||||
supplier_part_number VARCHAR(255),
|
||||
sources_json JSONB,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_planning_history_items_planning ON planning_history_items(planning_id);
|
||||
@@ -0,0 +1,30 @@
|
||||
-- Supplier Purchase Orders
|
||||
CREATE TABLE IF NOT EXISTS supplier_pos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
po_number VARCHAR(30) NOT NULL UNIQUE,
|
||||
supplier_id INTEGER NOT NULL REFERENCES suppliers(id) ON DELETE CASCADE,
|
||||
planning_id INTEGER REFERENCES planning_history(id) ON DELETE SET NULL,
|
||||
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'draft',
|
||||
notes TEXT,
|
||||
total_value NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Supplier Purchase Order line items
|
||||
CREATE TABLE IF NOT EXISTS supplier_po_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
supplier_po_id INTEGER NOT NULL REFERENCES supplier_pos(id) ON DELETE CASCADE,
|
||||
component_id INTEGER REFERENCES components(id) ON DELETE SET NULL,
|
||||
part_number VARCHAR(100),
|
||||
component_name VARCHAR(255),
|
||||
supplier_part_number VARCHAR(100),
|
||||
quantity INTEGER NOT NULL DEFAULT 0,
|
||||
unit_price NUMERIC(12,4) NOT NULL DEFAULT 0,
|
||||
line_total NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_supplier_pos_supplier ON supplier_pos(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_supplier_pos_planning ON supplier_pos(planning_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_supplier_po_items_po ON supplier_po_items(supplier_po_id);
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Widen po_number column to accommodate longer PO numbers (PO-EACH-YYYY_MM_DD-RR-SUPPLIERNAME)
|
||||
ALTER TABLE supplier_pos ALTER COLUMN po_number TYPE VARCHAR(100);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE supplier_po_items ADD COLUMN IF NOT EXISTS received_quantity INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Add customer_supplied boolean and customer_id FK to components table
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS customer_supplied BOOLEAN NOT NULL DEFAULT FALSE;
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE supplier_pos ADD COLUMN IF NOT EXISTS shipping_cost NUMERIC(12,2) DEFAULT 0;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE components ADD COLUMN IF NOT EXISTS specs jsonb DEFAULT '{}';
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE suppliers ADD COLUMN IF NOT EXISTS country VARCHAR DEFAULT '';
|
||||
ALTER TABLE suppliers ADD COLUMN IF NOT EXISTS currency VARCHAR DEFAULT 'EUR';
|
||||
@@ -0,0 +1,14 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const logoUrl = 'https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Preto_semfundo-QjUexykfB10GjO803zcUlswqR19RBV.png';
|
||||
|
||||
const res = await fetch(logoUrl);
|
||||
const arrayBuffer = await res.arrayBuffer();
|
||||
const base64 = Buffer.from(arrayBuffer).toString('base64');
|
||||
const dataUrl = `data:image/png;base64,${base64}`;
|
||||
|
||||
console.log(`Base64 length: ${base64.length}`);
|
||||
console.log('LOGO_START');
|
||||
console.log(dataUrl);
|
||||
console.log('LOGO_END');
|
||||
@@ -0,0 +1,59 @@
|
||||
-- Users table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(50) DEFAULT 'user',
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- User permissions table
|
||||
CREATE TABLE IF NOT EXISTS user_permissions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
-- Section access (which pages can be viewed)
|
||||
can_view_dashboard BOOLEAN DEFAULT true,
|
||||
can_view_components BOOLEAN DEFAULT true,
|
||||
can_view_products BOOLEAN DEFAULT true,
|
||||
can_view_production BOOLEAN DEFAULT true,
|
||||
can_view_suppliers BOOLEAN DEFAULT true,
|
||||
can_view_customers BOOLEAN DEFAULT true,
|
||||
can_view_stock_history BOOLEAN DEFAULT true,
|
||||
can_view_stock_take BOOLEAN DEFAULT true,
|
||||
can_view_logistics BOOLEAN DEFAULT true,
|
||||
can_view_settings BOOLEAN DEFAULT false,
|
||||
-- Financial visibility
|
||||
can_view_financial BOOLEAN DEFAULT false,
|
||||
-- Actions
|
||||
can_create BOOLEAN DEFAULT false,
|
||||
can_edit BOOLEAN DEFAULT false,
|
||||
can_delete BOOLEAN DEFAULT false,
|
||||
-- Download/export
|
||||
can_download BOOLEAN DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Sessions table for auth
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
token VARCHAR(255) UNIQUE NOT NULL,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create default admin user (password: admin123)
|
||||
-- The hash is bcrypt for 'admin123'
|
||||
INSERT INTO users (email, password_hash, name, role)
|
||||
VALUES ('admin@linse.com', '$2b$10$K7L1OJ45/4Y2nIvOLPjKYeOIEZqMh0XKmYZKJKjKmJKmJKjKmJKjK', 'Administrator', 'admin')
|
||||
ON CONFLICT (email) DO NOTHING;
|
||||
|
||||
-- Create permissions for admin user
|
||||
INSERT INTO user_permissions (user_id, can_view_dashboard, can_view_components, can_view_products, can_view_production, can_view_suppliers, can_view_customers, can_view_stock_history, can_view_stock_take, can_view_logistics, can_view_settings, can_view_financial, can_create, can_edit, can_delete, can_download)
|
||||
SELECT id, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true
|
||||
FROM users WHERE email = 'admin@linse.com'
|
||||
ON CONFLICT DO NOTHING;
|
||||
@@ -0,0 +1,28 @@
|
||||
import sharp from 'sharp';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const logoUrl = 'https://hebbkx1anhila5yf.public.blob.vercel-storage.com/Preto_semfundo-QjUexykfB10GjO803zcUlswqR19RBV.png';
|
||||
|
||||
const res = await fetch(logoUrl);
|
||||
const arrayBuffer = await res.arrayBuffer();
|
||||
const inputBuffer = Buffer.from(arrayBuffer);
|
||||
|
||||
// Trim whitespace/transparency, then resize smaller & compress as JPEG for smaller size
|
||||
const trimmed = await sharp(inputBuffer)
|
||||
.trim() // remove transparent/white borders
|
||||
.resize({ width: 400, fit: 'inside' }) // resize to max 400px wide
|
||||
.png({ quality: 60, compressionLevel: 9 })
|
||||
.toBuffer();
|
||||
|
||||
const base64 = trimmed.toString('base64');
|
||||
const dataUrl = `data:image/png;base64,${base64}`;
|
||||
|
||||
console.log(`Original size: ${inputBuffer.length} bytes`);
|
||||
console.log(`Cropped+compressed size: ${trimmed.length} bytes`);
|
||||
console.log(`Base64 length: ${base64.length} chars`);
|
||||
|
||||
// Output full data URL so we can embed it
|
||||
console.log('DATA_URL_START');
|
||||
console.log(dataUrl);
|
||||
console.log('DATA_URL_END');
|
||||
@@ -0,0 +1,5 @@
|
||||
-- Update admin password with proper bcrypt hash for 'admin123'
|
||||
-- Hash generated using bcrypt with 10 rounds
|
||||
UPDATE users
|
||||
SET password_hash = '$2a$10$rQnM1kkXhVrPjKjKkZvZcOxGxGx0Wz3Xz1Wz3Xz1Wz3Xz1Wz3Xz1W'
|
||||
WHERE email = 'admin@linse.com';
|
||||
@@ -0,0 +1,36 @@
|
||||
import bcrypt from "bcryptjs";
|
||||
import { neon } from "@neondatabase/serverless";
|
||||
|
||||
const sql = neon(process.env.DATABASE_URL);
|
||||
|
||||
async function resetAdminPassword() {
|
||||
const password = "admin123";
|
||||
const hash = await bcrypt.hash(password, 10);
|
||||
|
||||
console.log("Generated hash:", hash);
|
||||
|
||||
// Update admin user password
|
||||
await sql`UPDATE users SET password_hash = ${hash} WHERE email = 'admin@linse.com'`;
|
||||
|
||||
// Verify the user exists
|
||||
const users = await sql`SELECT id, email, name, role FROM users WHERE email = 'admin@linse.com'`;
|
||||
|
||||
if (users.length > 0) {
|
||||
console.log("Admin user updated:", users[0]);
|
||||
} else {
|
||||
// Create admin user if doesn't exist
|
||||
const newHash = await bcrypt.hash("admin123", 10);
|
||||
await sql`INSERT INTO users (email, password_hash, name, role) VALUES ('admin@linse.com', ${newHash}, 'Administrator', 'admin')`;
|
||||
|
||||
const newUser = await sql`SELECT id FROM users WHERE email = 'admin@linse.com'`;
|
||||
if (newUser.length > 0) {
|
||||
await sql`INSERT INTO user_permissions (user_id, can_view_dashboard, can_view_components, can_view_products, can_view_production, can_view_suppliers, can_view_customers, can_view_stock_history, can_view_stock_take, can_view_logistics, can_view_settings, can_view_financial, can_create, can_edit, can_delete, can_download, sections)
|
||||
VALUES (${newUser[0].id}, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, ARRAY['dashboard', 'components', 'products', 'production', 'suppliers', 'customers', 'stock-history', 'stock-take', 'logistics', 'settings'])`;
|
||||
console.log("Admin user created with permissions");
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Done!");
|
||||
}
|
||||
|
||||
resetAdminPassword().catch(console.error);
|
||||
Reference in New Issue
Block a user