BEGIN; --? RECORDINGS (tabel induk recording harian) CREATE TABLE IF NOT EXISTS recordings ( id BIGSERIAL PRIMARY KEY, project_flock_id BIGINT NOT NULL, record_datetime TIMESTAMPTZ NOT NULL, record_date DATE, status INT NOT NULL DEFAULT 0, --? 0=draft,1=submitted,2=approved,3=rejected ontime INT NOT NULL DEFAULT 0, --? 1=ontime,0=late (pakai INT/BOOLEAN sesuai preferensi) day INT, total_depletion INT, cum_depletion_rate NUMERIC(7,3), daily_gain NUMERIC(7,3), avg_daily_gain NUMERIC(7,3), cum_intake INT, fcr_value NUMERIC(7,3), total_chick BIGINT, daily_depletion_rate NUMERIC(7,3), cum_depletion INT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), deleted_at TIMESTAMPTZ, created_by BIGINT, CONSTRAINT fk_recordings_project_flock FOREIGN KEY (project_flock_id) REFERENCES project_flock_kandangs(id), CONSTRAINT fk_recordings_created_by FOREIGN KEY (created_by) REFERENCES users(id), CONSTRAINT chk_recordings_status CHECK (status IN (0,1,2,3)), CONSTRAINT chk_recordings_ontime CHECK (ontime IN (0,1)), CONSTRAINT chk_recordings_day CHECK (day IS NULL OR day >= 1), CONSTRAINT chk_recordings_nonnegatives CHECK ( (total_depletion IS NULL OR total_depletion >= 0) AND (cum_depletion IS NULL OR cum_depletion >= 0) AND (total_chick IS NULL OR total_chick >= 0) AND (cum_intake IS NULL OR cum_intake >= 0) AND (daily_gain IS NULL OR daily_gain >= 0) AND (avg_daily_gain IS NULL OR avg_daily_gain >= 0) AND (fcr_value IS NULL OR fcr_value > 0) AND (daily_depletion_rate IS NULL OR daily_depletion_rate >= 0) AND (cum_depletion_rate IS NULL OR cum_depletion_rate >= 0) ) ); --? Set record_date otomatis berdasarkan record_datetime (pakai zona Asia/Jakarta) CREATE OR REPLACE FUNCTION trg_set_record_date() RETURNS trigger AS $$ BEGIN NEW.record_date := (NEW.record_datetime AT TIME ZONE 'Asia/Jakarta')::date; RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS recordings_set_record_date_trg ON recordings; CREATE TRIGGER recordings_set_record_date_trg BEFORE INSERT OR UPDATE OF record_datetime ON recordings FOR EACH ROW EXECUTE FUNCTION trg_set_record_date(); CREATE INDEX IF NOT EXISTS idx_recordings_flock_datetime ON recordings (project_flock_id, record_datetime); --? Unique harian (1 recording per hari dan per flock) CREATE UNIQUE INDEX IF NOT EXISTS uq_recordings_flock_record_date ON recordings (project_flock_id, record_date) WHERE deleted_at IS NULL; --? RECORDING_BWS (BW per recording) CREATE TABLE IF NOT EXISTS recording_bws ( id BIGSERIAL PRIMARY KEY, recording_id BIGINT NOT NULL, weight NUMERIC(8,2) NOT NULL, --? bobot per ekor/kelompok qty INT NOT NULL DEFAULT 1, --? jumlah ekor pada bobot ini notes VARCHAR, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), CONSTRAINT fk_recording_bws_recording FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE, CONSTRAINT chk_recording_bws_nonneg CHECK (weight >= 0 AND qty >= 1) ); CREATE INDEX IF NOT EXISTS idx_recording_bws_recording ON recording_bws (recording_id); --? RECORDING_DEPLETIONS CREATE TABLE IF NOT EXISTS recording_depletions ( id BIGSERIAL PRIMARY KEY, recording_id BIGINT NOT NULL, product_warehouse_id BIGINT NOT NULL, total BIGINT NOT NULL, notes VARCHAR, CONSTRAINT fk_recording_depl_recording FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE, CONSTRAINT fk_recording_depl_prodwh FOREIGN KEY (product_warehouse_id) REFERENCES product_warehouses(id), CONSTRAINT chk_recording_depl_total CHECK (total >= 0) ); CREATE INDEX IF NOT EXISTS idx_recording_depl_recording ON recording_depletions (recording_id); --? RECORDING_STOCKS CREATE TABLE IF NOT EXISTS recording_stocks ( id BIGSERIAL PRIMARY KEY, recording_id BIGINT NOT NULL, product_warehouse_id BIGINT NOT NULL, increase NUMERIC(10,3), --? penambahan (boleh NULL) decrease NUMERIC(10,3), --? pengurangan (boleh NULL) usage_amount BIGINT, --? pemakaian (opsional, jika konsep dipisah dari decrease) notes VARCHAR, CONSTRAINT fk_recording_stocks_recording FOREIGN KEY (recording_id) REFERENCES recordings(id) ON DELETE CASCADE, CONSTRAINT fk_recording_stocks_prodwh FOREIGN KEY (product_warehouse_id) REFERENCES product_warehouses(id), CONSTRAINT chk_recording_stocks_nonneg CHECK ( (increase IS NULL OR increase >= 0) AND (decrease IS NULL OR decrease >= 0) AND (usage_amount IS NULL OR usage_amount >= 0) ) ); CREATE INDEX IF NOT EXISTS idx_recording_stocks_recording ON recording_stocks (recording_id); CREATE INDEX IF NOT EXISTS idx_recording_stocks_product ON recording_stocks (product_warehouse_id); COMMIT;