first commit

This commit is contained in:
ogi 2025-09-16 08:47:22 +07:00
commit 35e0199a9a
23 changed files with 2106 additions and 0 deletions

5
.dockerignore Normal file
View File

@ -0,0 +1,5 @@
README.md
.git
.idea
Makefile
Makefile.example

17
.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
# macOS
**/.DS_Store
# Jetbrains
.idea/
# Run script
Makefile
Makefile.localhost
Makefile.prod
# Dev build
build/
tmp/
# Test
*.out

54
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,54 @@
stages:
- test
- build
- deploy
variables:
DOCKER_CONFIG_FILE: "--config .docker"
DOCKER_REGCRED: "regcred"
PROJECT_NAME: "sipd-transaksi-pendapatan" #untuk dirubah
PROJECT_GROUP_ID: "sipd"
K8S_NAMESPACE: "development"
MY_TRIGGER_TOKEN: "glptt-eb34428616c382d3240f1ae6a979e453504addee"
# default:
# tags:
# - docker
build:image:
stage: build
image: nexus.registry:8086/docker:stable
services:
- name: nexus.registry:8086/docker:18.09-dind
entrypoint: ["dockerd-entrypoint.sh"]
command: [
"--insecure-registry=nexus.registry:8087",
"--insecure-registry=nexus.registry:8086"
]
alias: dockerd
variables:
DOCKER_HOST: tcp://dockerd:2375
DOCKER_DRIVER: overlay2
DOCKER_TAGS:
nexus.registry:8087/$PROJECT_GROUP_ID/$PROJECT_NAME
before_script:
- mkdir -p .docker/ && cat $DOCKER_CONF_JSON > .docker/config.json
script:
- echo $CI_COMMIT_SHORT_SHA
- docker $DOCKER_CONFIG_FILE build -q -f Dockerfile -t $DOCKER_TAGS:latest .
- docker image tag $DOCKER_TAGS:latest $DOCKER_TAGS:$CI_COMMIT_SHORT_SHA
- docker $DOCKER_CONFIG_FILE image push $DOCKER_TAGS:latest
- docker $DOCKER_CONFIG_FILE image push $DOCKER_TAGS:$CI_COMMIT_SHORT_SHA
rules:
- if: '$CI_COMMIT_BRANCH == "mains"'
#deploy:
# stage: deploy
# script:
# - echo $CI_SERVER_URL
# - apk add curl
# - 'curl -X POST --fail -F "token=$MY_TRIGGER_TOKEN" -F "ref=main" -F "variables[PROJECT_GROUP_ID]=$PROJECT_GROUP_ID" -F "variables[SERVICE_NAME]=$PROJECT_NAME" "$CI_SERVER_URL/api/v4/projects/3/trigger/pipeline"'
# - echo "deploy success"
# rules:
# - if: '$CI_COMMIT_BRANCH == "main"'

13
Dockerfile Normal file
View File

@ -0,0 +1,13 @@
FROM golang:1.23.12-alpine
RUN apk update && apk add --no-cache git
WORKDIR /app
COPY . .
RUN go mod tidy
RUN go build -o binary -tags musl
ENTRYPOINT ["/app/binary"]

51
Makefile.example Normal file
View File

@ -0,0 +1,51 @@
.PHONY: clean critic security lint test swag run stop
BUILD_DIR = $(PWD)/build
IMAGE_NAME = "SIPDTransaksiPendapatanService"
# App Env
SERVER_NAME="SIPDTransaksiPendapatanService"
SERVER_URL="0.0.0.0:3100"
SERVER_READ_TIMEOUT=60
JWT_SECRET_KEY="jwt_secret"
SIPD_CORS_WHITELISTS="*"
DB_CONN="host=localhost port=5432 user=xxxx password=xxxx dbname=master_sipd sslmode=disable application_name=SIPDTransaksiPendapatanService"
URL_SCHEME="http://"
BASE_URL="http://localhost:3100"
BASE_PATH="/"
go:
export SERVER_NAME=$(SERVER_NAME);\
export SERVER_URL=$(SERVER_URL);\
export SERVER_READ_TIMEOUT=$(SERVER_READ_TIMEOUT);\
export JWT_SECRET_KEY=$(JWT_SECRET_KEY);\
export SIPD_CORS_WHITELISTS=$(SIPD_CORS_WHITELISTS);\
export DB_CONN=$(DB_CONN);\
export URL_SCHEME=$(URL_SCHEME);\
export BASE_URL=$(BASE_URL);\
export BASE_PATH=$(BASE_PATH);\
go mod tidy;\
go run main.go
docker_build_image:
docker build -t $(IMAGE_NAME):latest .
docker_run: docker_build_image
docker run -d \
--restart unless-stopped \
--name $(IMAGE_NAME)_container \
--network host \
-e SERVER_NAME=$(SERVER_NAME) \
-e SERVER_URL=$(SERVER_URL) \
-e SERVER_READ_TIMEOUT=$(SERVER_READ_TIMEOUT) \
-e JWT_SECRET_KEY=$(JWT_SECRET_KEY) \
-e DB_CONN=$(DB_CONN) \
-e URL_SCHEME=$(URL_SCHEME) \
-e BASE_URL=$(BASE_URL) \
-e BASE_PATH=$(BASE_PATH) \
$(IMAGE_NAME):latest
docker_stop:
docker container stop $(IMAGE_NAME)_container
docker container rm $(IMAGE_NAME)_container
docker rmi $(IMAGE_NAME):latest

