import { Migration } from '@mikro-orm/migrations'; export class Migration20260404083020 extends Migration { override async up(): Promise { //recalc_invoice_totals this.addSql(` CREATE OR REPLACE FUNCTION recalc_invoice_totals() RETURNS TRIGGER AS $$ DECLARE v_invoice_id char(26); v_subtotal int; v_discount int; v_tax int; v_total int; v_paid int; v_enable_tax boolean; BEGIN v_invoice_id := COALESCE(NEW.invoice_id, OLD.invoice_id); SELECT COALESCE(SUM(sub_total),0), COALESCE(SUM(discount),0) INTO v_subtotal, v_discount FROM invoice_items WHERE invoice_id = v_invoice_id AND deleted_at IS NULL; SELECT enable_tax INTO v_enable_tax FROM invoices WHERE id = v_invoice_id; IF v_enable_tax THEN v_tax := (v_subtotal - v_discount) * 0.10; ELSE v_tax := 0; END IF; v_total := (v_subtotal - v_discount) + v_tax; SELECT COALESCE(SUM(amount),0) INTO v_paid FROM payments WHERE invoice_id = v_invoice_id AND status = 'paid' AND deleted_at IS NULL; UPDATE invoices SET sub_total = v_subtotal, discount = v_discount, tax_amount = v_tax, total = v_total, paid_amount = v_paid, balance = v_total - v_paid WHERE id = v_invoice_id; RETURN NULL; END; $$ LANGUAGE plpgsql; `); // trigger this.addSql(` CREATE TRIGGER trg_invoice_items_recalc AFTER INSERT OR UPDATE OR DELETE ON invoice_items FOR EACH ROW EXECUTE FUNCTION recalc_invoice_totals(); `); // recalc_invoice_payments this.addSql(` CREATE OR REPLACE FUNCTION recalc_invoice_payments() RETURNS TRIGGER AS $$ DECLARE v_invoice_id char(26); v_paid int; v_total int; BEGIN v_invoice_id := COALESCE(NEW.invoice_id, OLD.invoice_id); SELECT COALESCE(SUM(amount),0) INTO v_paid FROM payments WHERE invoice_id = v_invoice_id AND status = 'paid' AND deleted_at IS NULL; SELECT total INTO v_total FROM invoices WHERE id = v_invoice_id; UPDATE invoices SET paid_amount = v_paid, balance = v_total - v_paid WHERE id = v_invoice_id; RETURN NULL; END; $$ LANGUAGE plpgsql; `); // trigger this.addSql(` CREATE TRIGGER trg_payments_recalc AFTER INSERT OR UPDATE OR DELETE ON payments FOR EACH ROW EXECUTE FUNCTION recalc_invoice_payments(); `); this.addSql(`CREATE SEQUENCE invoice_number_seq START 1;`); this.addSql(` ALTER TABLE invoices ALTER COLUMN invoice_number SET DEFAULT nextval('invoice_number_seq'); `); } override async down(): Promise { this.addSql(`DROP TRIGGER IF EXISTS trg_invoice_items_recalc ON invoice_items;`); this.addSql(`DROP TRIGGER IF EXISTS trg_payments_recalc ON payments;`); this.addSql(`DROP FUNCTION IF EXISTS recalc_invoice_totals;`); this.addSql(`DROP FUNCTION IF EXISTS recalc_invoice_payments;`); // remove default from invoice_number this.addSql(` ALTER TABLE invoices ALTER COLUMN invoice_number DROP DEFAULT; `); // drop sequence this.addSql(`DROP SEQUENCE IF EXISTS invoice_number_seq;`); } }