package controllers import ( "context" "fmt" "math" "net/http" "reflect" "time" "kemendagri/sipd/services/master-sipd/models" "kemendagri/sipd/services/master-sipd/utils" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) type UrusanController struct { contextTimeout time.Duration pgxConn *pgxpool.Pool } func NewUrusanController(conn *pgxpool.Pool, timeout time.Duration) (controller *UrusanController) { controller = &UrusanController{ pgxConn: conn, contextTimeout: timeout, } return } func getUrusanDetailFields() []string { var field []string v := reflect.ValueOf(models.MstUrusanModel{}) for i := 0; i < v.Type().NumField(); i++ { field = append(field, v.Type().Field(i).Tag.Get("json")) } // log.Println("fields: ", field) return field } // Index lists of urusan func (c *UrusanController) Index( page, limit int, filter string, ) ( resp []models.MstUrusanModel, totalCount int, pageCount int, err error, ) { var q string resp = make([]models.MstUrusanModel, 0) pageCount = 1 offset := limit * (page - 1) var filterCond string if filter != "" { var filterMap map[string]string filterMap, err = utils.ValidateAndReturnFilterMap(filter, getUrusanDetailFields()) if err != nil { return resp, totalCount, pageCount, err } // log.Println("filterMap: ", filterMap) var key, val string for k, v := range filterMap { key = k val = v } switch key { case "nama_urusan": filterCond = fmt.Sprintf(" AND mu.%s ILIKE '%s%s%s' ", key, "%", val, "%") case "kode_urusan", "tahun": filterCond = fmt.Sprintf(" AND mu.%s = '%s' ", key, val) case "daerah_khusus", "jenis_pemda": filterCond = fmt.Sprintf(" AND '%s' = ANY(mu.%s) ", val, key) default: filterCond = "" } } // total data q = `SELECT COALESCE(COUNT(mu.id_urusan), 0) FROM "master_data"."mst_urusan" AS mu WHERE mu."locked"='f' AND mu."disable"='f' AND mu.deleted_by = 0 AND mu.deleted_at='0001-01-01 00:00:00'` + filterCond err = c.pgxConn.QueryRow(context.Background(), q).Scan(&totalCount) if err != nil { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengambil total data. - " + err.Error(), } return resp, totalCount, pageCount, err } var rows pgx.Rows q = `SELECT mu.id_urusan, mu.tahun, mu.kode_urusan, mu.nama_urusan, mu.locked, mu.disable FROM "master_data"."mst_urusan" AS mu WHERE mu."locked"='f' AND mu."disable"='f' AND mu.deleted_by = 0 AND mu.deleted_at='0001-01-01 00:00:00' ` q += filterCond q += ` ORDER BY mu.kode_urusan LIMIT $1 OFFSET $2` rows, err = c.pgxConn.Query(context.Background(), q, limit, offset) if err != nil { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengambil data. - " + err.Error(), } return resp, totalCount, pageCount, err } defer rows.Close() for rows.Next() { var m models.MstUrusanModel err = rows.Scan( &m.IDUrusan, &m.Tahun, &m.KodeUrusan, &m.NamaUrusan, &m.Locked, &m.Disable, ) if err != nil { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal iterasi data. - " + rows.Err().Error(), } return resp, totalCount, pageCount, err } resp = append(resp, m) } if rows.Err() != nil { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengambil data (rows). - " + rows.Err().Error(), } return resp, totalCount, pageCount, err } rows.Close() if totalCount > 0 && totalCount > limit { pageCount = int(math.Ceil(float64(totalCount) / float64(limit))) } return resp, totalCount, pageCount, err } // View detail of urusan func (c *UrusanController) View(id int, tahun int) (resp models.MstUrusanDetilModel, err error) { // log.Println("id: ", id) q := `SELECT mu.id_urusan, mu.tahun, mu.kode_urusan, mu.nama_urusan, mu.locked, mu.disable, mu.daerah_khusus, mu.jns_pemda , mu.created_at, mu.created_by, mu.updated_at, mu.updated_by, mu.deleted_at, mu.deleted_by FROM "master_data"."mst_urusan" AS mu WHERE mu."locked"='f' AND mu."disable"='f' AND mu.deleted_by = 0 AND mu.deleted_at='0001-01-01 00:00:00' AND mu.id_urusan=$1 AND mu.tahun=$2` err = c.pgxConn.QueryRow(context.Background(), q, id, tahun).Scan( &resp.IDUrusan, &resp.Tahun, &resp.KodeUrusan, &resp.NamaUrusan, &resp.Locked, &resp.Disable, &resp.DaerahKhusus, &resp.JenisPemda, &resp.CreatedAt, &resp.CreatedBy, &resp.UpdatedAt, &resp.UpdatedBy, &resp.DeletedAt, &resp.DeletedBy, ) if err != nil { if err.Error() == "no rows in result set" { err = utils.RequestError{ Code: http.StatusNotFound, Message: "Data tidak ditemukan", } } else { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengambil data. - " + err.Error(), } } return resp, err } if resp.DeletedBy > 0 && !resp.DeletedAt.IsZero() { err = utils.RequestError{ Code: http.StatusNotFound, Message: "Data sudah dihapus.", } return resp, err } return resp, err } // Create urusan func (c *UrusanController) Create(ctx context.Context, payload models.MstUrusanPayloadModel, createdBy int) (err error) { // Validasi duplikasi unique key var exists bool q := ` SELECT EXISTS ( SELECT 1 FROM "master_data"."mst_urusan" WHERE tahun = $1 AND kode_urusan = $2 AND deleted_by = 0 AND deleted_at = '0001-01-01 00:00:00' ) ` err = c.pgxConn.QueryRow(ctx, q, payload.Tahun, payload.KodeUrusan).Scan(&exists) if err != nil { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal memeriksa duplikasi data. - " + err.Error(), } return err } if exists { err = utils.RequestError{ Code: http.StatusBadRequest, Message: "Data dengan kode urusan dan tahun yang sama sudah ada", } return err } // Insert data baru q = ` INSERT INTO "master_data"."mst_urusan" ( tahun, kode_urusan, nama_urusan, daerah_khusus, jns_pemda, created_by, locked, disable ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8 ) ` _, err = c.pgxConn.Exec(ctx, q, payload.Tahun, payload.KodeUrusan, payload.NamaUrusan, payload.DaerahKhusus, payload.JenisPemda, createdBy, false, // locked default false false, // disable default false ) if err != nil { err = utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal menyimpan data urusan. - " + err.Error(), } return err } return nil } // Update urusan func (c *UrusanController) Update(ctx context.Context, id int, payload models.MstUrusanUpdatePayloadModel, updatedBy int) error { // Check if data exists var exists bool q := ` SELECT EXISTS ( SELECT 1 FROM "master_data"."mst_urusan" WHERE id_urusan = $1 AND deleted_by = 0 AND deleted_at = '0001-01-01 00:00:00' ) ` err := c.pgxConn.QueryRow(ctx, q, id).Scan(&exists) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal memeriksa keberadaan data urusan. - " + err.Error(), } } if !exists { return utils.RequestError{ Code: http.StatusNotFound, Message: "Data urusan tidak ditemukan", } } // Update hanya kolom nama_urusan, daerah_khusus, jns_pemda q = ` UPDATE "master_data"."mst_urusan" SET nama_urusan = $1, daerah_khusus = $2, jns_pemda = $3, updated_by = $4, updated_at = NOW() WHERE id_urusan = $5 ` _, err = c.pgxConn.Exec(ctx, q, payload.NamaUrusan, payload.DaerahKhusus, payload.JenisPemda, updatedBy, id, ) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengupdate data urusan. - " + err.Error(), } } return nil } // Delete urusan func (c *UrusanController) Delete(ctx context.Context, id int, deletedBy int) error { // Check if data exists and not already deleted var exists bool q := ` SELECT EXISTS ( SELECT 1 FROM "master_data"."mst_urusan" WHERE id_urusan = $1 AND deleted_by = 0 AND deleted_at = '0001-01-01 00:00:00' ) ` err := c.pgxConn.QueryRow(ctx, q, id).Scan(&exists) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal memeriksa keberadaan data urusan. - " + err.Error(), } } if !exists { return utils.RequestError{ Code: http.StatusNotFound, Message: "Data urusan tidak ditemukan atau sudah dihapus", } } // Perform soft delete q = ` UPDATE "master_data"."mst_urusan" SET deleted_by = $1, deleted_at = NOW() WHERE id_urusan = $2 ` _, err = c.pgxConn.Exec(ctx, q, deletedBy, id) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal menghapus data urusan. - " + err.Error(), } } return nil } // UpdateLocked updates the locked status of urusan func (c *UrusanController) UpdateLocked(ctx context.Context, id int, locked bool, updatedBy int) error { // Check if data exists and not deleted var exists bool q := ` SELECT EXISTS ( SELECT 1 FROM "master_data"."mst_urusan" WHERE id_urusan = $1 AND deleted_by = 0 AND deleted_at = '0001-01-01 00:00:00' ) ` err := c.pgxConn.QueryRow(ctx, q, id).Scan(&exists) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal memeriksa keberadaan data urusan. - " + err.Error(), } } if !exists { return utils.RequestError{ Code: http.StatusNotFound, Message: "Data urusan tidak ditemukan", } } // Update locked status q = ` UPDATE "master_data"."mst_urusan" SET locked = $1, updated_by = $2, updated_at = NOW() WHERE id_urusan = $3 ` _, err = c.pgxConn.Exec(ctx, q, locked, updatedBy, id) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengupdate status locked urusan. - " + err.Error(), } } return nil } // UpdateDisable updates the disable status of urusan func (c *UrusanController) UpdateDisable(ctx context.Context, id int, disable bool, updatedBy int) error { // Check if data exists and not deleted var exists bool q := ` SELECT EXISTS ( SELECT 1 FROM "master_data"."mst_urusan" WHERE id_urusan = $1 AND deleted_by = 0 AND deleted_at = '0001-01-01 00:00:00' ) ` err := c.pgxConn.QueryRow(ctx, q, id).Scan(&exists) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal memeriksa keberadaan data urusan. - " + err.Error(), } } if !exists { return utils.RequestError{ Code: http.StatusNotFound, Message: "Data urusan tidak ditemukan", } } // Update disable status q = ` UPDATE "master_data"."mst_urusan" SET disable = $1, updated_by = $2, updated_at = NOW() WHERE id_urusan = $3 ` _, err = c.pgxConn.Exec(ctx, q, disable, updatedBy, id) if err != nil { return utils.RequestError{ Code: http.StatusInternalServerError, Message: "gagal mengupdate status disable urusan. - " + err.Error(), } } return nil } // Create new daerah // func (c *DaerahController) Create(payloadl models.RefDaerahModelPayload) error { // var err error // var kodeUnik string // kodeUnik = uuid.New().String() // // mulai validasi duplikat unique key // var exists bool // q := ` // SELECT EXISTS ( // SELECT 1 // FROM "master_data"."mst_daerah" // WHERE kode_ddn = $1 // AND nama_daerah = $2 // ) // ` // err = c.pgxConn.QueryRow( // context.Background(), // q, // payloadl.KodeDdn, // payloadl.NamaDaerah, // ).Scan(&exists) // if err != nil { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal memeriksa duplikasi unique key. - " + err.Error(), // } // return err // } // if exists { // err = utils.RequestError{ // Code: http.StatusBadRequest, // Message: "Data sudah ada", // } // return err // } // // selesai validasi duplikat unique key // q = ` // INSERT INTO "master_data"."mst_daerah" ( // id_prov, // daerah_khusus, // jns_pemda, // zona_waktu, // zona_wilayah, // kode_unik, // kode_ddn, // nama_daerah, // nama_ibu_kota, // logo_daerah // ) VALUES ( // $1, -- id // $2, -- id_prov // $3, -- daerah_khusus // $4, -- jns_pemda // $5, -- zona_waktu // $6, -- zona_wilayah // $7, -- kode_unik // $8, -- kode_ddn // $9, -- nama_daerah // $10 -- nama_ibu_kota // ) // ` // _, err = c.pgxConn.Exec( // context.Background(), // q, // &payloadl.IDProv, // &payloadl.DaerahKhusus, // &payloadl.JnsPemda, // &payloadl.ZonaWaktu, // &payloadl.ZonaWilayah, // &kodeUnik, // &payloadl.KodeDdn, // &payloadl.NamaDaerah, // &payloadl.NamaIbuKota, // &payloadl.LogoDaerah, // ) // if err != nil { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal menyimpan data daerah. - " + err.Error(), // } // return err // } // return err // } // // Update daerah // func (c *DaerahController) Update(id int, payloadl models.RefDaerahModelPayload) error { // var err error // var q string // // pastikan data dengan id tersebut ada, dengan cara mengambil datanya. // var idDaerah int // var kodeDdn, namaDaerah string // q = `SELECT id, kode_ddn, nama_daerah FROM "master_data"."mst_daerah" WHERE id_daerah=$1` // err = c.pgxConn.QueryRow(context.Background(), q, id).Scan(&idDaerah, &kodeDdn, &namaDaerah) // if err != nil { // { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal mengambil data daerah. - " + err.Error(), // } // return err // } // } // if kodeDdn != payloadl.KodeDdn && namaDaerah != payloadl.NamaDaerah { // // mulai validasi duplikat unique key // var exists bool // q = ` // SELECT EXISTS ( // SELECT 1 // FROM "master_data"."mst_daerah" // WHERE kode_ddn = $1 // AND nama_daerah = $2 // ) // ` // err = c.pgxConn.QueryRow( // context.Background(), // q, // payloadl.KodeDdn, // payloadl.NamaDaerah, // ).Scan(&exists) // if err != nil { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal memeriksa duplikasi unique key. - " + err.Error(), // } // return err // } // if exists { // err = utils.RequestError{ // Code: http.StatusBadRequest, // Message: "Data sudah ada", // } // return err // } // // selesai validasi duplikat unique key // } // q = ` // UPDATE "master_data"."mst_daerah" // SET // id_prov = $1, // daerah_khusus = $2, // jns_pemda = $3, // zona_waktu = $4, // zona_wilayah = $5, // nama_daerah = $6, // nama_ibu_kota = $7, // logo_daerah = $8, // updated_at = NOW() // WHERE id = $9 // ` // _, err = c.pgxConn.Exec( // context.Background(), // q, // payloadl.IDProv, // payloadl.DaerahKhusus, // payloadl.JnsPemda, // payloadl.ZonaWaktu, // payloadl.ZonaWilayah, // payloadl.NamaDaerah, // payloadl.NamaIbuKota, // payloadl.LogoDaerah, // id, // kondisi WHERE // ) // if err != nil { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal mengupdate data daerah. - " + err.Error(), // } // return err // } // return err // } // func (c *DaerahController) Delete(id int) error { // var err error // var idDaerah, deletedBy int // var deletedAt time.Time // q := `SELECT id, deleted_by, deleted_at FROM "master_data"."mst_daerah" WHERE id_daerah=$1` // err = c.pgxConn.QueryRow(context.Background(), q, id).Scan(&idDaerah, &deletedBy, &deletedAt) // if err != nil { // { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal mengambil data daerah. - " + err.Error(), // } // return err // } // } // if deletedBy != 0 { // err = utils.RequestError{ // Code: http.StatusBadRequest, // Message: "data sudah dihapus", // } // return err // } // q = ` // UPDATE "master_data"."mst_daerah" // SET // deleted_by = $1, // deleted_at = NOW() // WHERE id = $2 // ` // _, err = c.pgxConn.Exec( // context.Background(), // q, // id, // id, // ) // if err != nil { // err = utils.RequestError{ // Code: http.StatusInternalServerError, // Message: "gagal menghapus data daerah. - " + err.Error(), // } // return err // } // return err // }