This commit is contained in:
parent
bd467aefe2
commit
10575b2512
40
internal/handlers/dto/district.go
Normal file
40
internal/handlers/dto/district.go
Normal file
@ -0,0 +1,40 @@
|
||||
package dto
|
||||
|
||||
type CreateDistrictRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2"`
|
||||
ProvinceID string `json:"province_id" binding:"required"`
|
||||
CityID string `json:"city_id" binding:"required"`
|
||||
}
|
||||
|
||||
type CreateDistrictResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name *string `json:"name"`
|
||||
ProvinceID *string `json:"province_id"`
|
||||
CityID *string `json:"city_id"`
|
||||
MerchantID *string `json:"merchant_id"`
|
||||
}
|
||||
|
||||
type DistrictFilterAllRequest 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"`
|
||||
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||
}
|
||||
|
||||
type UpdateDistrictRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2"`
|
||||
ProvinceID string `json:"province_id" binding:"required"`
|
||||
CityID string `json:"city_id" binding:"required"`
|
||||
}
|
||||
|
||||
type ImportDistrictResponse 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"`
|
||||
}
|
||||
@ -3,6 +3,7 @@ package handlers
|
||||
import (
|
||||
"cargo-erp-backend/internal/handlers/router/auth"
|
||||
"cargo-erp-backend/internal/handlers/router/city"
|
||||
"cargo-erp-backend/internal/handlers/router/district"
|
||||
"cargo-erp-backend/internal/handlers/router/province"
|
||||
"cargo-erp-backend/internal/middleware"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
@ -107,6 +108,7 @@ func (h *Handlers) Run() {
|
||||
{
|
||||
province.NewProvinceHandler(h.Helper, masterdata).Router()
|
||||
city.NewCityHandler(h.Helper, masterdata).Router()
|
||||
district.NewDistrictHandler(h.Helper, masterdata).Router()
|
||||
}
|
||||
|
||||
h.Helper.Log().Info("Starting Apps")
|
||||
|
||||
281
internal/handlers/router/district/district.go
Normal file
281
internal/handlers/router/district/district.go
Normal file
@ -0,0 +1,281 @@
|
||||
package district
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/handlers/dto"
|
||||
districtimporter "cargo-erp-backend/internal/importers/district"
|
||||
"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 DistrictHandlerInterface interface {
|
||||
Router()
|
||||
}
|
||||
|
||||
type DistrictHandler struct {
|
||||
Helper helpers.HelperInterface
|
||||
Group *gin.RouterGroup
|
||||
}
|
||||
|
||||
func NewDistrictHandler(helper helpers.HelperInterface, g *gin.RouterGroup) DistrictHandlerInterface {
|
||||
return &DistrictHandler{Helper: helper, Group: g}
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) Router() {
|
||||
r := h.Group.Group("districts")
|
||||
{
|
||||
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 *DistrictHandler) 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.DistrictFilterAllRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
u := usecases.NewDistrictUsecase(h.Helper, *userid)
|
||||
districts, _, err := u.GetAll(req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO = make([]dto.CreateDistrictResponse, 0)
|
||||
for _, v := range districts {
|
||||
var DTO dto.CreateDistrictResponse
|
||||
h.Helper.MapStructToStruct(v, "json", &DTO, "json")
|
||||
responseDTO = append(responseDTO, DTO)
|
||||
}
|
||||
response.Success(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) 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.NewDistrictUsecase(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 *DistrictHandler) 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.NewDistrictUsecase(h.Helper, *userid)
|
||||
district, err := u.GetByID(id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, "district not found")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, district)
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) Create(c *gin.Context) {
|
||||
var req dto.CreateDistrictRequest
|
||||
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.NewDistrictUsecase(h.Helper, *userid)
|
||||
district, err := u.Create(req.Name, req.ProvinceID, req.CityID, createdBy, merchantid)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO dto.CreateDistrictResponse
|
||||
h.Helper.MapStructToStruct(district, "json", &responseDTO, "json")
|
||||
response.Created(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var req dto.UpdateDistrictRequest
|
||||
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.NewDistrictUsecase(h.Helper, *userid)
|
||||
district, err := u.Update(id, req.Name, req.ProvinceID, req.CityID, updatedBy)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
var responseDTO dto.CreateDistrictResponse
|
||||
h.Helper.MapStructToStruct(district, "json", &responseDTO, "json")
|
||||
response.Success(c, responseDTO)
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) 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.NewDistrictUsecase(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": "district deleted"})
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) Template(c *gin.Context) {
|
||||
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
handler := districtimporter.NewDistrictImportHandler(*userid, h.Helper)
|
||||
imp := importer.NewImporter(h.Helper, handler)
|
||||
imp.ServeTemplate(c.Writer)
|
||||
}
|
||||
|
||||
func (h *DistrictHandler) 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 := districtimporter.NewDistrictImportHandler(*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.ImportDistrictResponse{
|
||||
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 *DistrictHandler) 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 := districtimporter.NewDistrictImportHandler(*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 *DistrictHandler) 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 := districtimporter.NewDistrictImportHandler(*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"})
|
||||
}
|
||||
122
internal/importers/district/importer.go
Normal file
122
internal/importers/district/importer.go
Normal file
@ -0,0 +1,122 @@
|
||||
package district
|
||||
|
||||
import (
|
||||
"cargo-erp-backend/internal/domain"
|
||||
"cargo-erp-backend/pkg/helpers"
|
||||
"cargo-erp-backend/pkg/importer"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DistrictImportHandler struct {
|
||||
UserData domain.User
|
||||
Helper helpers.HelperInterface
|
||||
lastProvinceName string
|
||||
lastCityName string
|
||||
}
|
||||
|
||||
func NewDistrictImportHandler(userData domain.User, helper helpers.HelperInterface) importer.ImportHandler {
|
||||
return &DistrictImportHandler{
|
||||
UserData: userData,
|
||||
Helper: helper,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DistrictImportHandler) ValidateRow(row []string, rowNumber int) (importer.RowData, []error) {
|
||||
var errors []error
|
||||
|
||||
if len(row) < 3 {
|
||||
errors = append(errors, fmt.Errorf("row must have 3 columns: 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"))
|
||||
}
|
||||
|
||||
cityName := strings.TrimSpace(row[1])
|
||||
if cityName == "" {
|
||||
errors = append(errors, fmt.Errorf("city_name is required"))
|
||||
}
|
||||
|
||||
provinceName := strings.TrimSpace(row[2])
|
||||
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
|
||||
}
|
||||
|
||||
h.lastProvinceName = provinceName
|
||||
h.lastCityName = cityName
|
||||
|
||||
now := time.Now()
|
||||
district := &domain.District{
|
||||
Name: &name,
|
||||
ProvinceID: &province.ID,
|
||||
CityID: &city.ID,
|
||||
MerchantID: h.UserData.MerchantID,
|
||||
CreatedBy: &h.UserData.ID,
|
||||
CreatedOn: &now,
|
||||
UpdatedBy: &h.UserData.ID,
|
||||
UpdatedOn: &now,
|
||||
}
|
||||
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func (h *DistrictImportHandler) GetDataString(data importer.RowData) string {
|
||||
district := data.(*domain.District)
|
||||
name := ""
|
||||
if district.Name != nil {
|
||||
name = *district.Name
|
||||
}
|
||||
return fmt.Sprintf("%s, %s, %s", name, h.lastCityName, h.lastProvinceName)
|
||||
}
|
||||
|
||||
func (h *DistrictImportHandler) IsDuplicate(db *gorm.DB, data importer.RowData) bool {
|
||||
district := data.(*domain.District)
|
||||
var count int64
|
||||
db.Model(&domain.District{}).
|
||||
Joins("JOIN city ON district.city_id = city.id").
|
||||
Joins("JOIN province ON district.province_id = province.id").
|
||||
Where("UPPER(district.name) = ? AND UPPER(city.name) = ? AND UPPER(province.name) = ?",
|
||||
strings.ToUpper(*district.Name), strings.ToUpper(h.lastCityName), strings.ToUpper(h.lastProvinceName)).
|
||||
Count(&count)
|
||||
return count > 0
|
||||
}
|
||||
|
||||
func (h *DistrictImportHandler) GetTemplateHeaders() []string {
|
||||
return []string{"name", "city_name", "province_name"}
|
||||
}
|
||||
|
||||
func (h *DistrictImportHandler) GetTemplateRows() [][]string {
|
||||
return [][]string{
|
||||
{"Kebayoran Baru", "Jakarta Pusat", "DKI Jakarta"},
|
||||
{"Menteng", "Jakarta Pusat", "DKI Jakarta"},
|
||||
{"Bandung Wetan", "Bandung", "Jawa Barat"},
|
||||
{"Coblong", "Bandung", "Jawa Barat"},
|
||||
}
|
||||
}
|
||||
160
internal/usecases/district.go
Normal file
160
internal/usecases/district.go
Normal file
@ -0,0 +1,160 @@
|
||||
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 DistrictUsecaseInterface interface {
|
||||
GetAll(filter dto.DistrictFilterAllRequest) ([]domain.District, int64, error)
|
||||
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||
GetByID(id string) (domain.District, error)
|
||||
Create(name string, provinceID string, cityID string, createdBy string, merchantid *string) (domain.District, error)
|
||||
Update(id string, name string, provinceID string, cityID string, updatedBy string) (domain.District, error)
|
||||
Delete(id string) error
|
||||
}
|
||||
|
||||
type DistrictUsecase struct {
|
||||
Helper helpers.HelperInterface
|
||||
AuthUser domain.User
|
||||
}
|
||||
|
||||
func NewDistrictUsecase(helper helpers.HelperInterface, authUser domain.User) DistrictUsecaseInterface {
|
||||
return &DistrictUsecase{Helper: helper, AuthUser: authUser}
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) GetAll(filter dto.DistrictFilterAllRequest) ([]domain.District, int64, error) {
|
||||
var districts []domain.District
|
||||
var total int64
|
||||
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Model(&districts)
|
||||
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.District{}).Count(&total)
|
||||
tx.Order("name ASC")
|
||||
if err := tx.Find(&districts).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return districts, total, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
|
||||
var response dto.DataTableResponse
|
||||
db := u.Helper.GetDB("slave")
|
||||
tx := db.Table("district").
|
||||
Joins("LEFT JOIN city ON district.city_id=city.id").
|
||||
Joins("LEFT JOIN province ON district.province_id=province.id").
|
||||
Joins("LEFT JOIN merchant ON district.merchant_id=merchant.id")
|
||||
dt := datatable.NewDatatable(tx, req)
|
||||
coldef := make([]dto.DataTableColDef, 0)
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "district.name",
|
||||
Alias: "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: "district.province_id",
|
||||
Alias: "province_id",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "district.city_id",
|
||||
Alias: "city_id",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "merchant.id",
|
||||
Alias: "merchant_id",
|
||||
})
|
||||
coldef = append(coldef, dto.DataTableColDef{
|
||||
Field: "district.id",
|
||||
Alias: "id",
|
||||
})
|
||||
|
||||
response = dt.Render(coldef)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) GetByID(id string) (domain.District, error) {
|
||||
var district domain.District
|
||||
db := u.Helper.GetDB("slave")
|
||||
if err := db.Where("id = ?", id).First(&district).Error; err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) Create(name string, provinceID string, cityID string, createdBy string, merchantid *string) (domain.District, error) {
|
||||
now := time.Now()
|
||||
district := domain.District{
|
||||
Name: &name,
|
||||
ProvinceID: &provinceID,
|
||||
CityID: &cityID,
|
||||
MerchantID: merchantid,
|
||||
CreatedBy: &createdBy,
|
||||
CreatedOn: &now,
|
||||
UpdatedBy: &createdBy,
|
||||
UpdatedOn: &now,
|
||||
}
|
||||
|
||||
db := u.Helper.GetDB("master")
|
||||
if err := db.Create(&district).Error; err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) Update(id string, name string, provinceID string, cityID string, updatedBy string) (domain.District, error) {
|
||||
var district domain.District
|
||||
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(&district).Error; err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
district.Name = &name
|
||||
district.ProvinceID = &provinceID
|
||||
district.CityID = &cityID
|
||||
district.UpdatedBy = &updatedBy
|
||||
district.UpdatedOn = &now
|
||||
|
||||
if err := db.Save(&district).Error; err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func (u *DistrictUsecase) 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.District{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -35,17 +35,23 @@ func (d *Datatable) Render(coldef []dto.DataTableColDef) dto.DataTableResponse {
|
||||
}
|
||||
d.DB.Select(selectAlias)
|
||||
//global filter
|
||||
var g *gorm.DB
|
||||
is_filtering := false
|
||||
if len(d.Req.Search.Value) > 0 {
|
||||
for _, vcol := range d.Req.Columns {
|
||||
if vcol.Searchable {
|
||||
for _, v := range coldef {
|
||||
if v.Alias == vcol.Data {
|
||||
d.DB.Or(fmt.Sprintf("%v::TEXT ILIKE '%%%v%%'", v.Field, d.Req.Search.Value))
|
||||
g.Or(fmt.Sprintf("%v::TEXT ILIKE '%%%v%%'", v.Field, d.Req.Search.Value))
|
||||
is_filtering = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if is_filtering {
|
||||
d.DB.Where(g)
|
||||
}
|
||||
//order
|
||||
if len(d.Req.Order) > 0 {
|
||||
for _, vOrder := range d.Req.Order {
|
||||
@ -60,6 +66,16 @@ func (d *Datatable) Render(coldef []dto.DataTableColDef) dto.DataTableResponse {
|
||||
}
|
||||
}
|
||||
}
|
||||
//order
|
||||
if len(d.Req.AdditionalFilter) > 0 {
|
||||
for k, vFilter := range d.Req.AdditionalFilter {
|
||||
for _, v := range coldef {
|
||||
if v.Alias == k {
|
||||
d.DB.Where(fmt.Sprintf("%v=?", v.Field), vFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var totalFiltered int64 = 0
|
||||
d.DB.Count(&totalFiltered)
|
||||
|
||||
@ -898,3 +898,19 @@
|
||||
{"level":"info","ts":"2026-08-18T15:06:06.979+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNDEwNTksImlhdCI6MTc4NzAzNzQ1OX0.YySp6YT6H0YXQg7XOSzwMvXYUzM15BTJAyNLtI8P3UI"}
|
||||
{"level":"info","ts":"2026-08-18T15:06:07.107+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-18T15:06:07.449+0700","caller":"handlers/handlers.go:67","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/import/status/efdbf19b-c71c-4c11-b160-2f82cff26fe4","query":"","ip":"127.0.0.1","latency":0.477752042,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:27.700+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.050+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.051+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.357+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.604+0700","caller":"handlers/handlers.go:114","msg":"Starting Apps"}
|
||||
{"level":"warn","ts":"2026-08-18T20:22:01.234+0700","caller":"handlers/handlers.go:66","msg":"Client Error","status":401,"method":"POST","path":"/master-data/provinces/list","query":"search=bandung&page=1&per_page=25&sort_by=name&sort_order=asc","ip":"127.0.0.1","latency":0.012759292,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||
{"level":"info","ts":"2026-08-18T20:22:53.527+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"POST","path":"/login","query":"","ip":"127.0.0.1","latency":8.082321709,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:08.809+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:09.804+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:23:15.870+0700","caller":"handlers/handlers.go:68","msg":"Request Success","status":200,"method":"POST","path":"/master-data/provinces/list","query":"","ip":"127.0.0.1","latency":7.060838208,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:44.621+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODcwNjI5NjYsImlhdCI6MTc4NzA1OTM2Nn0.xctXhU-k0oCqTfjGVUPaCuS0hdyK542X96Za0_Fw4LM"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:44.990+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:23:45.645+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.02558925,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||
{"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: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)"}
|
||||
|
||||
@ -3564,3 +3564,20 @@
|
||||
{"level":"info","ts":"2026-08-18T13:40:54.060+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/pkg/importer/importer.go:368","elapsed":0.185293792,"rows":1,"sql":"INSERT INTO \"province\" (\"name\",\"created_by\",\"created_on\",\"updated_by\",\"updated_on\",\"merchant_id\") VALUES ('DKI Jakarta','19ff104c16522a2252cbaca24d','2026-08-18 13:40:52.85','19ff104c16522a2252cbaca24d','2026-08-18 13:40:52.85','19ff111bca6c2c382d9eb43b3c') RETURNING \"id\""}
|
||||
{"level":"info","ts":"2026-08-18T14:20:47.856+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/auth.go:29","elapsed":0.071815875,"rows":1,"sql":"SELECT * FROM \"users_roles\" WHERE \"users_roles\".\"id\" = '19fe814c5350d67814c3e6057c'"}
|
||||
{"level":"info","ts":"2026-08-18T14:20:47.858+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/auth.go:29","elapsed":0.187898958,"rows":1,"sql":"SELECT * FROM \"users\" WHERE email='gcx@gmail.com'"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.358+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.358+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.478+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.478+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.478+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||
{"level":"info","ts":"2026-08-18T16:47:28.604+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||
{"level":"info","ts":"2026-08-18T20:22:46.868+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/auth.go:29","elapsed":0.231675917,"rows":1,"sql":"SELECT * FROM \"users_roles\" WHERE \"users_roles\".\"id\" = '19fe814c5350d67814c3e6057c'"}
|
||||
{"level":"info","ts":"2026-08-18T20:22:46.871+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/auth.go:29","elapsed":1.409850667,"rows":1,"sql":"SELECT * FROM \"users\" WHERE email='gcx@gmail.com'"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:12.478+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":2.669297834,"rows":1,"sql":"SELECT count(*) FROM \"province\" LEFT JOIN merchant ON province.merchant_id=merchant.id"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:14.421+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":1.940319541,"rows":1,"sql":"SELECT count(*) FROM \"province\" LEFT JOIN merchant ON province.merchant_id=merchant.id"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:15.869+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":1.447366667,"rows":10,"sql":"SELECT province.name AS name,merchant.id AS merchant_id,province.id AS id FROM \"province\" LEFT JOIN merchant ON province.merchant_id=merchant.id ORDER BY province.name ASC LIMIT 10"}
|
||||
{"level":"info","ts":"2026-08-18T20:23:45.149+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.150725916,"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:23:45.203+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.052747083,"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:23:45.644+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.441160666,"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: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: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"}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user