Add category table

This commit is contained in:
2026-06-08 12:29:59 +07:00
parent 094e8b2a47
commit 69d8c8ce5e
19 changed files with 1159 additions and 1 deletions
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS purchase_categories;
DROP TABLE IF EXISTS purchase_category_presets;
@@ -0,0 +1,64 @@
CREATE TABLE purchase_category_presets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
parent_id UUID REFERENCES purchase_category_presets(id) ON DELETE SET NULL,
code VARCHAR(100) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
type VARCHAR(20) NOT NULL CHECK (type IN ('raw_material', 'non_inventory')),
sort_order INTEGER NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE purchase_categories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
preset_id UUID REFERENCES purchase_category_presets(id) ON DELETE SET NULL,
parent_id UUID REFERENCES purchase_categories(id) ON DELETE SET NULL,
code VARCHAR(100) NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(20) NOT NULL CHECK (type IN ('raw_material', 'non_inventory')),
sort_order INTEGER NOT NULL DEFAULT 0,
is_system BOOLEAN NOT NULL DEFAULT false,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE (organization_id, code)
);
CREATE INDEX idx_purchase_category_presets_parent_id ON purchase_category_presets(parent_id);
CREATE INDEX idx_purchase_category_presets_type ON purchase_category_presets(type);
CREATE INDEX idx_purchase_category_presets_is_active ON purchase_category_presets(is_active);
CREATE INDEX idx_purchase_categories_organization_id ON purchase_categories(organization_id);
CREATE INDEX idx_purchase_categories_preset_id ON purchase_categories(preset_id);
CREATE INDEX idx_purchase_categories_parent_id ON purchase_categories(parent_id);
CREATE INDEX idx_purchase_categories_type ON purchase_categories(type);
CREATE INDEX idx_purchase_categories_is_active ON purchase_categories(is_active);
INSERT INTO purchase_category_presets (code, name, type, sort_order)
VALUES
('hpp', 'HPP', 'raw_material', 1),
('biaya_lain_lain', 'Biaya Lain-lain', 'non_inventory', 2)
ON CONFLICT (code) DO NOTHING;
INSERT INTO purchase_category_presets (parent_id, code, name, type, sort_order)
SELECT parent.id, child.code, child.name, child.type, child.sort_order
FROM purchase_category_presets parent
JOIN (
VALUES
('hpp', 'hpp_bakso_mie_ayam', 'Bakso & Mie Ayam', 'raw_material', 1),
('hpp', 'hpp_nusantara', 'Nusantara', 'raw_material', 2),
('hpp', 'hpp_ramen', 'Ramen', 'raw_material', 3),
('hpp', 'hpp_minuman_kopi', 'Minuman/Kopi', 'raw_material', 4),
('biaya_lain_lain', 'biaya_atk_perlengkapan', 'ATK & Perlengkapan', 'non_inventory', 1),
('biaya_lain_lain', 'biaya_makan_karyawan', 'Makan Karyawan', 'non_inventory', 2),
('biaya_lain_lain', 'biaya_bensin_parkir', 'Bensin & Parkir', 'non_inventory', 3),
('biaya_lain_lain', 'biaya_kebersihan_keamanan', 'Kebersihan & Keamanan', 'non_inventory', 4),
('biaya_lain_lain', 'biaya_gaji_dw', 'Gaji DW', 'non_inventory', 5),
('biaya_lain_lain', 'biaya_gaji_staff', 'Gaji Staff', 'non_inventory', 6),
('biaya_lain_lain', 'biaya_internet_server', 'Internet & Server', 'non_inventory', 7),
('biaya_lain_lain', 'biaya_air_listrik', 'Air & Listrik', 'non_inventory', 8),
('biaya_lain_lain', 'biaya_promosi', 'Promosi', 'non_inventory', 9)
) AS child(parent_code, code, name, type, sort_order) ON parent.code = child.parent_code
ON CONFLICT (code) DO NOTHING;
@@ -0,0 +1,2 @@
DROP TRIGGER IF EXISTS trigger_create_default_purchase_categories ON organizations;
DROP FUNCTION IF EXISTS create_default_purchase_categories();
@@ -0,0 +1,49 @@
CREATE OR REPLACE FUNCTION create_default_purchase_categories()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO purchase_categories (organization_id, preset_id, parent_id, code, name, type, sort_order, is_system, is_active, created_at, updated_at)
SELECT
NEW.id,
preset.id,
NULL,
preset.code,
preset.name,
preset.type,
preset.sort_order,
true,
preset.is_active,
NOW(),
NOW()
FROM purchase_category_presets preset
WHERE preset.parent_id IS NULL
AND preset.is_active = true
ON CONFLICT (organization_id, code) DO NOTHING;
INSERT INTO purchase_categories (organization_id, preset_id, parent_id, code, name, type, sort_order, is_system, is_active, created_at, updated_at)
SELECT
NEW.id,
child_preset.id,
parent_category.id,
child_preset.code,
child_preset.name,
child_preset.type,
child_preset.sort_order,
true,
child_preset.is_active,
NOW(),
NOW()
FROM purchase_category_presets child_preset
JOIN purchase_category_presets parent_preset ON child_preset.parent_id = parent_preset.id
JOIN purchase_categories parent_category ON parent_category.organization_id = NEW.id
AND parent_category.code = parent_preset.code
WHERE child_preset.is_active = true
ON CONFLICT (organization_id, code) DO NOTHING;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_create_default_purchase_categories
AFTER INSERT ON organizations
FOR EACH ROW
EXECUTE FUNCTION create_default_purchase_categories();
@@ -0,0 +1,3 @@
DELETE FROM purchase_categories
WHERE is_system = true
AND preset_id IS NOT NULL;
@@ -0,0 +1,39 @@
INSERT INTO purchase_categories (organization_id, preset_id, parent_id, code, name, type, sort_order, is_system, is_active, created_at, updated_at)
SELECT
org.id,
preset.id,
NULL,
preset.code,
preset.name,
preset.type,
preset.sort_order,
true,
preset.is_active,
NOW(),
NOW()
FROM organizations org
CROSS JOIN purchase_category_presets preset
WHERE preset.parent_id IS NULL
AND preset.is_active = true
ON CONFLICT (organization_id, code) DO NOTHING;
INSERT INTO purchase_categories (organization_id, preset_id, parent_id, code, name, type, sort_order, is_system, is_active, created_at, updated_at)
SELECT
org.id,
child_preset.id,
parent_category.id,
child_preset.code,
child_preset.name,
child_preset.type,
child_preset.sort_order,
true,
child_preset.is_active,
NOW(),
NOW()
FROM organizations org
JOIN purchase_category_presets child_preset ON child_preset.parent_id IS NOT NULL
JOIN purchase_category_presets parent_preset ON child_preset.parent_id = parent_preset.id
JOIN purchase_categories parent_category ON parent_category.organization_id = org.id
AND parent_category.code = parent_preset.code
WHERE child_preset.is_active = true
ON CONFLICT (organization_id, code) DO NOTHING;