From 17d55bd2c0b4b247be1b0e7f48e2798ccb7793e0 Mon Sep 17 00:00:00 2001 From: "Hafizh A. Y" Date: Fri, 9 Jan 2026 16:43:20 +0700 Subject: [PATCH] fix(BE): fix code 500 when delete master data foreign to others table --- ...20260109093155_drop_unused_tables.down.sql | 1 + .../20260109093155_drop_unused_tables.up.sql | 1 + ...32_update_master_data_fk_restrict.down.sql | 20 ++++++++++ ...3832_update_master_data_fk_restrict.up.sql | 20 ++++++++++ internal/utils/error.go | 38 +++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 internal/database/migrations/20260109093155_drop_unused_tables.down.sql create mode 100644 internal/database/migrations/20260109093155_drop_unused_tables.up.sql create mode 100644 internal/database/migrations/20260109093832_update_master_data_fk_restrict.down.sql create mode 100644 internal/database/migrations/20260109093832_update_master_data_fk_restrict.up.sql diff --git a/internal/database/migrations/20260109093155_drop_unused_tables.down.sql b/internal/database/migrations/20260109093155_drop_unused_tables.down.sql new file mode 100644 index 00000000..f17c3a80 --- /dev/null +++ b/internal/database/migrations/20260109093155_drop_unused_tables.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS projects; diff --git a/internal/database/migrations/20260109093155_drop_unused_tables.up.sql b/internal/database/migrations/20260109093155_drop_unused_tables.up.sql new file mode 100644 index 00000000..f17c3a80 --- /dev/null +++ b/internal/database/migrations/20260109093155_drop_unused_tables.up.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS projects; diff --git a/internal/database/migrations/20260109093832_update_master_data_fk_restrict.down.sql b/internal/database/migrations/20260109093832_update_master_data_fk_restrict.down.sql new file mode 100644 index 00000000..bc43de5c --- /dev/null +++ b/internal/database/migrations/20260109093832_update_master_data_fk_restrict.down.sql @@ -0,0 +1,20 @@ +-- Revert master data foreign keys to CASCADE delete (except FCR) +ALTER TABLE nonstock_suppliers + DROP CONSTRAINT IF EXISTS nonstock_suppliers_nonstock_id_fkey, + DROP CONSTRAINT IF EXISTS nonstock_suppliers_supplier_id_fkey; + +ALTER TABLE nonstock_suppliers + ADD CONSTRAINT nonstock_suppliers_nonstock_id_fkey FOREIGN KEY (nonstock_id) + REFERENCES nonstocks (id) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT nonstock_suppliers_supplier_id_fkey FOREIGN KEY (supplier_id) + REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE; + +ALTER TABLE product_suppliers + DROP CONSTRAINT IF EXISTS product_suppliers_product_id_fkey, + DROP CONSTRAINT IF EXISTS product_suppliers_supplier_id_fkey; + +ALTER TABLE product_suppliers + ADD CONSTRAINT product_suppliers_product_id_fkey FOREIGN KEY (product_id) + REFERENCES products (id) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT product_suppliers_supplier_id_fkey FOREIGN KEY (supplier_id) + REFERENCES suppliers (id) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/internal/database/migrations/20260109093832_update_master_data_fk_restrict.up.sql b/internal/database/migrations/20260109093832_update_master_data_fk_restrict.up.sql new file mode 100644 index 00000000..dbb45637 --- /dev/null +++ b/internal/database/migrations/20260109093832_update_master_data_fk_restrict.up.sql @@ -0,0 +1,20 @@ +-- Update master data foreign keys to RESTRICT delete (except FCR) +ALTER TABLE nonstock_suppliers + DROP CONSTRAINT IF EXISTS nonstock_suppliers_nonstock_id_fkey, + DROP CONSTRAINT IF EXISTS nonstock_suppliers_supplier_id_fkey; + +ALTER TABLE nonstock_suppliers + ADD CONSTRAINT nonstock_suppliers_nonstock_id_fkey FOREIGN KEY (nonstock_id) + REFERENCES nonstocks (id) ON DELETE RESTRICT ON UPDATE CASCADE, + ADD CONSTRAINT nonstock_suppliers_supplier_id_fkey FOREIGN KEY (supplier_id) + REFERENCES suppliers (id) ON DELETE RESTRICT ON UPDATE CASCADE; + +ALTER TABLE product_suppliers + DROP CONSTRAINT IF EXISTS product_suppliers_product_id_fkey, + DROP CONSTRAINT IF EXISTS product_suppliers_supplier_id_fkey; + +ALTER TABLE product_suppliers + ADD CONSTRAINT product_suppliers_product_id_fkey FOREIGN KEY (product_id) + REFERENCES products (id) ON DELETE RESTRICT ON UPDATE CASCADE, + ADD CONSTRAINT product_suppliers_supplier_id_fkey FOREIGN KEY (supplier_id) + REFERENCES suppliers (id) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/internal/utils/error.go b/internal/utils/error.go index ead06aeb..66537c00 100644 --- a/internal/utils/error.go +++ b/internal/utils/error.go @@ -2,11 +2,14 @@ package utils import ( "errors" + "strings" "gitlab.com/mbugroup/lti-api.git/internal/common/validation" "gitlab.com/mbugroup/lti-api.git/internal/response" "github.com/gofiber/fiber/v2" + "github.com/jackc/pgconn" + pgconnv5 "github.com/jackc/pgx/v5/pgconn" ) func ErrorHandler(c *fiber.Ctx, err error) error { @@ -14,6 +17,10 @@ func ErrorHandler(c *fiber.Ctx, err error) error { return response.Error(c, fiber.StatusBadRequest, message, nil) } + if statusCode, message := mapPgError(err); statusCode != 0 { + return response.Error(c, statusCode, message, nil) + } + var fiberErr *fiber.Error if errors.As(err, &fiberErr) { return response.Error(c, fiberErr.Code, fiberErr.Message, nil) @@ -26,6 +33,37 @@ func NotFoundHandler(c *fiber.Ctx) error { return response.Error(c, fiber.StatusNotFound, "Endpoint Not Found", nil) } +func mapPgError(err error) (int, string) { + code, message := getPgErrorDetails(err) + if code == "" { + return 0, "" + } + + switch code { + case "23503": + return fiber.StatusConflict, "Data tidak bisa dihapus karena masih digunakan oleh data lain." + case "P0001": + if strings.HasPrefix(message, "Cannot soft delete") { + return fiber.StatusConflict, "Data tidak bisa dihapus karena masih digunakan oleh data lain." + } + } + + return 0, "" +} + +func getPgErrorDetails(err error) (string, string) { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) { + return pgErr.Code, pgErr.Message + } + + var pgErrV5 *pgconnv5.PgError + if errors.As(err, &pgErrV5) { + return pgErrV5.Code, pgErrV5.Message + } + + return "", "" +} func BadRequest(msg string) error { return fiber.NewError(fiber.StatusBadRequest, msg)