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

432 lines
10 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/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
type DaerahController struct {
contextTimeout time.Duration
pgxConn *pgxpool.Pool
}
func NewDaerahController(conn *pgxpool.Pool, timeout time.Duration) (controller *DaerahController) {
controller = &DaerahController{
pgxConn: conn,
contextTimeout: timeout,
}
return
}
func getDaerahDetailFields() []string {
var field []string
v := reflect.ValueOf(models.MstDaerahModel{})
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 daerah
func (c *DaerahController) Index(
page, limit int,
filter string,
) (
resp []models.MstDaerahModel,
totalCount int,
pageCount int,
err error,
) {
var q string
resp = make([]models.MstDaerahModel, 0)
pageCount = 1
offset := limit * (page - 1)
var filterCond string
if filter != "" {
var filterMap map[string]string
filterMap, err = utils.ValidateAndReturnFilterMap(filter, getDaerahDetailFields())
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_daerah":
filterCond = fmt.Sprintf(" AND dd.%s ILIKE '%s%s%s' ", key, "%", val, "%")
case "kode_ddn", "jns_pemda":
filterCond = fmt.Sprintf(" AND dd.%s = '%s' ", key, val)
default:
filterCond = ""
}
}
// total data
q = `SELECT COALESCE(COUNT(dd.id_daerah), 0)
FROM "master_data"."mst_daerah" AS dd
WHERE dd.deleted_by = 0 AND dd.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 dd.id_daerah, dd.kode_ddn, dd.nama_daerah, dd.nama_ibu_kota, dd.daerah_khusus, dd.jns_pemda, dd.logo_daerah
FROM "master_data"."mst_daerah" AS dd
WHERE dd.deleted_by = 0 AND dd.deleted_at='0001-01-01 00:00:00' `
q += filterCond
q += ` 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.MstDaerahModel
err = rows.Scan(
&m.ID,
&m.KodeDaerah,
&m.NamaDaerah,
&m.NamaIbuKota,
&m.DaerahKhusus,
&m.JnsPemda,
&m.LogoDaerah,
)
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 daerah
func (c *DaerahController) View(id int) (resp models.MstDaerahDetilModel, err error) {
// log.Println("id: ", id)
q := `SELECT dd.id_daerah, pv.id_daerah as id_provinsi, pv.kode_ddn as kode_provinsi, pv.nama_daerah as nama_provinsi
, dd.kode_ddn, dd.nama_daerah, dd.nama_ibu_kota, dd.daerah_khusus, dd.jns_pemda,
CASE WHEN dd.jns_pemda=1 THEN 'Provinsi' WHEN dd.jns_pemda=2 THEN 'Kabupaten' WHEN dd.jns_pemda=3 THEN 'Kota' ELSE '-' END AS jenis_pemda_alias
, dd.zona_waktu, dd.zona_wilayah, dd.logo_daerah
, dd.created_at, dd.created_by, dd.updated_at, dd.updated_by, dd.deleted_at, dd.deleted_by
FROM "master_data"."mst_daerah" AS dd
LEFT JOIN "master_data"."mst_daerah" AS pv ON pv.id_daerah=dd.id_prov
WHERE dd.id_daerah=$1`
err = c.pgxConn.QueryRow(context.Background(), q, id).Scan(
&resp.ID,
&resp.IDProv,
&resp.KodeProv,
&resp.NamaProv,
&resp.KodeDaerah,
&resp.NamaDaerah,
&resp.NamaIbuKota,
&resp.DaerahKhusus,
&resp.JnsPemda,
&resp.JnsPemdaAlias,
&resp.ZonaWaktu,
&resp.ZonaWilayah,
&resp.LogoDaerah,
&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 new daerah
func (c *DaerahController) Create(payload models.MstDaerahPayloadModel) error {
var err error
var kodeUnik string
kodeUnik = uuid.New().String()
// mulai validasi duplikat unique key
var exists bool
q := `SELECT EXISTS (
SELECT dd.id_daerah
FROM "master_data"."mst_daerah" AS dd
WHERE dd.kode_ddn = $1 OR dd.nama_daerah = $2
)`
err = c.pgxConn.QueryRow(
context.Background(),
q,
payload.KodeDaerah,
payload.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,
kode_unik,
kode_ddn,
nama_daerah,
nama_ibu_kota,
daerah_khusus,
jns_pemda,
zona_waktu,
zona_wilayah,
logo_daerah
) VALUES (
$1, -- id_prov
$2, -- kode_unik
$3, -- kode_ddn
$4, -- nama_daerah
$5, -- nama_ibu_kota
$6, -- daerah_khusus
$7, -- jns_pemda
$8, -- zona_waktu
$9, -- zona_wilayah
$10 -- logo_daerah
)
`
_, err = c.pgxConn.Exec(
context.Background(),
q,
&payload.IDProv,
&kodeUnik,
&payload.KodeDaerah,
&payload.NamaDaerah,
&payload.NamaIbuKota,
&payload.DaerahKhusus,
&payload.JnsPemda,
&payload.ZonaWaktu,
&payload.ZonaWilayah,
&payload.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, payload models.MstDaerahPayloadModel) error {
var err error
var q string
// pastikan data dengan id tersebut ada, dengan cara mengambil datanya.
var idDaerah int
var kodeDaerah, namaDaerah string
q = `SELECT dd.id_daerah, dd.kode_ddn, dd.nama_daerah FROM "master_data"."mst_daerah" AS dd WHERE dd.id_daerah=$1`
err = c.pgxConn.QueryRow(context.Background(), q, id).Scan(&idDaerah, &kodeDaerah, &namaDaerah)
if err != nil {
{
err = utils.RequestError{
Code: http.StatusInternalServerError,
Message: "gagal mengambil data daerah. - " + err.Error(),
}
return err
}
}
if kodeDaerah != payload.KodeDaerah && namaDaerah != payload.NamaDaerah {
// mulai validasi duplikat unique key
var exists bool
q = `SELECT EXISTS (
SELECT dd.id_daerah
FROM "master_data"."mst_daerah" AS dd
WHERE dd.kode_ddn = $1 OR dd.nama_daerah = $2
)`
err = c.pgxConn.QueryRow(
context.Background(),
q,
payload.KodeDaerah,
payload.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,
kode_ddn = $2,
nama_daerah = $3,
nama_ibu_kota = $4,
daerah_khusus = $5,
jenis_pemda = $6,
zona_waktu = $7,
zona_wilayah = $8,
logo_daerah = $9,
updated_at = NOW()
WHERE id_daerah = $10
`
_, err = c.pgxConn.Exec(
context.Background(),
q,
payload.IDProv,
payload.KodeDaerah,
payload.NamaDaerah,
payload.NamaIbuKota,
payload.DaerahKhusus,
payload.JnsPemda,
payload.ZonaWaktu,
payload.ZonaWilayah,
payload.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_daerah, 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
}