sipd-master/controllers/urusan_controller.go
2025-09-16 08:26:35 +07:00

691 lines
17 KiB
Go

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
// }