View File

@ -0,0 +1,31 @@
package controllers
import (
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
type WelcomeController struct {
contextTimeout time.Duration
pgxConn *pgxpool.Pool
}
func NewWelcomeController(conn *pgxpool.Pool, timeout time.Duration) (controller *WelcomeController) {
controller = &WelcomeController{
pgxConn: conn,
contextTimeout: timeout,
}
return
}
// Index welcome
func (c *WelcomeController) Index() (
resp string,
err error,
) {
resp = "Hello SIPD Transaksi Pendapatan"
return resp, err
}

174
docs/docs.go Normal file
View File

@ -0,0 +1,174 @@
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs
import "github.com/swaggo/swag"
const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{escape .Description}}",
"title": "{{.Title}}",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "API Support",
"email": "lifelinejar@mail.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/welcome": {
"get": {
"description": "get welcome",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Welcome"
],
"summary": "get welcome",
"parameters": [
{
"type": "integer",
"description": "Halaman yang ditampilkan",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "Jumlah data per halaman, maksimal 50 data",
"name": "limit",
"in": "query"
},
{
"type": "string",
"description": "Key value pencarian ([kode_ddn,nama_daerah,jns_pemda]). Contoh: kode_ddn.11 -\u003e (akan menampilkan data dengan kode ddn = '11')",
"name": "filter",
"in": "query"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/models.WelcomeModel"
}
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
},
"404": {
"description": "Not found",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
},
"422": {
"description": "Data validation failed",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/utils.RequestError"
}
}
},
"500": {
"description": "Server error",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
}
}
}
}
},
"definitions": {
"models.WelcomeModel": {
"type": "object",
"properties": {
"id_daerah": {
"type": "integer",
"example": 1
}
}
},
"utils.DataValidationError": {
"type": "object",
"properties": {
"field": {
"type": "string",
"example": "email"
},
"message": {
"type": "string",
"example": "Invalid email address"
}
}
},
"utils.RequestError": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"example": 422
},
"fields": {
"type": "array",
"items": {
"$ref": "#/definitions/utils.DataValidationError"
}
},
"message": {
"type": "string",
"example": "Invalid email address"
}
}
}
},
"securityDefinitions": {
"ApiKeyAuth": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
}
}`
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "1.0",
Host: "",
BasePath: "",
Schemes: []string{},
Title: "SIPD Service Transaksi Pendapatan",
Description: "SIPD Service Transaksi Pendapatan Rest API.",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}
func init() {
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}

148
docs/swagger.json Normal file
View File

@ -0,0 +1,148 @@
{
"swagger": "2.0",
"info": {
"description": "SIPD Service Transaksi Pendapatan Rest API.",
"title": "SIPD Service Transaksi Pendapatan",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "API Support",
"email": "lifelinejar@mail.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0"
},
"paths": {
"/welcome": {
"get": {
"description": "get welcome",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Welcome"
],
"summary": "get welcome",
"parameters": [
{
"type": "integer",
"description": "Halaman yang ditampilkan",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "Jumlah data per halaman, maksimal 50 data",
"name": "limit",
"in": "query"
},
{
"type": "string",
"description": "Key value pencarian ([kode_ddn,nama_daerah,jns_pemda]). Contoh: kode_ddn.11 -\u003e (akan menampilkan data dengan kode ddn = '11')",
"name": "filter",
"in": "query"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/models.WelcomeModel"
}
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
},
"404": {
"description": "Not found",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
},
"422": {
"description": "Data validation failed",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/utils.RequestError"
}
}
},
"500": {
"description": "Server error",
"schema": {
"$ref": "#/definitions/utils.RequestError"
}
}
}
}
}
},
"definitions": {
"models.WelcomeModel": {
"type": "object",
"properties": {
"id_daerah": {
"type": "integer",
"example": 1
}
}
},
"utils.DataValidationError": {
"type": "object",
"properties": {
"field": {
"type": "string",
"example": "email"
},
"message": {
"type": "string",
"example": "Invalid email address"
}
}
},
"utils.RequestError": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"example": 422
},
"fields": {
"type": "array",
"items": {
"$ref": "#/definitions/utils.DataValidationError"
}
},
"message": {
"type": "string",
"example": "Invalid email address"
}
}
}
},
"securityDefinitions": {
"ApiKeyAuth": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
}
}

100
docs/swagger.yaml Normal file
View File

@ -0,0 +1,100 @@
definitions:
models.WelcomeModel:
properties:
id_daerah:
example: 1
type: integer
type: object
utils.DataValidationError:
properties:
field:
example: email
type: string
message:
example: Invalid email address
type: string
type: object
utils.RequestError:
properties:
code:
example: 422
type: integer
fields:
items:
$ref: '#/definitions/utils.DataValidationError'
type: array
message:
example: Invalid email address
type: string
type: object
info:
contact:
email: lifelinejar@mail.com
name: API Support
description: SIPD Service Transaksi Pendapatan Rest API.
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
termsOfService: http://swagger.io/terms/
title: SIPD Service Transaksi Pendapatan
version: "1.0"
paths:
/welcome:
get:
consumes:
- application/json
description: get welcome
parameters:
- description: Halaman yang ditampilkan
in: query
name: page
type: integer
- description: Jumlah data per halaman, maksimal 50 data
in: query
name: limit
type: integer
- description: 'Key value pencarian ([kode_ddn,nama_daerah,jns_pemda]). Contoh:
kode_ddn.11 -> (akan menampilkan data dengan kode ddn = ''11'')'
in: query
name: filter
type: string
produces:
- application/json
responses:
"200":
description: Success
schema:
items:
$ref: '#/definitions/models.WelcomeModel'
type: array
"400":
description: Bad request
schema:
$ref: '#/definitions/utils.RequestError'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/utils.RequestError'
"404":
description: Not found
schema:
$ref: '#/definitions/utils.RequestError'
"422":
description: Data validation failed
schema:
items:
$ref: '#/definitions/utils.RequestError'
type: array
"500":
description: Server error
schema:
$ref: '#/definitions/utils.RequestError'
summary: get welcome
tags:
- Welcome
securityDefinitions:
ApiKeyAuth:
in: header
name: Authorization
type: apiKey
swagger: "2.0"

60
go.mod Normal file
View File

@ -0,0 +1,60 @@
module kemendagri/sipd/services/transaksi-pendapatan-sipd
go 1.23.0
toolchain go1.23.12
require (
github.com/arsmn/fiber-swagger/v2 v2.31.1
github.com/go-playground/validator/v10 v10.27.0
github.com/gofiber/fiber/v2 v2.52.9
github.com/gofiber/jwt/v3 v3.3.10
github.com/golang-migrate/migrate/v4 v4.18.3
github.com/jackc/pgx/v5 v5.7.5
github.com/lib/pq v1.10.9
github.com/swaggo/swag v1.16.6
)
require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 // indirect
github.com/tinylib/msgp v1.2.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/tools v0.24.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

289
go.sum Normal file
View File

@ -0,0 +1,289 @@
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/arsmn/fiber-swagger/v2 v2.31.1 h1:VmX+flXiGGNqLX3loMEEzL3BMOZFSPwBEWR04GA6Mco=
github.com/arsmn/fiber-swagger/v2 v2.31.1/go.mod h1:ZHhMprtB3M6jd2mleG03lPGhHH0lk9u3PtfWS1cBhMA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dhui/dktest v0.4.5 h1:uUfYBIVREmj/Rw6MvgmqNAYzTiKOHJak+enB5Di73MM=
github.com/dhui/dktest v0.4.5/go.mod h1:tmcyeHDKagvlDrz7gDKq4UAJOLIfVZYkfD5OnHDwcCo=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4=
github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/gofiber/fiber/v2 v2.31.0/go.mod h1:1Ega6O199a3Y7yDGuM9FyXDPYQfv+7/y48wl6WCwUF4=
github.com/gofiber/fiber/v2 v2.45.0/go.mod h1:DNl0/c37WLe0g92U6lx1VMQuxGUQY5V7EIaVoEsUffc=
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/jwt/v3 v3.3.10 h1:0bpWtFKaGepjwYTU4efHfy0o+matSqZwTxGMo5a+uuc=
github.com/gofiber/jwt/v3 v3.3.10/go.mod h1:GJorFVaDyfMPSK9RB8RG4NQ3s1oXKTmYaoL/ny08O1A=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -0,0 +1,82 @@
package configs
import (
"errors"
"fmt"
"kemendagri/sipd/services/transaksi-pendapatan-sipd/utils"
"os"
"strconv"
"time"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
)
// FiberConfig func for configuration Fiber app.
// See: https://docs.gofiber.io/api/fiber#config
func FiberConfig() fiber.Config {
// Define server settings.
readTimeoutSecondsCount, _ := strconv.Atoi(os.Getenv("SERVER_READ_TIMEOUT"))
// Return Fiber configuration.
return fiber.Config{
AppName: os.Getenv("APP_NAME"),
ReadTimeout: time.Second * time.Duration(readTimeoutSecondsCount),
//Prefork: true,
//CaseSensitive: true,
//StrictRouting: true,
ServerHeader: os.Getenv("SERVER_NAME"),
ErrorHandler: fiberErrorHandler,
}
}
func fiberErrorHandler(ctx *fiber.Ctx, err error) error {
var re utils.RequestError
var vlde validator.ValidationErrors
switch {
case errors.As(err, &re):
_ = ctx.Status(re.Code).JSON(re)
case errors.As(err, &vlde):
var eReq = new(utils.RequestError)
eReq.Code = fiber.StatusInternalServerError
for _, err := range vlde {
errObj := utils.DataValidationError{Field: err.Field()}
// penyesuaian pesan error berdasarkan jenis validasinya
switch err.Tag() {
case "gte":
errObj.Message = fmt.Sprintf("%s harus lebih besar atau sama dengan %s", err.Field(), err.Param())
case "gt":
errObj.Message = fmt.Sprintf("%s harus lebih besar dari %s", err.Field(), err.Param())
case "lt":
errObj.Message = fmt.Sprintf("%s harus lebih kecil dari %s", err.Field(), err.Param())
case "max":
errObj.Message = fmt.Sprintf("%s maksimal %s karakter", err.Field(), err.Param())
case "min":
errObj.Message = fmt.Sprintf("%s minimal %s karakter", err.Field(), err.Param())
case "oneof":
errObj.Message = fmt.Sprintf("%s harus salah satu dari: %s", err.Field(), err.Param())
case "url":
errObj.Message = fmt.Sprintf("%s harus format url", err.Field())
case "e164":
errObj.Message = "Invalid phone number format (E.164)"
case "alphanumspace":
errObj.Message = "Only alphanumeric and space allowed"
case "alphanumslashasterisk":
errObj.Message = "Only alphanumeric, slash and asterisk allowed"
default:
errObj.Message = err.Tag()
}
eReq.Fields = append(eReq.Fields, errObj)
}
_ = ctx.Status(fiber.StatusUnprocessableEntity).JSON(eReq)
default:
_ = ctx.Status(fiber.StatusInternalServerError).JSON(utils.GlobalError{Message: err.Error()})
}
// Return from handler
return nil
}

View File

@ -0,0 +1,15 @@
package http_util
type JSONResult struct {
Code int `json:"code" example:"404"`
Message string `json:"message" example:"Not Found"`
Data interface{} `json:"data"`
Meta interface{} `json:"meta"`
}
type JSONResultMeta struct {
TotalCount int `json:"total_count"`
PageCount int `json:"page_count"`
CurrentPage int `json:"current_page"`
PerPage int `json:"per_page"`
}

View File

@ -0,0 +1,44 @@
package http_util
import (
"log"
"os"
"os/signal"
"github.com/gofiber/fiber/v2"
)
// StartServerWithGracefulShutdown function for starting server with a graceful shutdown.
func StartServerWithGracefulShutdown(a *fiber.App) {
// Create channel for idle connections.
idleConnsClosed := make(chan struct{})
go func() {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt) // Catch OS signals.
<-sigint
// Received an interrupt signal, shutdown.
if err := a.Shutdown(); err != nil {
// Error from closing listeners, or context timeout:
log.Printf("Oops... Server is not shutting down! Reason: %v", err)
}
close(idleConnsClosed)
}()
// Run server.
if err := a.Listen(os.Getenv("SERVER_URL")); err != nil {
log.Printf("Oops... Server is not running! Reason: %v", err)
}
<-idleConnsClosed
}
// StartServer func for starting a simple server.
func StartServer(a *fiber.App) {
// Run server.
if err := a.Listen(os.Getenv("SERVER_URL")); err != nil {
log.Printf("Oops... Server is not running! Reason: %v", err)
}
}

View File

@ -0,0 +1,111 @@
package middleware
import (
"fmt"
"os"
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/limiter"
"github.com/gofiber/fiber/v2/middleware/logger"
jwtware "github.com/gofiber/jwt/v3"
)
// GoMiddleware represent the data-struct for middleware
type GoMiddleware struct {
appCtx *fiber.App
// another stuff , may be needed by middleware
}
// CORS will handle the CORS middleware
func (m *GoMiddleware) CORS() fiber.Handler {
crs := os.Getenv("SIPD_CORS_WHITELISTS")
if crs == "*" {
return cors.New(cors.Config{
AllowOrigins: "*",
AllowHeaders: "Content-Type, Accept, Authorization",
AllowMethods: "GET, HEAD, PUT, PATCH, POST, DELETE",
ExposeHeaders: "*", //"X-Pagination-Current-Page,X-Pagination-Next-Page,X-Pagination-Page-Count,X-Pagination-Page-Size,X-Pagination-Total-Count"
})
}
return cors.New(cors.Config{
AllowOrigins: crs,
AllowCredentials: true,
AllowHeaders: "Content-Type, Accept, Authorization",
AllowMethods: "GET, HEAD, PUT, PATCH, POST, DELETE",
ExposeHeaders: "*", //"X-Pagination-Current-Page,X-Pagination-Next-Page,X-Pagination-Page-Count,X-Pagination-Page-Size,X-Pagination-Total-Count"
})
}
// LOGGER simple logger.
func (m *GoMiddleware) LOGGER() fiber.Handler {
return logger.New()
}
// JWT jwt.
func (m *GoMiddleware) JWT() fiber.Handler {
// Create config for JWT authentication middleware.
config := jwtware.Config{
SigningKey: []byte(os.Getenv("JWT_SECRET_KEY")),
ContextKey: "jwt", // used in private routes
ErrorHandler: jwtError,
}
return jwtware.New(config)
}
func jwtError(c *fiber.Ctx, err error) error {
// Return status 400 and failed authentication error.
if err.Error() == "Missing or malformed JWT" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": true,
"msg": err.Error(),
})
}
// Return status 401 and failed authentication error.
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"error": true,
"msg": err.Error(),
})
}
func (m *GoMiddleware) RateLimiter() fiber.Handler {
limiterCfg := limiter.Config{
Max: 20,
Expiration: 30 * time.Second,
KeyGenerator: func(c *fiber.Ctx) string {
authKey := c.Get("Authorization")
if authKey == "" {
uniqueID := c.Cookies("sipd_penatausahaan_uk_")
if uniqueID == "" {
uniqueID = fmt.Sprintf("%d", time.Now().UnixNano())
c.Cookie(&fiber.Cookie{
Name: "sipd_penatausahaan_uk_",
Value: uniqueID,
Expires: time.Now().Add(24 * time.Hour),
HTTPOnly: true,
Secure: true,
})
}
return c.IP() + c.Get("User-Agent") + uniqueID
} else {
return authKey
}
},
LimitReached: func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusTooManyRequests)
},
}
return limiter.New(limiterCfg)
}
// InitMiddleware initialize the middleware
func InitMiddleware(ctx *fiber.App) *GoMiddleware {
return &GoMiddleware{appCtx: ctx}
}

View File

@ -0,0 +1,57 @@
package handler
import (
"kemendagri/sipd/services/transaksi-pendapatan-sipd/controllers"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
)
type WelcomeHandler struct {
Controller *controllers.WelcomeController
Validate *validator.Validate
}
func NewWelcomeHandler(app *fiber.App, vld *validator.Validate, controller *controllers.WelcomeController) {
handler := &WelcomeHandler{
Controller: controller,
Validate: vld,
}
// public route
rpub := app.Group("/welcome")
rpub.Get("/", handler.Index)
// rpub.Get("/:id", handler.View)
// rpub.Post("/", handler.Create)
// rpub.Put("/:id", handler.Update)
// rpub.Delete("/:id", handler.Delete)
}
// Index func for get welcome.
//
// @Summary get welcome
// @Description get welcome
// @Tags Welcome
// @Accept json
// @Param page query int false "Halaman yang ditampilkan"
// @Param limit query int false "Jumlah data per halaman, maksimal 50 data"
// @param filter query string false "Key value pencarian ([kode_ddn,nama_daerah,jns_pemda]). Contoh: kode_ddn.11 -> (akan menampilkan data dengan kode ddn = '11')"
// @Produce json
// @success 200 {array} models.WelcomeModel "Success"
// @Failure 400 {object} utils.RequestError "Bad request"
// @Failure 401 {object} utils.RequestError "Unauthorized"
// @Failure 404 {object} utils.RequestError "Not found"
// @Failure 422 {array} utils.RequestError "Data validation failed"
// @Failure 500 {object} utils.RequestError "Server error"
// @Router /welcome [get]
func (h *WelcomeHandler) Index(c *fiber.Ctx) error {
resp, err := h.Controller.Index()
if err != nil {
return err
}
return c.JSON(resp)
}

231
main.go Normal file
View File

@ -0,0 +1,231 @@
package main
import (
"context"
"database/sql"
"fmt"
"kemendagri/sipd/services/transaksi-pendapatan-sipd/controllers"
hdl "kemendagri/sipd/services/transaksi-pendapatan-sipd/handler"
"kemendagri/sipd/services/transaksi-pendapatan-sipd/handler/configs"
"kemendagri/sipd/services/transaksi-pendapatan-sipd/handler/http_util"
_deliveryMiddleware "kemendagri/sipd/services/transaksi-pendapatan-sipd/handler/middleware"
"kemendagri/sipd/services/transaksi-pendapatan-sipd/utils"
"log"
"os"
"strconv"
"strings"
"time"
swagDoc "kemendagri/sipd/services/transaksi-pendapatan-sipd/docs"
swagger "github.com/arsmn/fiber-swagger/v2"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database"
"github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/jackc/pgx/v5/pgxpool"
_ "github.com/lib/pq"
)
var db *sql.DB
var pgxConn *pgxpool.Pool
var driver database.Driver
var migration *migrate.Migrate
var vld *validator.Validate
var err error
var serverName, serverUrl, serverReadTimeout, alwOrg, dbConn, urlScheme, baseUrl, basePath string
func init() {
serverName = os.Getenv("SERVER_NAME")
if serverName == "" {
exitf("SERVER_NAME env is required")
}
serverUrl = os.Getenv("SERVER_URL")
if serverUrl == "" {
exitf("SERVER_URL env is required")
}
serverReadTimeout = os.Getenv("SERVER_READ_TIMEOUT")
if serverReadTimeout == "" {
exitf("SERVER_READ_TIMEOUT env is required")
}
alwOrg = os.Getenv("SIPD_CORS_WHITELISTS")
if alwOrg == "" {
exitf("SIPD_CORS_WHITELISTS config is required")
}
// Databse Env
dbConn = os.Getenv("DB_CONN")
if dbConn == "" {
exitf("DB_CONN config is required")
}
urlScheme = os.Getenv("URL_SCHEME")
if urlScheme == "" {
exitf("URL_SCHEME config is required")
}
baseUrl = os.Getenv("BASE_URL")
if baseUrl == "" {
exitf("BASE_URL config is required")
}
basePath = os.Getenv("BASE_PATH")
if basePath == "" {
exitf("BASE_PATH config is required")
}
}
func databaseMigration() {
db, err = sql.Open("postgres", dbConn) //sesuaikan saat migrasi
if err != nil {
exitf("Db open error: %v\n", err)
}
driver, err = postgres.WithInstance(db, &postgres.Config{})
if err != nil {
_ = db.Close()
exitf("Db postgres driven error: %v\n", err)
}
migration, err = migrate.NewWithDatabaseInstance("file://migrations", "postgres", driver)
if err != nil {
_ = db.Close()
exitf("Unable to initiate migration: %v\n", err)
}
err = migration.Up() // or m.Step(2) if you want to explicitly set the number of migrations to run
if err != nil {
log.Println(fmt.Sprintf("Migration error: %s", err.Error()))
}
err = db.Close()
if err != nil {
log.Println(fmt.Sprintf("Db close error: %s", err.Error()))
}
}
func dbConnection() {
var maxConnLifetime, maxConnIdleTime time.Duration
maxConnLifetime = 5 * time.Minute
maxConnIdleTime = 2 * time.Minute
var cfg *pgxpool.Config
cfg, err = pgxpool.ParseConfig(dbConn)
if err != nil {
exitf("Unable to create db pool config sipd_anggaran %v\n", err)
}
// cfg.MaxConns = 1000 // Maximum total connections in the pool
cfg.MaxConnLifetime = maxConnLifetime // Maximum lifetime of a connection
cfg.MaxConnIdleTime = maxConnIdleTime // Maximum time a connection can be idle
pgxConn, err = pgxpool.NewWithConfig(context.Background(), cfg)
if err != nil {
exitf("Unable to connect to database sipd_anggaran %v\n", err)
}
}
// @title SIPD Service Transaksi Pendapatan
// @version 1.0
// @description SIPD Service Transaksi Pendapatan Rest API.
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.email lifelinejar@mail.com
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
// @BasePath /
func main() {
// migrasi database
// databaseMigration()
// Pgx Pool Connection
dbConnection()
defer func() {
pgxConn.Close()
}()
// End Pgx Pool Connection
// Define a validator
vld = utils.NewValidator()
// Define Fiber config.
config := configs.FiberConfig()
app := fiber.New(config)
middL := _deliveryMiddleware.InitMiddleware(app)
//app.Use(middL.RateLimiter())
app.Use(middL.CORS())
app.Use(middL.LOGGER())
app.Use(func(c *fiber.Ctx) error { // Middleware to check for whitelisted domains
if alwOrg == "*" {
// Continue to the next middleware/handler
return c.Next()
}
// Use "X-Forwarded-Host" to simulate the Host header in Postman
origin := c.Get("Origin")
// log.Println("Origin: ", origin)
alwOrgArr := strings.Split(alwOrg, ",")
// log.Println("alwOrgArr: ", alwOrgArr)
var originMatch bool
for _, alo := range alwOrgArr {
if origin == alo {
originMatch = true
break
} else {
/*host := c.Hostname()
// log.Println("Host: ", host)
if "https://"+host == alo || "http://"+host == alo {
originMatch = true
break
}*/
}
}
if !originMatch {
log.Println("alwOrgArr: ", alwOrgArr)
log.Println("Origin: ", origin)
return c.Status(fiber.StatusForbidden).SendString("403 - MSTDT: origin not allowed")
}
// Continue to the next middleware/handler
return c.Next()
})
// Swagger handler
// app.Get("/swagger/*", swagger.HandlerDefault)
swagDoc.SwaggerInfo.Host = baseUrl
swagDoc.SwaggerInfo.BasePath = basePath
app.Get("/swagger/*", swagger.New(swagger.Config{
URL: urlScheme + baseUrl + basePath + "swagger/doc.json", // default search box
}))
serverReadTimeoutInt, err := strconv.Atoi(serverReadTimeout)
if err != nil {
exitf("Failed casting timeout context: ", err)
}
timeoutContext := time.Duration(serverReadTimeoutInt) * time.Second
// welcome router
welcomeController := controllers.NewWelcomeController(pgxConn, timeoutContext)
hdl.NewWelcomeHandler(app, vld, welcomeController)
// end welcome router
// kecamatan router
// kecamatanController := controllers.NewKecamatanController(pgxConn, timeoutContext)
// hdl.NewKecamatanHandler(app, vld, kecamatanController)
// end kecamatan router
http_util.StartServer(app)
}
func exitf(s string, args ...interface{}) {
errorf(s, args...)
os.Exit(1)
}
func errorf(s string, args ...interface{}) {
fmt.Fprintf(os.Stderr, s+"\n", args...)
}

View File

@ -0,0 +1 @@
CREATE EXTENSION IF NOT EXISTS dblink;

View File

@ -0,0 +1,537 @@
CREATE TABLE IF NOT EXISTS public.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT public.uuid_generate_v7() NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE public.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE public.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE public.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN public.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN public.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN public.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN public.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN public.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN public.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN public.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN public.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN public.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN public.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN public.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN public.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN public.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN public.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN public.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN public.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN public.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN public.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN public.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON public.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON public.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON public.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON public.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON public.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON public.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON public.trn_pendapatan USING btree (id_akun);
-- SCHEMA rancangan_murni;
CREATE TABLE IF NOT EXISTS rancangan_murni.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE rancangan_murni.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE rancangan_murni.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE rancangan_murni.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN rancangan_murni.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON rancangan_murni.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON rancangan_murni.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON rancangan_murni.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON rancangan_murni.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON rancangan_murni.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON rancangan_murni.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON rancangan_murni.trn_pendapatan USING btree (id_akun);
-- SCHEMA penetapan_murni
CREATE TABLE IF NOT EXISTS penetapan_murni.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE penetapan_murni.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE penetapan_murni.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE penetapan_murni.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN penetapan_murni.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON penetapan_murni.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON penetapan_murni.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON penetapan_murni.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON penetapan_murni.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON penetapan_murni.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON penetapan_murni.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON penetapan_murni.trn_pendapatan USING btree (id_akun);
-- SCHEMA rancangan_pergeseran;
CREATE TABLE IF NOT EXISTS rancangan_pergeseran.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE rancangan_pergeseran.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE rancangan_pergeseran.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE rancangan_pergeseran.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN rancangan_pergeseran.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON rancangan_pergeseran.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON rancangan_pergeseran.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON rancangan_pergeseran.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON rancangan_pergeseran.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON rancangan_pergeseran.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON rancangan_pergeseran.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON rancangan_pergeseran.trn_pendapatan USING btree (id_akun);
-- SCHEMA penetapan_peregseran
CREATE TABLE IF NOT EXISTS penetapan_pergeseran.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE penetapan_pergeseran.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE penetapan_pergeseran.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE penetapan_pergeseran.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN penetapan_pergeseran.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON penetapan_pergeseran.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON penetapan_pergeseran.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON penetapan_pergeseran.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON penetapan_pergeseran.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON penetapan_pergeseran.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON penetapan_pergeseran.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON penetapan_pergeseran.trn_pendapatan USING btree (id_akun);
-- SCHEMA rancangan_perubahan;
CREATE TABLE IF NOT EXISTS rancangan_perubahan.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE rancangan_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE rancangan_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE rancangan_perubahan.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN rancangan_perubahan.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON rancangan_perubahan.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON rancangan_perubahan.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON rancangan_perubahan.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON rancangan_perubahan.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON rancangan_perubahan.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON rancangan_perubahan.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON rancangan_perubahan.trn_pendapatan USING btree (id_akun);
-- SCHEMA penetapan_perubahan;
CREATE TABLE IF NOT EXISTS penetapan_perubahan.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE penetapan_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE penetapan_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE penetapan_perubahan.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN penetapan_perubahan.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON penetapan_perubahan.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON penetapan_perubahan.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON penetapan_perubahan.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON penetapan_perubahan.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON penetapan_perubahan.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON penetapan_perubahan.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON penetapan_perubahan.trn_pendapatan USING btree (id_akun);
-- SCHEMA rancangan_pergeseran_perubahan;
CREATE TABLE IF NOT EXISTS rancangan_pergeseran_perubahan.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE rancangan_pergeseran_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE rancangan_pergeseran_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE rancangan_pergeseran_perubahan.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN rancangan_pergeseran_perubahan.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON rancangan_pergeseran_perubahan.trn_pendapatan USING btree (id_akun);
-- SCHEMA penetapan_pergeseran_perubahan;
CREATE TABLE IF NOT EXISTS penetapan_pergeseran_perubahan.trn_pendapatan (
id_unik_pendapatan uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
tahun integer DEFAULT 0 NOT NULL,
id_daerah integer DEFAULT 0 NOT NULL,
id_unik_jadwal uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_unik_sub_skpd uuid DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,
id_akun integer DEFAULT 0 NOT NULL,
keterangan text DEFAULT ''::text NOT NULL,
total_harga numeric(17,2) DEFAULT 0,
keterangan_murni text DEFAULT ''::text NOT NULL,
total_harga_murni numeric(17,2) DEFAULT 0,
koefisien character varying(150) DEFAULT '1 TAHUN'::character varying,
volume numeric(17,2) DEFAULT 1,
satuan character varying(120) DEFAULT 'TAHUN'::character varying,
id_pendapatan_lama bigint DEFAULT 0 NOT NULL,
total_harga_lama double precision DEFAULT 0,
total_harga_murni_lama double precision DEFAULT 0,
created_at timestamp(6) without time zone DEFAULT now() NOT NULL,
created_by integer DEFAULT 0 NOT NULL,
updated_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
updated_by integer DEFAULT 0 NOT NULL,
deleted_at timestamp(6) without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL,
deleted_by integer DEFAULT 0 NOT NULL
);
ALTER TABLE penetapan_pergeseran_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_pkey PRIMARY KEY (id_unik_pendapatan, tahun, id_daerah);
ALTER TABLE penetapan_pergeseran_perubahan.trn_pendapatan ADD CONSTRAINT trn_pendapatan_unique_key UNIQUE (tahun, id_daerah, id_unik_jadwal, id_unik_skpd, id_unik_sub_skpd, id_akun, keterangan);
COMMENT ON TABLE penetapan_pergeseran_perubahan.trn_pendapatan IS 'Tabel untuk menyimpan informasi anggaran pendapatan pada perangkat daerah yang memiliki pendapatan';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_unik_pendapatan IS 'ID unik UUID sebagai ID primary key..';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_pendapatan_lama IS 'Primary key tabel d_pendapatan lama.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.tahun IS 'Tahun anggaran.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_daerah IS 'ID daerah terkait.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_unik_jadwal IS 'ID jadwal anggaran.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_unik_skpd IS 'ID SKPD induk.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_unik_sub_skpd IS 'ID SKPD.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.id_akun IS 'ID akun pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.keterangan IS 'keterangan spesifik pada anggaran pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.total_harga IS 'Total anggaran pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.koefisien IS 'Detail koefisien volume dan satuan.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.volume IS 'Volume total pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.satuan IS 'Satuan volume pendapatan.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.created_at IS 'Tanggal dan waktu data dibuat.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.created_by IS 'ID pengguna yang membuat data.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.updated_at IS 'Tanggal dan waktu terakhir data diperbarui.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.updated_by IS 'ID pengguna yang memperbarui data.';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.deleted_at IS 'Tanggal dan waktu data dihapus (soft delete).';
COMMENT ON COLUMN penetapan_pergeseran_perubahan.trn_pendapatan.deleted_by IS 'ID pengguna yang menghapus data.';
CREATE INDEX trn_pendapatan_id_unik_pendapatan_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_pendapatan);
CREATE INDEX trn_pendapatan_tahun_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (tahun);
CREATE INDEX trn_pendapatan_id_daerah_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (id_daerah);
CREATE INDEX trn_pendapatan_id_unik_jadwal_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_jadwal);
CREATE INDEX trn_pendapatan_id_unik_skpd_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_skpd);
CREATE INDEX trn_pendapatan_id_unik_sub_skpd_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (id_unik_sub_skpd);
CREATE INDEX trn_pendapatan_id_akun_idx ON penetapan_pergeseran_perubahan.trn_pendapatan USING btree (id_akun);

5
models/welcome_model.go Normal file
View File

@ -0,0 +1,5 @@
package models
type WelcomeModel struct {
ID int `json:"id_daerah" example:"1"`
}

20
utils/app_errors.go Normal file
View File

@ -0,0 +1,20 @@
package utils
type RequestError struct {
Code int `json:"code" xml:"code" example:"422"`
Message string `json:"message" xml:"message" example:"Invalid email address"`
Fields []DataValidationError `json:"fields" xml:"fields"`
}
func (re RequestError) Error() string {
return re.Message
}
type DataValidationError struct {
Field string `json:"field" xml:"field" example:"email"`
Message string `json:"message" xml:"message" example:"Invalid email address"`
}
type GlobalError struct {
Message string `json:"message" xml:"message" example:"invalid name"`
}

27
utils/strUtility.go Normal file
View File

@ -0,0 +1,27 @@
package utils
import (
"errors"
"strings"
)
func ValidateAndReturnFilterMap(filter string, fields []string) (map[string]string, error) {
splits := strings.Split(filter, ".")
if len(splits) != 2 {
return nil, errors.New("malformed sortBy query parameter, should be field.orderdirection")
}
field, value := splits[0], splits[1]
if !StringInSlice(fields, field) {
return nil, errors.New("unknown field in filter query parameter")
}
return map[string]string{field: value}, nil
}
func StringInSlice(strSlice []string, s string) bool {
for _, v := range strSlice {
if v == s {
return true
}
}
return false
}

34
utils/validator.go Normal file
View File

@ -0,0 +1,34 @@
package utils
import (
"github.com/go-playground/validator/v10"
"reflect"
"strings"
)
// NewValidator func for create a new validator for model fields.
func NewValidator() *validator.Validate {
// Create a new validator for a Book model.
validate := validator.New()
// RegisterTagNameFunc registers a function to get alternate names for StructFields.
// eg. Title become title, CreatedAt become created_at
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// Custom validation for uuid.UUID fields.
/*_ = validate.RegisterValidation("uuid", func(fl validator.FieldLevel) bool {
field := fl.Field().String()
if _, err := uuid.Parse(field); err != nil {
return true
}
return false
})*/
return validate
}