-- USERS
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    id_user BIGINT NOT NULL,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(50) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ
);

CREATE UNIQUE INDEX users_id_user_unique ON users (id_user)
WHERE
    deleted_at IS NULL;

CREATE UNIQUE INDEX users_email_unique ON users (email)
WHERE
    deleted_at IS NULL;

-- FLAGS
CREATE TABLE flags (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    flagable_id BIGINT NOT NULL,
    flagable_type VARCHAR(50) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW ()
);

CREATE UNIQUE INDEX flags_unique_flagable ON flags (name, flagable_id, flagable_type);

CREATE INDEX flags_flagable_lookup ON flags (flagable_type, flagable_id);

-- PRODUCT CATEGORIES
CREATE TABLE product_categories (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    code VARCHAR(10) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX product_categories_name_unique ON product_categories (name)
WHERE
    deleted_at IS NULL;

CREATE UNIQUE INDEX product_categories_code_unique ON product_categories (code)
WHERE
    deleted_at IS NULL;

-- UOM
CREATE TABLE uoms (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX uoms_name_unique ON uoms (name)
WHERE
    deleted_at IS NULL;

-- BANKS
CREATE TABLE banks (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    alias VARCHAR(5) NOT NULL,
    owner VARCHAR(50),
    account_number VARCHAR(50) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX banks_name_unique ON banks (name)
WHERE
    deleted_at IS NULL;

-- AREAS
CREATE TABLE areas (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX areas_name_unique ON areas (name)
WHERE
    deleted_at IS NULL;

-- LOCATIONS
CREATE TABLE locations (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    address TEXT NOT NULL,
    area_id BIGINT NOT NULL REFERENCES areas (id) ON DELETE RESTRICT ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX locations_name_unique ON locations (name)
WHERE
    deleted_at IS NULL;

-- KANDANG
CREATE TABLE kandangs (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    location_id BIGINT NOT NULL REFERENCES locations (id) ON DELETE RESTRICT ON UPDATE CASCADE,
    pic_id BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX kandangs_name_unique ON kandangs (name)
WHERE
    deleted_at IS NULL;

-- WAREHOUSES
CREATE TABLE warehouses (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    type VARCHAR(50) NOT NULL,
    area_id BIGINT NOT NULL REFERENCES areas (id) ON DELETE RESTRICT ON UPDATE CASCADE,
    location_id BIGINT REFERENCES locations (id) ON DELETE SET NULL ON UPDATE CASCADE,
    kandang_id BIGINT REFERENCES kandangs (id) ON DELETE SET NULL ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX warehouses_name_unique ON warehouses (name)
WHERE
    deleted_at IS NULL;

-- CUSTOMERS
CREATE TABLE customers (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    pic_id BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
    type VARCHAR(50) NOT NULL,
    address TEXT NOT NULL,
    phone VARCHAR(20) NOT NULL,
    email VARCHAR(50) NOT NULL,
    account_number VARCHAR(50) NOT NULL,
    balance NUMERIC(15, 3) DEFAULT 0,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX customers_name_unique ON customers (name)
WHERE
    deleted_at IS NULL;

-- NONSTOCK
CREATE TABLE nonstocks (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    uom_id BIGINT NOT NULL REFERENCES uoms (id) ON DELETE RESTRICT ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX nonstocks_name_unique ON nonstocks (name)
WHERE
    deleted_at IS NULL;

-- FCR
CREATE TABLE fcrs (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX fcrs_name_unique ON fcrs (name)
WHERE
    deleted_at IS NULL;

CREATE TABLE fcr_standards (
    id BIGSERIAL PRIMARY KEY,
    fcr_id BIGINT NOT NULL REFERENCES fcrs (id) ON DELETE CASCADE ON UPDATE CASCADE,
    weight NUMERIC(15, 3) NOT NULL,
    fcr_number NUMERIC(15, 3) NOT NULL,
    mortality NUMERIC(15, 3) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ
);

-- SUPPLIERS
CREATE TABLE suppliers (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    alias VARCHAR(5) NOT NULL,
    pic VARCHAR(50) NOT NULL,
    type VARCHAR(50) NOT NULL,
    category VARCHAR(20) NOT NULL,
    hatchery VARCHAR(50),
    phone VARCHAR(20) NOT NULL,
    email VARCHAR(50) NOT NULL,
    address TEXT NOT NULL,
    npwp VARCHAR(50),
    account_number VARCHAR(50),
    balance NUMERIC(15, 3) DEFAULT 0,
    due_date INT NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX suppliers_name_unique ON suppliers (name)
WHERE
    deleted_at IS NULL;

CREATE TABLE nonstock_suppliers (
    nonstock_id BIGINT NOT NULL REFERENCES nonstocks (id) ON DELETE CASCADE ON UPDATE CASCADE,
    supplier_id BIGINT NOT NULL REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    PRIMARY KEY (nonstock_id, supplier_id)
);

-- PRODUCTS
CREATE TABLE products (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    brand VARCHAR(50) NOT NULL,
    sku VARCHAR(100),
    uom_id BIGINT NOT NULL REFERENCES uoms (id) ON DELETE RESTRICT ON UPDATE CASCADE,
    product_category_id BIGINT NOT NULL REFERENCES product_categories (id) ON DELETE RESTRICT ON UPDATE CASCADE,
    product_price NUMERIC(15, 3) NOT NULL,
    selling_price NUMERIC(15, 3),
    tax NUMERIC(15, 3),
    expiry_period INT,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

CREATE UNIQUE INDEX products_name_unique ON products (name)
WHERE
    deleted_at IS NULL;

CREATE UNIQUE INDEX products_sku_unique ON products (sku)
WHERE
    deleted_at IS NULL;

CREATE TABLE product_suppliers (
    product_id BIGINT NOT NULL REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE,
    supplier_id BIGINT NOT NULL REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    PRIMARY KEY (product_id, supplier_id)
);

-- PROJECTS
CREATE TABLE projects (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ,
    created_by BIGINT REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE
);

-- PRODUCT WAREHOUSES TABLE
CREATE TABLE product_warehouses (
    id BIGSERIAL PRIMARY KEY,
    product_id BIGINT NOT NULL REFERENCES products (id),
    warehouse_id BIGINT NOT NULL REFERENCES warehouses (id),
    quantity INTEGER NOT NULL DEFAULT 0,
    created_by BIGINT NOT NULL REFERENCES users (id),
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ
);

-- INDEXES
CREATE INDEX idx_product_warehouses_product_id ON product_warehouses (product_id);

CREATE INDEX idx_product_warehouses_warehouse_id ON product_warehouses (warehouse_id);

CREATE INDEX idx_product_warehouses_deleted_at ON product_warehouses (deleted_at);

CREATE UNIQUE INDEX idx_product_warehouses_unique ON product_warehouses (product_id, warehouse_id)
WHERE
    deleted_at IS NULL;

-- STOCK LOGS
CREATE TABLE stock_logs (
    id BIGSERIAL PRIMARY KEY,
    transaction_type VARCHAR(20) NOT NULL,
    quantity NUMERIC(15, 3) NOT NULL,
    before_quantity NUMERIC(15, 3) NOT NULL,
    after_quantity NUMERIC(15, 3) NOT NULL,
    log_type VARCHAR(50) NOT NULL,
    log_id BIGINT,
    note TEXT,
    product_warehouse_id BIGINT NOT NULL REFERENCES product_warehouses (id) ON DELETE CASCADE ON UPDATE CASCADE,
    created_by BIGINT NOT NULL REFERENCES users (id) ON DELETE SET NULL ON UPDATE CASCADE,
    created_at TIMESTAMPTZ DEFAULT NOW (),
    updated_at TIMESTAMPTZ DEFAULT NOW (),
    deleted_at TIMESTAMPTZ
);

-- Create indexes for better performance
CREATE INDEX stock_logs_product_warehouse_id_idx ON stock_logs (product_warehouse_id);

CREATE INDEX stock_logs_log_type_log_id_idx ON stock_logs (log_type, log_id);

CREATE INDEX stock_logs_created_by_idx ON stock_logs (created_by);

CREATE INDEX stock_logs_created_at_idx ON stock_logs (created_at);

CREATE INDEX stock_logs_deleted_at_idx ON stock_logs (deleted_at);