This commit is contained in:
parent
10575b2512
commit
5669b376b2
48
internal/handlers/dto/postal_code.go
Normal file
48
internal/handlers/dto/postal_code.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
type CreatePostalCodeRequest struct {
|
||||||
|
PostalCode string `json:"postal_code" binding:"required"`
|
||||||
|
ProvinceID string `json:"province_id" binding:"required"`
|
||||||
|
CityID string `json:"city_id" binding:"required"`
|
||||||
|
DistrictID string `json:"district_id" binding:"required"`
|
||||||
|
SubdistrictID string `json:"subdistrict_id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreatePostalCodeResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
PostalCode *string `json:"postal_code"`
|
||||||
|
ProvinceID *string `json:"province_id"`
|
||||||
|
CityID *string `json:"city_id"`
|
||||||
|
DistrictID *string `json:"district_id"`
|
||||||
|
SubdistrictID *string `json:"subdistrict_id"`
|
||||||
|
MerchantID *string `json:"merchant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PostalCodeFilterAllRequest struct {
|
||||||
|
ID string `json:"id" form:"id"`
|
||||||
|
PostalCode string `json:"postal_code" form:"postal_code"`
|
||||||
|
ProvinceID string `json:"province_id" form:"province_id"`
|
||||||
|
CityID string `json:"city_id" form:"city_id"`
|
||||||
|
DistrictID string `json:"district_id" form:"district_id"`
|
||||||
|
SubdistrictID string `json:"subdistrict_id" form:"subdistrict_id"`
|
||||||
|
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdatePostalCodeRequest struct {
|
||||||
|
PostalCode string `json:"postal_code" binding:"required"`
|
||||||
|
ProvinceID string `json:"province_id" binding:"required"`
|
||||||
|
CityID string `json:"city_id" binding:"required"`
|
||||||
|
DistrictID string `json:"district_id" binding:"required"`
|
||||||
|
SubdistrictID string `json:"subdistrict_id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportPostalCodeResponse struct {
|
||||||
|
JobID string `json:"job_id,omitempty"`
|
||||||
|
TotalRows int `json:"total_rows"`
|
||||||
|
Imported int `json:"imported"`
|
||||||
|
Skipped int `json:"skipped"`
|
||||||
|
Logs []ImportLog `json:"logs"`
|
||||||
|
Errors []string `json:"errors"`
|
||||||
|
IsAsync bool `json:"is_async"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
@ -27,14 +27,14 @@ type ImportLog struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ImportProvinceResponse struct {
|
type ImportProvinceResponse struct {
|
||||||
JobID string `json:"job_id,omitempty"`
|
JobID string `json:"job_id,omitempty"`
|
||||||
TotalRows int `json:"total_rows"`
|
TotalRows int `json:"total_rows"`
|
||||||
Imported int `json:"imported"`
|
Imported int `json:"imported"`
|
||||||
Skipped int `json:"skipped"`
|
Skipped int `json:"skipped"`
|
||||||
Logs []ImportLog `json:"logs"`
|
Logs []ImportLog `json:"logs"`
|
||||||
Errors []string `json:"errors"`
|
Errors []string `json:"errors"`
|
||||||
IsAsync bool `json:"is_async"`
|
IsAsync bool `json:"is_async"`
|
||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type StopImportRequest struct {
|
type StopImportRequest struct {
|
||||||
|
|||||||
44
internal/handlers/dto/subdistrict.go
Normal file
44
internal/handlers/dto/subdistrict.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
type CreateSubdistrictRequest struct {
|
||||||
|
Name string `json:"name" binding:"required,min=2"`
|
||||||
|
ProvinceID string `json:"province_id" binding:"required"`
|
||||||
|
CityID string `json:"city_id" binding:"required"`
|
||||||
|
DistrictID string `json:"district_id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateSubdistrictResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name *string `json:"name"`
|
||||||
|
ProvinceID *string `json:"province_id"`
|
||||||
|
CityID *string `json:"city_id"`
|
||||||
|
DistrictID *string `json:"district_id"`
|
||||||
|
MerchantID *string `json:"merchant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubdistrictFilterAllRequest struct {
|
||||||
|
ID string `json:"id" form:"id"`
|
||||||
|
Name string `json:"name" form:"name"`
|
||||||
|
ProvinceID string `json:"province_id" form:"province_id"`
|
||||||
|
CityID string `json:"city_id" form:"city_id"`
|
||||||
|
DistrictID string `json:"district_id" form:"district_id"`
|
||||||
|
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateSubdistrictRequest struct {
|
||||||
|
Name string `json:"name" binding:"required,min=2"`
|
||||||
|
ProvinceID string `json:"province_id" binding:"required"`
|
||||||
|
CityID string `json:"city_id" binding:"required"`
|
||||||
|
DistrictID string `json:"district_id" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportSubdistrictResponse struct {
|
||||||
|
JobID string `json:"job_id,omitempty"`
|
||||||
|
TotalRows int `json:"total_rows"`
|
||||||
|
Imported int `json:"imported"`
|
||||||
|
Skipped int `json:"skipped"`
|
||||||
|
Logs []ImportLog `json:"logs"`
|
||||||
|
Errors []string `json:"errors"`
|
||||||
|
IsAsync bool `json:"is_async"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
@ -4,7 +4,9 @@ import (
|
|||||||
"cargo-erp-backend/internal/handlers/router/auth"
|
"cargo-erp-backend/internal/handlers/router/auth"
|
||||||
"cargo-erp-backend/internal/handlers/router/city"
|
"cargo-erp-backend/internal/handlers/router/city"
|
||||||
"cargo-erp-backend/internal/handlers/router/district"
|
"cargo-erp-backend/internal/handlers/router/district"
|
||||||
|
"cargo-erp-backend/internal/handlers/router/postal_code"
|
||||||
"cargo-erp-backend/internal/handlers/router/province"
|
"cargo-erp-backend/internal/handlers/router/province"
|
||||||
|
"cargo-erp-backend/internal/handlers/router/subdistrict"
|
||||||
"cargo-erp-backend/internal/middleware"
|
"cargo-erp-backend/internal/middleware"
|
||||||
"cargo-erp-backend/pkg/helpers"
|
"cargo-erp-backend/pkg/helpers"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -109,6 +111,8 @@ func (h *Handlers) Run() {
|
|||||||
province.NewProvinceHandler(h.Helper, masterdata).Router()
|
province.NewProvinceHandler(h.Helper, masterdata).Router()
|
||||||
city.NewCityHandler(h.Helper, masterdata).Router()
|
city.NewCityHandler(h.Helper, masterdata).Router()
|
||||||
district.NewDistrictHandler(h.Helper, masterdata).Router()
|
district.NewDistrictHandler(h.Helper, masterdata).Router()
|
||||||
|
subdistrict.NewSubdistrictHandler(h.Helper, masterdata).Router()
|
||||||
|
postal_code.NewPostalCodeHandler(h.Helper, masterdata).Router()
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Helper.Log().Info("Starting Apps")
|
h.Helper.Log().Info("Starting Apps")
|
||||||
|
|||||||
281
internal/handlers/router/postal_code/postal_code.go
Normal file
281
internal/handlers/router/postal_code/postal_code.go
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
package postal_code
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/handlers/dto"
|
||||||
|
postal_codeimporter "cargo-erp-backend/internal/importers/postal_code"
|
||||||
|
"cargo-erp-backend/internal/usecases"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"cargo-erp-backend/pkg/importer"
|
||||||
|
"cargo-erp-backend/pkg/response"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PostalCodeHandlerInterface interface {
|
||||||
|
Router()
|
||||||
|
}
|
||||||
|
|
||||||
|
type PostalCodeHandler struct {
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
Group *gin.RouterGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPostalCodeHandler(helper helpers.HelperInterface, g *gin.RouterGroup) PostalCodeHandlerInterface {
|
||||||
|
return &PostalCodeHandler{Helper: helper, Group: g}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) Router() {
|
||||||
|
r := h.Group.Group("postal-codes")
|
||||||
|
{
|
||||||
|
r.GET("/", h.GetAll)
|
||||||
|
r.POST("/list", h.GetList)
|
||||||
|
r.GET("/:id", h.GetByID)
|
||||||
|
r.POST("/", h.Create)
|
||||||
|
r.PUT("/:id", h.Update)
|
||||||
|
r.DELETE("/:id", h.Delete)
|
||||||
|
r.GET("/template", h.Template)
|
||||||
|
r.POST("/import", h.Import)
|
||||||
|
r.POST("/import/stop", h.ImportStop)
|
||||||
|
r.GET("/import/status/:jobId", h.ImportStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) GetAll(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req dto.PostalCodeFilterAllRequest
|
||||||
|
if err := c.ShouldBindQuery(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u := usecases.NewPostalCodeUsecase(h.Helper, *userid)
|
||||||
|
postalCodes, _, err := u.GetAll(req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseDTO = make([]dto.CreatePostalCodeResponse, 0)
|
||||||
|
for _, v := range postalCodes {
|
||||||
|
var DTO dto.CreatePostalCodeResponse
|
||||||
|
h.Helper.MapStructToStruct(v, "json", &DTO, "json")
|
||||||
|
responseDTO = append(responseDTO, DTO)
|
||||||
|
}
|
||||||
|
response.Success(c, responseDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) GetList(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req dto.DataTableRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u := usecases.NewPostalCodeUsecase(h.Helper, *userid)
|
||||||
|
res, err := u.GetList(req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Success(c, res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) GetByID(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
u := usecases.NewPostalCodeUsecase(h.Helper, *userid)
|
||||||
|
postalCode, err := u.GetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusNotFound, "postal code not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, postalCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) Create(c *gin.Context) {
|
||||||
|
var req dto.CreatePostalCodeRequest
|
||||||
|
if err := c.BindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var merchantid *string = nil
|
||||||
|
if userid.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
merchantid = userid.MerchantID
|
||||||
|
}
|
||||||
|
createdBy := userid.ID
|
||||||
|
|
||||||
|
u := usecases.NewPostalCodeUsecase(h.Helper, *userid)
|
||||||
|
postalCode, err := u.Create(req.PostalCode, req.ProvinceID, req.CityID, req.DistrictID, req.SubdistrictID, createdBy, merchantid)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseDTO dto.CreatePostalCodeResponse
|
||||||
|
h.Helper.MapStructToStruct(postalCode, "json", &responseDTO, "json")
|
||||||
|
response.Created(c, responseDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) Update(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
var req dto.UpdatePostalCodeRequest
|
||||||
|
if err := c.BindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updatedBy := userid.ID
|
||||||
|
|
||||||
|
u := usecases.NewPostalCodeUsecase(h.Helper, *userid)
|
||||||
|
postalCode, err := u.Update(id, req.PostalCode, req.ProvinceID, req.CityID, req.DistrictID, req.SubdistrictID, updatedBy)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseDTO dto.CreatePostalCodeResponse
|
||||||
|
h.Helper.MapStructToStruct(postalCode, "json", &responseDTO, "json")
|
||||||
|
response.Success(c, responseDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) Delete(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := c.Param("id")
|
||||||
|
u := usecases.NewPostalCodeUsecase(h.Helper, *userid)
|
||||||
|
if err := u.Delete(id); err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, map[string]interface{}{"message": "postal code deleted"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) Template(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handler := postal_codeimporter.NewPostalCodeImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
imp.ServeTemplate(c.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) Import(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, header, err := c.Request.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, "File is required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
handler := postal_codeimporter.NewPostalCodeImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
|
||||||
|
result, err := imp.Process(file, userid.ID, header.Filename)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var importLogs []dto.ImportLog
|
||||||
|
for _, l := range result.Logs {
|
||||||
|
importLogs = append(importLogs, dto.ImportLog{
|
||||||
|
Row: l.Row,
|
||||||
|
Status: l.Status,
|
||||||
|
Data: l.Data,
|
||||||
|
Message: l.Message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, dto.ImportPostalCodeResponse{
|
||||||
|
JobID: result.JobID,
|
||||||
|
TotalRows: result.TotalRows,
|
||||||
|
Imported: result.Imported,
|
||||||
|
Skipped: result.Skipped,
|
||||||
|
Logs: importLogs,
|
||||||
|
Errors: result.Errors,
|
||||||
|
IsAsync: result.IsAsync,
|
||||||
|
Message: result.Message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) ImportStatus(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jobId := c.Param("jobId")
|
||||||
|
|
||||||
|
handler := postal_codeimporter.NewPostalCodeImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
|
||||||
|
job, logs, err := imp.GetJobStatus(jobId)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusNotFound, "Job not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, map[string]interface{}{
|
||||||
|
"job": job,
|
||||||
|
"logs": logs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeHandler) ImportStop(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req dto.StopImportRequest
|
||||||
|
if err := c.BindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, "job_id is required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := postal_codeimporter.NewPostalCodeImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
|
||||||
|
if err := imp.StopJob(req.JobID); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, map[string]interface{}{"message": "Job stopped"})
|
||||||
|
}
|
||||||
281
internal/handlers/router/subdistrict/subdistrict.go
Normal file
281
internal/handlers/router/subdistrict/subdistrict.go
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
package subdistrict
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/handlers/dto"
|
||||||
|
subdistrictimporter "cargo-erp-backend/internal/importers/subdistrict"
|
||||||
|
"cargo-erp-backend/internal/usecases"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"cargo-erp-backend/pkg/importer"
|
||||||
|
"cargo-erp-backend/pkg/response"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubdistrictHandlerInterface interface {
|
||||||
|
Router()
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubdistrictHandler struct {
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
Group *gin.RouterGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSubdistrictHandler(helper helpers.HelperInterface, g *gin.RouterGroup) SubdistrictHandlerInterface {
|
||||||
|
return &SubdistrictHandler{Helper: helper, Group: g}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) Router() {
|
||||||
|
r := h.Group.Group("subdistricts")
|
||||||
|
{
|
||||||
|
r.GET("/", h.GetAll)
|
||||||
|
r.POST("/list", h.GetList)
|
||||||
|
r.GET("/:id", h.GetByID)
|
||||||
|
r.POST("/", h.Create)
|
||||||
|
r.PUT("/:id", h.Update)
|
||||||
|
r.DELETE("/:id", h.Delete)
|
||||||
|
r.GET("/template", h.Template)
|
||||||
|
r.POST("/import", h.Import)
|
||||||
|
r.POST("/import/stop", h.ImportStop)
|
||||||
|
r.GET("/import/status/:jobId", h.ImportStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) GetAll(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req dto.SubdistrictFilterAllRequest
|
||||||
|
if err := c.ShouldBindQuery(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u := usecases.NewSubdistrictUsecase(h.Helper, *userid)
|
||||||
|
subdistricts, _, err := u.GetAll(req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseDTO = make([]dto.CreateSubdistrictResponse, 0)
|
||||||
|
for _, v := range subdistricts {
|
||||||
|
var DTO dto.CreateSubdistrictResponse
|
||||||
|
h.Helper.MapStructToStruct(v, "json", &DTO, "json")
|
||||||
|
responseDTO = append(responseDTO, DTO)
|
||||||
|
}
|
||||||
|
response.Success(c, responseDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) GetList(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req dto.DataTableRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u := usecases.NewSubdistrictUsecase(h.Helper, *userid)
|
||||||
|
res, err := u.GetList(req)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Success(c, res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) GetByID(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
u := usecases.NewSubdistrictUsecase(h.Helper, *userid)
|
||||||
|
subdistrict, err := u.GetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusNotFound, "subdistrict not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, subdistrict)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) Create(c *gin.Context) {
|
||||||
|
var req dto.CreateSubdistrictRequest
|
||||||
|
if err := c.BindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var merchantid *string = nil
|
||||||
|
if userid.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
merchantid = userid.MerchantID
|
||||||
|
}
|
||||||
|
createdBy := userid.ID
|
||||||
|
|
||||||
|
u := usecases.NewSubdistrictUsecase(h.Helper, *userid)
|
||||||
|
subdistrict, err := u.Create(req.Name, req.ProvinceID, req.CityID, req.DistrictID, createdBy, merchantid)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseDTO dto.CreateSubdistrictResponse
|
||||||
|
h.Helper.MapStructToStruct(subdistrict, "json", &responseDTO, "json")
|
||||||
|
response.Created(c, responseDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) Update(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
var req dto.UpdateSubdistrictRequest
|
||||||
|
if err := c.BindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updatedBy := userid.ID
|
||||||
|
|
||||||
|
u := usecases.NewSubdistrictUsecase(h.Helper, *userid)
|
||||||
|
subdistrict, err := u.Update(id, req.Name, req.ProvinceID, req.CityID, req.DistrictID, updatedBy)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var responseDTO dto.CreateSubdistrictResponse
|
||||||
|
h.Helper.MapStructToStruct(subdistrict, "json", &responseDTO, "json")
|
||||||
|
response.Success(c, responseDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) Delete(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := c.Param("id")
|
||||||
|
u := usecases.NewSubdistrictUsecase(h.Helper, *userid)
|
||||||
|
if err := u.Delete(id); err != nil {
|
||||||
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, map[string]interface{}{"message": "subdistrict deleted"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) Template(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handler := subdistrictimporter.NewSubdistrictImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
imp.ServeTemplate(c.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) Import(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, header, err := c.Request.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, "File is required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
handler := subdistrictimporter.NewSubdistrictImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
|
||||||
|
result, err := imp.Process(file, userid.ID, header.Filename)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var importLogs []dto.ImportLog
|
||||||
|
for _, l := range result.Logs {
|
||||||
|
importLogs = append(importLogs, dto.ImportLog{
|
||||||
|
Row: l.Row,
|
||||||
|
Status: l.Status,
|
||||||
|
Data: l.Data,
|
||||||
|
Message: l.Message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, dto.ImportSubdistrictResponse{
|
||||||
|
JobID: result.JobID,
|
||||||
|
TotalRows: result.TotalRows,
|
||||||
|
Imported: result.Imported,
|
||||||
|
Skipped: result.Skipped,
|
||||||
|
Logs: importLogs,
|
||||||
|
Errors: result.Errors,
|
||||||
|
IsAsync: result.IsAsync,
|
||||||
|
Message: result.Message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) ImportStatus(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jobId := c.Param("jobId")
|
||||||
|
|
||||||
|
handler := subdistrictimporter.NewSubdistrictImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
|
||||||
|
job, logs, err := imp.GetJobStatus(jobId)
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusNotFound, "Job not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, map[string]interface{}{
|
||||||
|
"job": job,
|
||||||
|
"logs": logs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictHandler) ImportStop(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req dto.StopImportRequest
|
||||||
|
if err := c.BindJSON(&req); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, "job_id is required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := subdistrictimporter.NewSubdistrictImportHandler(*userid, h.Helper)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
|
||||||
|
if err := imp.StopJob(req.JobID); err != nil {
|
||||||
|
response.Error(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Success(c, map[string]interface{}{"message": "Job stopped"})
|
||||||
|
}
|
||||||
151
internal/importers/postal_code/importer.go
Normal file
151
internal/importers/postal_code/importer.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package postal_code
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/domain"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"cargo-erp-backend/pkg/importer"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PostalCodeImportHandler struct {
|
||||||
|
UserData domain.User
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
lastProvinceName string
|
||||||
|
lastCityName string
|
||||||
|
lastDistrictName string
|
||||||
|
lastSubdistrictName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPostalCodeImportHandler(userData domain.User, helper helpers.HelperInterface) importer.ImportHandler {
|
||||||
|
return &PostalCodeImportHandler{
|
||||||
|
UserData: userData,
|
||||||
|
Helper: helper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeImportHandler) ValidateRow(row []string, rowNumber int) (importer.RowData, []error) {
|
||||||
|
var errors []error
|
||||||
|
|
||||||
|
if len(row) < 5 {
|
||||||
|
errors = append(errors, fmt.Errorf("row must have 5 columns: postal_code, subdistrict_name, district_name, city_name, province_name"))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
postalCode := strings.TrimSpace(row[0])
|
||||||
|
if postalCode == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("postal_code is required"))
|
||||||
|
} else if len(postalCode) > 10 {
|
||||||
|
errors = append(errors, fmt.Errorf("postal_code must be at most 10 characters"))
|
||||||
|
}
|
||||||
|
|
||||||
|
subdistrictName := strings.TrimSpace(row[1])
|
||||||
|
if subdistrictName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("subdistrict_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
districtName := strings.TrimSpace(row[2])
|
||||||
|
if districtName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("district_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
cityName := strings.TrimSpace(row[3])
|
||||||
|
if cityName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("city_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
provinceName := strings.TrimSpace(row[4])
|
||||||
|
if provinceName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("province_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var province domain.Province
|
||||||
|
db := h.Helper.GetDB("slave")
|
||||||
|
if err := db.Where("UPPER(name) = ?", strings.ToUpper(provinceName)).First(&province).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("province '%s' not found", provinceName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var city domain.City
|
||||||
|
if err := db.Where("UPPER(name) = ? AND province_id = ?", strings.ToUpper(cityName), province.ID).First(&city).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("city '%s' not found in province '%s'", cityName, provinceName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var district domain.District
|
||||||
|
if err := db.Where("UPPER(name) = ? AND city_id = ?", strings.ToUpper(districtName), city.ID).First(&district).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("district '%s' not found in city '%s'", districtName, cityName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var subdistrict domain.Subdistrict
|
||||||
|
if err := db.Where("UPPER(name) = ? AND district_id = ?", strings.ToUpper(subdistrictName), district.ID).First(&subdistrict).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("subdistrict '%s' not found in district '%s'", subdistrictName, districtName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
h.lastProvinceName = provinceName
|
||||||
|
h.lastCityName = cityName
|
||||||
|
h.lastDistrictName = districtName
|
||||||
|
h.lastSubdistrictName = subdistrictName
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
nowStr := now.Format("2006-01-02 15:04:05")
|
||||||
|
pc := &domain.PostalCode{
|
||||||
|
PostalCode: &postalCode,
|
||||||
|
ProvinceID: &province.ID,
|
||||||
|
CityID: &city.ID,
|
||||||
|
DistrictID: &district.ID,
|
||||||
|
SubdistrictID: &subdistrict.ID,
|
||||||
|
MerchantID: h.UserData.MerchantID,
|
||||||
|
CreatedBy: &h.UserData.ID,
|
||||||
|
CreatedOn: &now,
|
||||||
|
UpdatedBy: &h.UserData.ID,
|
||||||
|
UpdatedOn: &nowStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
return pc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeImportHandler) GetDataString(data importer.RowData) string {
|
||||||
|
pc := data.(*domain.PostalCode)
|
||||||
|
code := ""
|
||||||
|
if pc.PostalCode != nil {
|
||||||
|
code = *pc.PostalCode
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s, %s, %s, %s, %s", code, h.lastSubdistrictName, h.lastDistrictName, h.lastCityName, h.lastProvinceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeImportHandler) IsDuplicate(db *gorm.DB, data importer.RowData) bool {
|
||||||
|
pc := data.(*domain.PostalCode)
|
||||||
|
var count int64
|
||||||
|
db.Model(&domain.PostalCode{}).
|
||||||
|
Joins("JOIN subdistrict ON postal_code.subdistrict_id = subdistrict.id").
|
||||||
|
Joins("JOIN district ON postal_code.district_id = district.id").
|
||||||
|
Joins("JOIN city ON postal_code.city_id = city.id").
|
||||||
|
Joins("JOIN province ON postal_code.province_id = province.id").
|
||||||
|
Where("UPPER(postal_code.postal_code) = ? AND UPPER(subdistrict.name) = ? AND UPPER(district.name) = ? AND UPPER(city.name) = ? AND UPPER(province.name) = ?",
|
||||||
|
strings.ToUpper(*pc.PostalCode), strings.ToUpper(h.lastSubdistrictName), strings.ToUpper(h.lastDistrictName), strings.ToUpper(h.lastCityName), strings.ToUpper(h.lastProvinceName)).
|
||||||
|
Count(&count)
|
||||||
|
return count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeImportHandler) GetTemplateHeaders() []string {
|
||||||
|
return []string{"postal_code", "subdistrict_name", "district_name", "city_name", "province_name"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *PostalCodeImportHandler) GetTemplateRows() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
{"10430", "Kramat Pulo", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
{"10430", "Senen", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
{"10440", "Cempaka Putih", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
{"10510", "Gambir", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
}
|
||||||
|
}
|
||||||
137
internal/importers/subdistrict/importer.go
Normal file
137
internal/importers/subdistrict/importer.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package subdistrict
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/domain"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"cargo-erp-backend/pkg/importer"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubdistrictImportHandler struct {
|
||||||
|
UserData domain.User
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
lastProvinceName string
|
||||||
|
lastCityName string
|
||||||
|
lastDistrictName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSubdistrictImportHandler(userData domain.User, helper helpers.HelperInterface) importer.ImportHandler {
|
||||||
|
return &SubdistrictImportHandler{
|
||||||
|
UserData: userData,
|
||||||
|
Helper: helper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictImportHandler) ValidateRow(row []string, rowNumber int) (importer.RowData, []error) {
|
||||||
|
var errors []error
|
||||||
|
|
||||||
|
if len(row) < 4 {
|
||||||
|
errors = append(errors, fmt.Errorf("row must have 4 columns: name, district_name, city_name, province_name"))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.TrimSpace(row[0])
|
||||||
|
if name == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("name is required"))
|
||||||
|
} else if len(name) < 2 {
|
||||||
|
errors = append(errors, fmt.Errorf("name must be at least 2 characters"))
|
||||||
|
} else if len(name) > 255 {
|
||||||
|
errors = append(errors, fmt.Errorf("name must be at most 255 characters"))
|
||||||
|
}
|
||||||
|
|
||||||
|
districtName := strings.TrimSpace(row[1])
|
||||||
|
if districtName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("district_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
cityName := strings.TrimSpace(row[2])
|
||||||
|
if cityName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("city_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
provinceName := strings.TrimSpace(row[3])
|
||||||
|
if provinceName == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("province_name is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var province domain.Province
|
||||||
|
db := h.Helper.GetDB("slave")
|
||||||
|
if err := db.Where("UPPER(name) = ?", strings.ToUpper(provinceName)).First(&province).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("province '%s' not found", provinceName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var city domain.City
|
||||||
|
if err := db.Where("UPPER(name) = ? AND province_id = ?", strings.ToUpper(cityName), province.ID).First(&city).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("city '%s' not found in province '%s'", cityName, provinceName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
var district domain.District
|
||||||
|
if err := db.Where("UPPER(name) = ? AND city_id = ?", strings.ToUpper(districtName), city.ID).First(&district).Error; err != nil {
|
||||||
|
errors = append(errors, fmt.Errorf("district '%s' not found in city '%s'", districtName, cityName))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
h.lastProvinceName = provinceName
|
||||||
|
h.lastCityName = cityName
|
||||||
|
h.lastDistrictName = districtName
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
subdistrict := &domain.Subdistrict{
|
||||||
|
Name: &name,
|
||||||
|
ProvinceID: &province.ID,
|
||||||
|
CityID: &city.ID,
|
||||||
|
DistrictID: &district.ID,
|
||||||
|
MerchantID: h.UserData.MerchantID,
|
||||||
|
CreatedBy: &h.UserData.ID,
|
||||||
|
CreatedOn: &now,
|
||||||
|
UpdatedBy: &h.UserData.ID,
|
||||||
|
UpdatedOn: &now,
|
||||||
|
}
|
||||||
|
|
||||||
|
return subdistrict, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictImportHandler) GetDataString(data importer.RowData) string {
|
||||||
|
subdistrict := data.(*domain.Subdistrict)
|
||||||
|
name := ""
|
||||||
|
if subdistrict.Name != nil {
|
||||||
|
name = *subdistrict.Name
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s, %s, %s, %s", name, h.lastDistrictName, h.lastCityName, h.lastProvinceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictImportHandler) IsDuplicate(db *gorm.DB, data importer.RowData) bool {
|
||||||
|
subdistrict := data.(*domain.Subdistrict)
|
||||||
|
var count int64
|
||||||
|
db.Model(&domain.Subdistrict{}).
|
||||||
|
Joins("JOIN district ON subdistrict.district_id = district.id").
|
||||||
|
Joins("JOIN city ON subdistrict.city_id = city.id").
|
||||||
|
Joins("JOIN province ON subdistrict.province_id = province.id").
|
||||||
|
Where("UPPER(subdistrict.name) = ? AND UPPER(district.name) = ? AND UPPER(city.name) = ? AND UPPER(province.name) = ?",
|
||||||
|
strings.ToUpper(*subdistrict.Name), strings.ToUpper(h.lastDistrictName), strings.ToUpper(h.lastCityName), strings.ToUpper(h.lastProvinceName)).
|
||||||
|
Count(&count)
|
||||||
|
return count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictImportHandler) GetTemplateHeaders() []string {
|
||||||
|
return []string{"name", "district_name", "city_name", "province_name"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SubdistrictImportHandler) GetTemplateRows() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
{"Kramat Pulo", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
{"Senen", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
{"Cempaka Putih", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
{"Gambir", "Jakarta Pusat", "Jakarta Pusat", "DKI Jakarta"},
|
||||||
|
}
|
||||||
|
}
|
||||||
184
internal/usecases/postal_code.go
Normal file
184
internal/usecases/postal_code.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package usecases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/domain"
|
||||||
|
"cargo-erp-backend/internal/handlers/dto"
|
||||||
|
"cargo-erp-backend/pkg/datatable"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PostalCodeUsecaseInterface interface {
|
||||||
|
GetAll(filter dto.PostalCodeFilterAllRequest) ([]domain.PostalCode, int64, error)
|
||||||
|
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||||
|
GetByID(id string) (domain.PostalCode, error)
|
||||||
|
Create(postalCode string, provinceID string, cityID string, districtID string, subdistrictID string, createdBy string, merchantid *string) (domain.PostalCode, error)
|
||||||
|
Update(id string, postalCode string, provinceID string, cityID string, districtID string, subdistrictID string, updatedBy string) (domain.PostalCode, error)
|
||||||
|
Delete(id string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type PostalCodeUsecase struct {
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
AuthUser domain.User
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPostalCodeUsecase(helper helpers.HelperInterface, authUser domain.User) PostalCodeUsecaseInterface {
|
||||||
|
return &PostalCodeUsecase{Helper: helper, AuthUser: authUser}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *PostalCodeUsecase) GetAll(filter dto.PostalCodeFilterAllRequest) ([]domain.PostalCode, int64, error) {
|
||||||
|
var postalCodes []domain.PostalCode
|
||||||
|
var total int64
|
||||||
|
|
||||||
|
db := u.Helper.GetDB("slave")
|
||||||
|
tx := db.Model(&postalCodes)
|
||||||
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(filter)
|
||||||
|
t := reflect.TypeOf(filter)
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
if v.Field(i).String() != "" {
|
||||||
|
tagKey := t.Field(i).Tag.Get("form")
|
||||||
|
tx.Where(fmt.Sprintf("%v=?", tagKey), v.Field(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tx.Model(&domain.PostalCode{}).Count(&total)
|
||||||
|
tx.Order("postal_code ASC")
|
||||||
|
if err := tx.Find(&postalCodes).Error; err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return postalCodes, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *PostalCodeUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
|
||||||
|
var response dto.DataTableResponse
|
||||||
|
db := u.Helper.GetDB("slave")
|
||||||
|
tx := db.Table("postal_code").
|
||||||
|
Joins("LEFT JOIN subdistrict ON postal_code.subdistrict_id=subdistrict.id").
|
||||||
|
Joins("LEFT JOIN district ON postal_code.district_id=district.id").
|
||||||
|
Joins("LEFT JOIN city ON postal_code.city_id=city.id").
|
||||||
|
Joins("LEFT JOIN province ON postal_code.province_id=province.id").
|
||||||
|
Joins("LEFT JOIN merchant ON postal_code.merchant_id=merchant.id")
|
||||||
|
dt := datatable.NewDatatable(tx, req)
|
||||||
|
coldef := make([]dto.DataTableColDef, 0)
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "postal_code.postal_code",
|
||||||
|
Alias: "postal_code",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "subdistrict.name",
|
||||||
|
Alias: "subdistrict_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "district.name",
|
||||||
|
Alias: "district_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "city.name",
|
||||||
|
Alias: "city_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "province.name",
|
||||||
|
Alias: "province_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "postal_code.province_id",
|
||||||
|
Alias: "province_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "postal_code.city_id",
|
||||||
|
Alias: "city_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "postal_code.district_id",
|
||||||
|
Alias: "district_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "postal_code.subdistrict_id",
|
||||||
|
Alias: "subdistrict_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "merchant.id",
|
||||||
|
Alias: "merchant_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "postal_code.id",
|
||||||
|
Alias: "id",
|
||||||
|
})
|
||||||
|
|
||||||
|
response = dt.Render(coldef)
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *PostalCodeUsecase) GetByID(id string) (domain.PostalCode, error) {
|
||||||
|
var postalCode domain.PostalCode
|
||||||
|
db := u.Helper.GetDB("slave")
|
||||||
|
if err := db.Where("id = ?", id).First(&postalCode).Error; err != nil {
|
||||||
|
return domain.PostalCode{}, err
|
||||||
|
}
|
||||||
|
return postalCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *PostalCodeUsecase) Create(postalCode string, provinceID string, cityID string, districtID string, subdistrictID string, createdBy string, merchantid *string) (domain.PostalCode, error) {
|
||||||
|
now := time.Now()
|
||||||
|
nowStr := now.Format("2006-01-02 15:04:05")
|
||||||
|
pc := domain.PostalCode{
|
||||||
|
PostalCode: &postalCode,
|
||||||
|
ProvinceID: &provinceID,
|
||||||
|
CityID: &cityID,
|
||||||
|
DistrictID: &districtID,
|
||||||
|
SubdistrictID: &subdistrictID,
|
||||||
|
MerchantID: merchantid,
|
||||||
|
CreatedBy: &createdBy,
|
||||||
|
CreatedOn: &now,
|
||||||
|
UpdatedBy: &createdBy,
|
||||||
|
UpdatedOn: &nowStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
db := u.Helper.GetDB("master")
|
||||||
|
if err := db.Create(&pc).Error; err != nil {
|
||||||
|
return domain.PostalCode{}, err
|
||||||
|
}
|
||||||
|
return pc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *PostalCodeUsecase) Update(id string, postalCode string, provinceID string, cityID string, districtID string, subdistrictID string, updatedBy string) (domain.PostalCode, error) {
|
||||||
|
var pc domain.PostalCode
|
||||||
|
db := u.Helper.GetDB("master")
|
||||||
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||||
|
}
|
||||||
|
if err := db.Where("id = ?", id).First(&pc).Error; err != nil {
|
||||||
|
return domain.PostalCode{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
nowStr := now.Format("2006-01-02 15:04:05")
|
||||||
|
pc.PostalCode = &postalCode
|
||||||
|
pc.ProvinceID = &provinceID
|
||||||
|
pc.CityID = &cityID
|
||||||
|
pc.DistrictID = &districtID
|
||||||
|
pc.SubdistrictID = &subdistrictID
|
||||||
|
pc.UpdatedBy = &updatedBy
|
||||||
|
pc.UpdatedOn = &nowStr
|
||||||
|
|
||||||
|
if err := db.Save(&pc).Error; err != nil {
|
||||||
|
return domain.PostalCode{}, err
|
||||||
|
}
|
||||||
|
return pc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *PostalCodeUsecase) Delete(id string) error {
|
||||||
|
db := u.Helper.GetDB("master")
|
||||||
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||||
|
}
|
||||||
|
if err := db.Delete(&domain.PostalCode{}, "id = ?", id).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
171
internal/usecases/subdistrict.go
Normal file
171
internal/usecases/subdistrict.go
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
package usecases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/domain"
|
||||||
|
"cargo-erp-backend/internal/handlers/dto"
|
||||||
|
"cargo-erp-backend/pkg/datatable"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubdistrictUsecaseInterface interface {
|
||||||
|
GetAll(filter dto.SubdistrictFilterAllRequest) ([]domain.Subdistrict, int64, error)
|
||||||
|
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||||
|
GetByID(id string) (domain.Subdistrict, error)
|
||||||
|
Create(name string, provinceID string, cityID string, districtID string, createdBy string, merchantid *string) (domain.Subdistrict, error)
|
||||||
|
Update(id string, name string, provinceID string, cityID string, districtID string, updatedBy string) (domain.Subdistrict, error)
|
||||||
|
Delete(id string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubdistrictUsecase struct {
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
AuthUser domain.User
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSubdistrictUsecase(helper helpers.HelperInterface, authUser domain.User) SubdistrictUsecaseInterface {
|
||||||
|
return &SubdistrictUsecase{Helper: helper, AuthUser: authUser}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *SubdistrictUsecase) GetAll(filter dto.SubdistrictFilterAllRequest) ([]domain.Subdistrict, int64, error) {
|
||||||
|
var subdistricts []domain.Subdistrict
|
||||||
|
var total int64
|
||||||
|
|
||||||
|
db := u.Helper.GetDB("slave")
|
||||||
|
tx := db.Model(&subdistricts)
|
||||||
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
||||||
|
}
|
||||||
|
v := reflect.ValueOf(filter)
|
||||||
|
t := reflect.TypeOf(filter)
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
if v.Field(i).String() != "" {
|
||||||
|
tagKey := t.Field(i).Tag.Get("form")
|
||||||
|
tx.Where(fmt.Sprintf("%v=?", tagKey), v.Field(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tx.Model(&domain.Subdistrict{}).Count(&total)
|
||||||
|
tx.Order("name ASC")
|
||||||
|
if err := tx.Find(&subdistricts).Error; err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return subdistricts, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *SubdistrictUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
|
||||||
|
var response dto.DataTableResponse
|
||||||
|
db := u.Helper.GetDB("slave")
|
||||||
|
tx := db.Table("subdistrict").
|
||||||
|
Joins("LEFT JOIN district ON subdistrict.district_id=district.id").
|
||||||
|
Joins("LEFT JOIN city ON subdistrict.city_id=city.id").
|
||||||
|
Joins("LEFT JOIN province ON subdistrict.province_id=province.id").
|
||||||
|
Joins("LEFT JOIN merchant ON subdistrict.merchant_id=merchant.id")
|
||||||
|
dt := datatable.NewDatatable(tx, req)
|
||||||
|
coldef := make([]dto.DataTableColDef, 0)
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "subdistrict.name",
|
||||||
|
Alias: "name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "district.name",
|
||||||
|
Alias: "district_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "city.name",
|
||||||
|
Alias: "city_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "province.name",
|
||||||
|
Alias: "province_name",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "subdistrict.province_id",
|
||||||
|
Alias: "province_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "subdistrict.city_id",
|
||||||
|
Alias: "city_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "subdistrict.district_id",
|
||||||
|
Alias: "district_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "merchant.id",
|
||||||
|
Alias: "merchant_id",
|
||||||
|
})
|
||||||
|
coldef = append(coldef, dto.DataTableColDef{
|
||||||
|
Field: "subdistrict.id",
|
||||||
|
Alias: "id",
|
||||||
|
})
|
||||||
|
|
||||||
|
response = dt.Render(coldef)
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *SubdistrictUsecase) GetByID(id string) (domain.Subdistrict, error) {
|
||||||
|
var subdistrict domain.Subdistrict
|
||||||
|
db := u.Helper.GetDB("slave")
|
||||||
|
if err := db.Where("id = ?", id).First(&subdistrict).Error; err != nil {
|
||||||
|
return domain.Subdistrict{}, err
|
||||||
|
}
|
||||||
|
return subdistrict, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *SubdistrictUsecase) Create(name string, provinceID string, cityID string, districtID string, createdBy string, merchantid *string) (domain.Subdistrict, error) {
|
||||||
|
now := time.Now()
|
||||||
|
subdistrict := domain.Subdistrict{
|
||||||
|
Name: &name,
|
||||||
|
ProvinceID: &provinceID,
|
||||||
|
CityID: &cityID,
|
||||||
|
DistrictID: &districtID,
|
||||||
|
MerchantID: merchantid,
|
||||||
|
CreatedBy: &createdBy,
|
||||||
|
CreatedOn: &now,
|
||||||
|
UpdatedBy: &createdBy,
|
||||||
|
UpdatedOn: &now,
|
||||||
|
}
|
||||||
|
|
||||||
|
db := u.Helper.GetDB("master")
|
||||||
|
if err := db.Create(&subdistrict).Error; err != nil {
|
||||||
|
return domain.Subdistrict{}, err
|
||||||
|
}
|
||||||
|
return subdistrict, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *SubdistrictUsecase) Update(id string, name string, provinceID string, cityID string, districtID string, updatedBy string) (domain.Subdistrict, error) {
|
||||||
|
var subdistrict domain.Subdistrict
|
||||||
|
db := u.Helper.GetDB("master")
|
||||||
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||||
|
}
|
||||||
|
if err := db.Where("id = ?", id).First(&subdistrict).Error; err != nil {
|
||||||
|
return domain.Subdistrict{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
subdistrict.Name = &name
|
||||||
|
subdistrict.ProvinceID = &provinceID
|
||||||
|
subdistrict.CityID = &cityID
|
||||||
|
subdistrict.DistrictID = &districtID
|
||||||
|
subdistrict.UpdatedBy = &updatedBy
|
||||||
|
subdistrict.UpdatedOn = &now
|
||||||
|
|
||||||
|
if err := db.Save(&subdistrict).Error; err != nil {
|
||||||
|
return domain.Subdistrict{}, err
|
||||||
|
}
|
||||||
|
return subdistrict, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *SubdistrictUsecase) Delete(id string) error {
|
||||||
|
db := u.Helper.GetDB("master")
|
||||||
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
|
db.Where("merchant_id=?", u.AuthUser.MerchantID)
|
||||||
|
}
|
||||||
|
if err := db.Delete(&domain.Subdistrict{}, "id = ?", id).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -914,3 +914,12 @@
|
|||||||
{"level":"info","ts":"2026-08-18T20:24:04.777+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
{"level":"info","ts":"2026-08-18T20:24:04.777+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
||||||
{"level":"info","ts":"2026-08-18T20:24:04.834+0700","caller":"middleware/auth.go:90","msg":"Set Auth : {\"blocked\":false,\"blocked_notes\":null,\"citys_relation\":null,\"created_by\":null,\"created_on\":\"2026-08-11T20:30:48.554654Z\",\"districts_relation\":null,\"email\":\"gcx@gmail.com\",\"id\":\"19ff104c16522a2252cbaca24d\",\"is_active\":true,\"merchant_id\":\"19ff111bca6c2c382d9eb43b3c\",\"merchant_relation\":null,\"merchants_relation\":null,\"nick_name\":\"Administrator\",\"postal_codes_relation\":null,\"provinces_relation\":null,\"subdistricts_relation\":null,\"updated_by\":null,\"updated_on\":\"2026-08-11T20:30:48.554654Z\",\"users_role_id\":\"19fe814c5350d67814c3e6057c\",\"users_role_relation\":{\"created_by\":null,\"created_on\":\"2026-08-10T02:51:43.16495Z\",\"id\":\"19fe814c5350d67814c3e6057c\",\"merchant_id\":null,\"merchant_relation\":{\"active\":null,\"additional_information\":null,\"address\":null,\"city_id\":null,\"city_relation\":null,\"citys_relation\":null,\"created_by\":null,\"created_by_relation\":null,\"created_on\":null,\"district_id\":null,\"district_relation\":null,\"districts_relation\":null,\"email\":null,\"id\":\"\",\"modas_relation\":null,\"name\":null,\"package_types_relation\":null,\"postal_code\":null,\"postal_codes_relation\":null,\"province_id\":null,\"province_relation\":null,\"provinces_relation\":null,\"subdistrict_id\":null,\"subdistrict_relation\":null,\"subdistricts_relation\":null,\"telp\":null,\"updated_by\":null,\"updated_on\":null,\"users_roless_relation\":null,\"userss_relation\":null},\"name\":\"Administrator\",\"role_key\":\"ADM_MERCHANT\",\"updated_by\":null,\"updated_on\":\"2026-08-10T02:51:43.16495Z\",\"userss_relation\":null}}"}
|
{"level":"info","ts":"2026-08-18T20:24:04.834+0700","caller":"middleware/auth.go:90","msg":"Set Auth : {\"blocked\":false,\"blocked_notes\":null,\"citys_relation\":null,\"created_by\":null,\"created_on\":\"2026-08-11T20:30:48.554654Z\",\"districts_relation\":null,\"email\":\"gcx@gmail.com\",\"id\":\"19ff104c16522a2252cbaca24d\",\"is_active\":true,\"merchant_id\":\"19ff111bca6c2c382d9eb43b3c\",\"merchant_relation\":null,\"merchants_relation\":null,\"nick_name\":\"Administrator\",\"postal_codes_relation\":null,\"provinces_relation\":null,\"subdistricts_relation\":null,\"updated_by\":null,\"updated_on\":\"2026-08-11T20:30:48.554654Z\",\"users_role_id\":\"19fe814c5350d67814c3e6057c\",\"users_role_relation\":{\"created_by\":null,\"created_on\":\"2026-08-10T02:51:43.16495Z\",\"id\":\"19fe814c5350d67814c3e6057c\",\"merchant_id\":null,\"merchant_relation\":{\"active\":null,\"additional_information\":null,\"address\":null,\"city_id\":null,\"city_relation\":null,\"citys_relation\":null,\"created_by\":null,\"created_by_relation\":null,\"created_on\":null,\"district_id\":null,\"district_relation\":null,\"districts_relation\":null,\"email\":null,\"id\":\"\",\"modas_relation\":null,\"name\":null,\"package_types_relation\":null,\"postal_code\":null,\"postal_codes_relation\":null,\"province_id\":null,\"province_relation\":null,\"provinces_relation\":null,\"subdistrict_id\":null,\"subdistrict_relation\":null,\"subdistricts_relation\":null,\"telp\":null,\"updated_by\":null,\"updated_on\":null,\"users_roless_relation\":null,\"userss_relation\":null},\"name\":\"Administrator\",\"role_key\":\"ADM_MERCHANT\",\"updated_by\":null,\"updated_on\":\"2026-08-10T02:51:43.16495Z\",\"userss_relation\":null}}"}
|
||||||
{"level":"info","ts":"2026-08-18T20:24:05.015+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"POST","path":"/master-data/cities/list","query":"","ip":"127.0.0.1","latency":0.239231125,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
{"level":"info","ts":"2026-08-18T20:24:05.015+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"POST","path":"/master-data/cities/list","query":"","ip":"127.0.0.1","latency":0.239231125,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:33:56.318+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:33:57.630+0700","caller":"middleware/auth.go:90","msg":"Set Auth : {\"blocked\":false,\"blocked_notes\":null,\"citys_relation\":null,\"created_by\":null,\"created_on\":\"2026-08-11T20:30:48.554654Z\",\"districts_relation\":null,\"email\":\"gcx@gmail.com\",\"id\":\"19ff104c16522a2252cbaca24d\",\"is_active\":true,\"merchant_id\":\"19ff111bca6c2c382d9eb43b3c\",\"merchant_relation\":null,\"merchants_relation\":null,\"nick_name\":\"Administrator\",\"postal_codes_relation\":null,\"provinces_relation\":null,\"subdistricts_relation\":null,\"updated_by\":null,\"updated_on\":\"2026-08-11T20:30:48.554654Z\",\"users_role_id\":\"19fe814c5350d67814c3e6057c\",\"users_role_relation\":{\"created_by\":null,\"created_on\":\"2026-08-10T02:51:43.16495Z\",\"id\":\"19fe814c5350d67814c3e6057c\",\"merchant_id\":null,\"merchant_relation\":{\"active\":null,\"additional_information\":null,\"address\":null,\"city_id\":null,\"city_relation\":null,\"citys_relation\":null,\"created_by\":null,\"created_by_relation\":null,\"created_on\":null,\"district_id\":null,\"district_relation\":null,\"districts_relation\":null,\"email\":null,\"id\":\"\",\"modas_relation\":null,\"name\":null,\"package_types_relation\":null,\"postal_code\":null,\"postal_codes_relation\":null,\"province_id\":null,\"province_relation\":null,\"provinces_relation\":null,\"subdistrict_id\":null,\"subdistrict_relation\":null,\"subdistricts_relation\":null,\"telp\":null,\"updated_by\":null,\"updated_on\":null,\"users_roless_relation\":null,\"userss_relation\":null},\"name\":\"Administrator\",\"role_key\":\"ADM_MERCHANT\",\"updated_by\":null,\"updated_on\":\"2026-08-10T02:51:43.16495Z\",\"userss_relation\":null}}"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:33:58.058+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"POST","path":"/master-data/cities/list","query":"","ip":"127.0.0.1","latency":1.749137667,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:36:08.722+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:36:09.348+0700","caller":"middleware/auth.go:90","msg":"Set Auth : {\"blocked\":false,\"blocked_notes\":null,\"citys_relation\":null,\"created_by\":null,\"created_on\":\"2026-08-11T20:30:48.554654Z\",\"districts_relation\":null,\"email\":\"gcx@gmail.com\",\"id\":\"19ff104c16522a2252cbaca24d\",\"is_active\":true,\"merchant_id\":\"19ff111bca6c2c382d9eb43b3c\",\"merchant_relation\":null,\"merchants_relation\":null,\"nick_name\":\"Administrator\",\"postal_codes_relation\":null,\"provinces_relation\":null,\"subdistricts_relation\":null,\"updated_by\":null,\"updated_on\":\"2026-08-11T20:30:48.554654Z\",\"users_role_id\":\"19fe814c5350d67814c3e6057c\",\"users_role_relation\":{\"created_by\":null,\"created_on\":\"2026-08-10T02:51:43.16495Z\",\"id\":\"19fe814c5350d67814c3e6057c\",\"merchant_id\":null,\"merchant_relation\":{\"active\":null,\"additional_information\":null,\"address\":null,\"city_id\":null,\"city_relation\":null,\"citys_relation\":null,\"created_by\":null,\"created_by_relation\":null,\"created_on\":null,\"district_id\":null,\"district_relation\":null,\"districts_relation\":null,\"email\":null,\"id\":\"\",\"modas_relation\":null,\"name\":null,\"package_types_relation\":null,\"postal_code\":null,\"postal_codes_relation\":null,\"province_id\":null,\"province_relation\":null,\"provinces_relation\":null,\"subdistrict_id\":null,\"subdistrict_relation\":null,\"subdistricts_relation\":null,\"telp\":null,\"updated_by\":null,\"updated_on\":null,\"users_roless_relation\":null,\"userss_relation\":null},\"name\":\"Administrator\",\"role_key\":\"ADM_MERCHANT\",\"updated_by\":null,\"updated_on\":\"2026-08-10T02:51:43.16495Z\",\"userss_relation\":null}}"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:36:09.857+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"POST","path":"/master-data/districts/list","query":"","ip":"127.0.0.1","latency":1.136347459,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:37:45.299+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:37:45.397+0700","caller":"middleware/auth.go:90","msg":"Set Auth : {\"blocked\":false,\"blocked_notes\":null,\"citys_relation\":null,\"created_by\":null,\"created_on\":\"2026-08-11T20:30:48.554654Z\",\"districts_relation\":null,\"email\":\"gcx@gmail.com\",\"id\":\"19ff104c16522a2252cbaca24d\",\"is_active\":true,\"merchant_id\":\"19ff111bca6c2c382d9eb43b3c\",\"merchant_relation\":null,\"merchants_relation\":null,\"nick_name\":\"Administrator\",\"postal_codes_relation\":null,\"provinces_relation\":null,\"subdistricts_relation\":null,\"updated_by\":null,\"updated_on\":\"2026-08-11T20:30:48.554654Z\",\"users_role_id\":\"19fe814c5350d67814c3e6057c\",\"users_role_relation\":{\"created_by\":null,\"created_on\":\"2026-08-10T02:51:43.16495Z\",\"id\":\"19fe814c5350d67814c3e6057c\",\"merchant_id\":null,\"merchant_relation\":{\"active\":null,\"additional_information\":null,\"address\":null,\"city_id\":null,\"city_relation\":null,\"citys_relation\":null,\"created_by\":null,\"created_by_relation\":null,\"created_on\":null,\"district_id\":null,\"district_relation\":null,\"districts_relation\":null,\"email\":null,\"id\":\"\",\"modas_relation\":null,\"name\":null,\"package_types_relation\":null,\"postal_code\":null,\"postal_codes_relation\":null,\"province_id\":null,\"province_relation\":null,\"provinces_relation\":null,\"subdistrict_id\":null,\"subdistrict_relation\":null,\"subdistricts_relation\":null,\"telp\":null,\"updated_by\":null,\"updated_on\":null,\"users_roless_relation\":null,\"userss_relation\":null},\"name\":\"Administrator\",\"role_key\":\"ADM_MERCHANT\",\"updated_by\":null,\"updated_on\":\"2026-08-10T02:51:43.16495Z\",\"userss_relation\":null}}"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:37:45.428+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"GET","path":"/master-data/districts/template","query":"","ip":"127.0.0.1","latency":0.137240458,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
|||||||
@ -3581,3 +3581,9 @@
|
|||||||
{"level":"info","ts":"2026-08-18T20:24:04.900+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:30","elapsed":0.053077667,"rows":1,"sql":"SELECT count(*) FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id"}
|
{"level":"info","ts":"2026-08-18T20:24:04.900+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:30","elapsed":0.053077667,"rows":1,"sql":"SELECT count(*) FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id"}
|
||||||
{"level":"info","ts":"2026-08-18T20:24:04.957+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:81","elapsed":0.054915792,"rows":1,"sql":"SELECT count(*) FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id WHERE city.province_id='19fe79fac96c4db9fbb7fe5c52'"}
|
{"level":"info","ts":"2026-08-18T20:24:04.957+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:81","elapsed":0.054915792,"rows":1,"sql":"SELECT count(*) FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id WHERE city.province_id='19fe79fac96c4db9fbb7fe5c52'"}
|
||||||
{"level":"info","ts":"2026-08-18T20:24:05.014+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:89","elapsed":0.057587875,"rows":10,"sql":"SELECT city.name AS name,province.name AS province_name,city.province_id AS province_id,merchant.id AS merchant_id,city.id AS id FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id WHERE city.province_id='19fe79fac96c4db9fbb7fe5c52' ORDER BY city.name ASC LIMIT 10"}
|
{"level":"info","ts":"2026-08-18T20:24:05.014+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:89","elapsed":0.057587875,"rows":10,"sql":"SELECT city.name AS name,province.name AS province_name,city.province_id AS province_id,merchant.id AS merchant_id,city.id AS id FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id WHERE city.province_id='19fe79fac96c4db9fbb7fe5c52' ORDER BY city.name ASC LIMIT 10"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:33:57.963+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:30","elapsed":0.317756709,"rows":1,"sql":"SELECT count(*) FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:33:58.009+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:81","elapsed":0.045027208,"rows":1,"sql":"SELECT count(*) FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:33:58.055+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:89","elapsed":0.04498725,"rows":10,"sql":"SELECT city.name AS name,province.name AS province_name,city.province_id AS province_id,merchant.id AS merchant_id,city.id AS id FROM \"city\" INNER JOIN province ON city.province_id=province.id LEFT JOIN merchant ON city.merchant_id=merchant.id ORDER BY city.name ASC LIMIT 10"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:36:09.759+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:30","elapsed":0.4042015,"rows":1,"sql":"SELECT count(*) FROM \"district\" LEFT JOIN city ON district.city_id=city.id LEFT JOIN province ON district.province_id=province.id LEFT JOIN merchant ON district.merchant_id=merchant.id"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:36:09.792+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:81","elapsed":0.032117583,"rows":1,"sql":"SELECT count(*) FROM \"district\" LEFT JOIN city ON district.city_id=city.id LEFT JOIN province ON district.province_id=province.id LEFT JOIN merchant ON district.merchant_id=merchant.id"}
|
||||||
|
{"level":"info","ts":"2026-08-18T20:36:09.856+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/datatable/datatable.go:89","elapsed":0.064178167,"rows":10,"sql":"SELECT district.name AS name,city.name AS city_name,province.name AS province_name,district.province_id AS province_id,district.city_id AS city_id,merchant.id AS merchant_id,district.id AS id FROM \"district\" LEFT JOIN city ON district.city_id=city.id LEFT JOIN province ON district.province_id=province.id LEFT JOIN merchant ON district.merchant_id=merchant.id ORDER BY district.name ASC LIMIT 10"}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user