This commit is contained in:
parent
1783bb2e7d
commit
fc0d140c5c
@ -5,10 +5,34 @@ type CreateProvinceRequest struct {
|
|||||||
}
|
}
|
||||||
type CreateProvinceResponse struct {
|
type CreateProvinceResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name *string `json:"name"`
|
||||||
MerchantID *string `json:"merchant_id"`
|
MerchantID *string `json:"merchant_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProvinceFilterAllRequest struct {
|
||||||
|
ID string `json:"id" form:"id"`
|
||||||
|
Name string `json:"name" form:"name"`
|
||||||
|
MerchantID string `json:"merchant_id" form:"merchant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
type UpdateProvinceRequest struct {
|
type UpdateProvinceRequest struct {
|
||||||
Name string `json:"name" binding:"required,min=2"`
|
Name string `json:"name" binding:"required,min=2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImportLog struct {
|
||||||
|
Row int `json:"row"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportProvinceResponse 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"`
|
||||||
|
}
|
||||||
|
|||||||
@ -2,11 +2,12 @@ package province
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"cargo-erp-backend/internal/handlers/dto"
|
"cargo-erp-backend/internal/handlers/dto"
|
||||||
|
provinceimporter "cargo-erp-backend/internal/importers/province"
|
||||||
"cargo-erp-backend/internal/usecases"
|
"cargo-erp-backend/internal/usecases"
|
||||||
"cargo-erp-backend/pkg/helpers"
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"cargo-erp-backend/pkg/importer"
|
||||||
"cargo-erp-backend/pkg/response"
|
"cargo-erp-backend/pkg/response"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@ -33,6 +34,9 @@ func (h *ProvinceHandler) Router() {
|
|||||||
r.POST("/", h.Create)
|
r.POST("/", h.Create)
|
||||||
r.PUT("/:id", h.Update)
|
r.PUT("/:id", h.Update)
|
||||||
r.DELETE("/:id", h.Delete)
|
r.DELETE("/:id", h.Delete)
|
||||||
|
r.GET("/template", h.Template)
|
||||||
|
r.POST("/import", h.Import)
|
||||||
|
r.GET("/import/status/:jobId", h.ImportStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,24 +46,24 @@ func (h *ProvinceHandler) GetAll(c *gin.Context) {
|
|||||||
response.Error(c, http.StatusUnauthorized, err.Error())
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
var req dto.ProvinceFilterAllRequest
|
||||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
if err := c.ShouldBindQuery(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
if page < 1 {
|
return
|
||||||
page = 1
|
|
||||||
}
|
}
|
||||||
if limit < 1 {
|
|
||||||
limit = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
u := usecases.NewProvinceUsecase(h.Helper, *userid)
|
u := usecases.NewProvinceUsecase(h.Helper, *userid)
|
||||||
provinces, total, err := u.GetAll(page, limit)
|
provinces, _, err := u.GetAll(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var responseDTO = make([]dto.CreateProvinceResponse, 0)
|
||||||
response.PaginatedResponse(c, provinces, int(total), page, limit)
|
for _, v := range provinces {
|
||||||
|
var DTO dto.CreateProvinceResponse
|
||||||
|
h.Helper.MapStructToStruct(v, "json", &DTO, "json")
|
||||||
|
responseDTO = append(responseDTO, DTO)
|
||||||
|
}
|
||||||
|
response.Success(c, responseDTO)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ProvinceHandler) GetList(c *gin.Context) {
|
func (h *ProvinceHandler) GetList(c *gin.Context) {
|
||||||
@ -70,8 +74,6 @@ func (h *ProvinceHandler) GetList(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var req dto.DataTableRequest
|
var req dto.DataTableRequest
|
||||||
|
|
||||||
// 1. Bind JSON request otomatis ke struct
|
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
response.Error(c, http.StatusBadRequest, "Request Format request invalid")
|
||||||
return
|
return
|
||||||
@ -153,8 +155,9 @@ func (h *ProvinceHandler) Update(c *gin.Context) {
|
|||||||
response.Error(c, http.StatusInternalServerError, err.Error())
|
response.Error(c, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var responseDTO dto.CreateProvinceResponse
|
||||||
response.Success(c, province)
|
h.Helper.MapStructToStruct(province, "json", &responseDTO, "json")
|
||||||
|
response.Success(c, responseDTO)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ProvinceHandler) Delete(c *gin.Context) {
|
func (h *ProvinceHandler) Delete(c *gin.Context) {
|
||||||
@ -172,3 +175,82 @@ func (h *ProvinceHandler) Delete(c *gin.Context) {
|
|||||||
|
|
||||||
response.Success(c, map[string]interface{}{"message": "province deleted"})
|
response.Success(c, map[string]interface{}{"message": "province deleted"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceHandler) Template(c *gin.Context) {
|
||||||
|
userid, err := h.Helper.GetAuthInfo(c.GetString("auth"))
|
||||||
|
if err != nil {
|
||||||
|
response.Error(c, http.StatusUnauthorized, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handler := provinceimporter.NewProvinceImportHandler(*userid)
|
||||||
|
imp := importer.NewImporter(h.Helper, handler)
|
||||||
|
imp.ServeTemplate(c.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceHandler) 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 := provinceimporter.NewProvinceImportHandler(*userid)
|
||||||
|
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.ImportProvinceResponse{
|
||||||
|
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 *ProvinceHandler) 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 := provinceimporter.NewProvinceImportHandler(*userid)
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
84
internal/importers/province/importer.go
Normal file
84
internal/importers/province/importer.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package province
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cargo-erp-backend/internal/domain"
|
||||||
|
"cargo-erp-backend/pkg/importer"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProvinceImportHandler struct {
|
||||||
|
UserData domain.User
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProvinceImportHandler(user_data domain.User) importer.ImportHandler {
|
||||||
|
return &ProvinceImportHandler{
|
||||||
|
UserData: user_data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceImportHandler) ValidateRow(row []string, rowNumber int) (importer.RowData, []error) {
|
||||||
|
var errors []error
|
||||||
|
|
||||||
|
if len(row) < 1 {
|
||||||
|
errors = append(errors, fmt.Errorf("row is empty"))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.TrimSpace(row[0])
|
||||||
|
if name == "" {
|
||||||
|
errors = append(errors, fmt.Errorf("name is required"))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(name) < 2 {
|
||||||
|
errors = append(errors, fmt.Errorf("name must be at least 2 characters"))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(name) > 255 {
|
||||||
|
errors = append(errors, fmt.Errorf("name must be at most 255 characters"))
|
||||||
|
return nil, errors
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
province := &domain.Province{
|
||||||
|
MerchantID: h.UserData.MerchantID,
|
||||||
|
Name: &name,
|
||||||
|
CreatedOn: &now,
|
||||||
|
UpdatedOn: &now,
|
||||||
|
}
|
||||||
|
|
||||||
|
return province, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceImportHandler) GetDataString(data importer.RowData) string {
|
||||||
|
province := data.(*domain.Province)
|
||||||
|
if province.Name != nil {
|
||||||
|
return *province.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceImportHandler) IsDuplicate(db *gorm.DB, data importer.RowData) bool {
|
||||||
|
province := data.(*domain.Province)
|
||||||
|
var count int64
|
||||||
|
db.Model(&domain.Province{}).Where("UPPER(name) = ?", strings.ToUpper(*province.Name)).Count(&count)
|
||||||
|
return count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceImportHandler) GetTemplateHeaders() []string {
|
||||||
|
return []string{"name"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ProvinceImportHandler) GetTemplateRows() [][]string {
|
||||||
|
return [][]string{
|
||||||
|
{"DKI Jakarta"},
|
||||||
|
{"Jawa Barat"},
|
||||||
|
{"Jawa Tengah"},
|
||||||
|
{"Jawa Timur"},
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,11 +5,13 @@ import (
|
|||||||
"cargo-erp-backend/internal/handlers/dto"
|
"cargo-erp-backend/internal/handlers/dto"
|
||||||
"cargo-erp-backend/pkg/datatable"
|
"cargo-erp-backend/pkg/datatable"
|
||||||
"cargo-erp-backend/pkg/helpers"
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProvinceUsecaseInterface interface {
|
type ProvinceUsecaseInterface interface {
|
||||||
GetAll(page int, limit int) ([]domain.Province, int64, error)
|
GetAll(filter dto.ProvinceFilterAllRequest) ([]domain.Province, int64, error)
|
||||||
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
|
||||||
GetByID(id string) (domain.Province, error)
|
GetByID(id string) (domain.Province, error)
|
||||||
Create(name string, createdBy string, merchantid *string) (domain.Province, error)
|
Create(name string, createdBy string, merchantid *string) (domain.Province, error)
|
||||||
@ -26,21 +28,29 @@ func NewProvinceUsecase(helper helpers.HelperInterface, authUser domain.User) Pr
|
|||||||
return &ProvinceUsecase{Helper: helper, AuthUser: authUser}
|
return &ProvinceUsecase{Helper: helper, AuthUser: authUser}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *ProvinceUsecase) GetAll(page int, limit int) ([]domain.Province, int64, error) {
|
func (u *ProvinceUsecase) GetAll(filter dto.ProvinceFilterAllRequest) ([]domain.Province, int64, error) {
|
||||||
var provinces []domain.Province
|
var provinces []domain.Province
|
||||||
var total int64
|
var total int64
|
||||||
|
|
||||||
db := u.Helper.GetDB("slave")
|
db := u.Helper.GetDB("slave")
|
||||||
|
tx := db.Model(&provinces)
|
||||||
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
if u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
|
||||||
db.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
|
||||||
}
|
}
|
||||||
db.Model(&domain.Province{}).Count(&total)
|
v := reflect.ValueOf(filter)
|
||||||
|
t := reflect.TypeOf(filter)
|
||||||
|
|
||||||
offset := (page - 1) * limit
|
for i := 0; i < v.NumField(); i++ {
|
||||||
if err := db.Offset(offset).Limit(limit).Find(&provinces).Error; err != nil {
|
if v.Field(i).String() != "" {
|
||||||
|
tagKey := t.Field(i).Tag.Get("form")
|
||||||
|
tx.Where(fmt.Sprintf("%v=?", tagKey), v.Field(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tx.Model(&domain.Province{}).Count(&total)
|
||||||
|
tx.Order("name ASC")
|
||||||
|
if err := tx.Find(&provinces).Error; err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return provinces, total, nil
|
return provinces, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
90
pkg/csv/csv.go
Normal file
90
pkg/csv/csv.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package csv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RowHandler func(row []string, rowNumber int) error
|
||||||
|
|
||||||
|
func ReadCSV(file io.Reader, handler RowHandler) (int, []string, error) {
|
||||||
|
reader := csv.NewReader(file)
|
||||||
|
reader.LazyQuotes = true
|
||||||
|
reader.TrimLeadingSpace = true
|
||||||
|
|
||||||
|
var errors []string
|
||||||
|
rowNumber := 0
|
||||||
|
totalRows := 0
|
||||||
|
|
||||||
|
for {
|
||||||
|
row, err := reader.Read()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
rowNumber++
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errors = append(errors, "Row "+itoa(rowNumber)+": "+err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip empty rows
|
||||||
|
if len(row) == 0 || (len(row) == 1 && strings.TrimSpace(row[0]) == "") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip header row (first row)
|
||||||
|
if rowNumber == 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := handler(row, rowNumber); err != nil {
|
||||||
|
errors = append(errors, "Row "+itoa(rowNumber)+": "+err.Error())
|
||||||
|
}
|
||||||
|
totalRows++
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalRows, errors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CountRows(file io.Reader) (int, error) {
|
||||||
|
reader := csv.NewReader(file)
|
||||||
|
count := 0
|
||||||
|
for {
|
||||||
|
_, err := reader.Read()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteCSV(headers []string, rows [][]string) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
writer := csv.NewWriter(&sb)
|
||||||
|
|
||||||
|
writer.Write(headers)
|
||||||
|
for _, row := range rows {
|
||||||
|
writer.Write(row)
|
||||||
|
}
|
||||||
|
writer.Flush()
|
||||||
|
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func itoa(i int) string {
|
||||||
|
if i == 0 {
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
result := ""
|
||||||
|
for i > 0 {
|
||||||
|
result = string(rune('0'+i%10)) + result
|
||||||
|
i /= 10
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
389
pkg/importer/importer.go
Normal file
389
pkg/importer/importer.go
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
package importer
|
||||||
|
|
||||||
|
import (
|
||||||
|
csvlib "cargo-erp-backend/pkg/csv"
|
||||||
|
"cargo-erp-backend/pkg/helpers"
|
||||||
|
"cargo-erp-backend/pkg/jobqueue"
|
||||||
|
"context"
|
||||||
|
"encoding/csv"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RowData interface {
|
||||||
|
TableName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportHandler interface {
|
||||||
|
ValidateRow(row []string, rowNumber int) (RowData, []error)
|
||||||
|
IsDuplicate(db *gorm.DB, data RowData) bool
|
||||||
|
GetDataString(data RowData) string
|
||||||
|
GetTemplateHeaders() []string
|
||||||
|
GetTemplateRows() [][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportLog struct {
|
||||||
|
Row int `json:"row"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportResult 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Importer struct {
|
||||||
|
Helper helpers.HelperInterface
|
||||||
|
Handler ImportHandler
|
||||||
|
JobQ *jobqueue.JobQueue
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewImporter(helper helpers.HelperInterface, handler ImportHandler) *Importer {
|
||||||
|
return &Importer{
|
||||||
|
Helper: helper,
|
||||||
|
Handler: handler,
|
||||||
|
JobQ: jobqueue.NewJobQueue(helper.GetRedis("master")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) Process(file io.Reader, userID string, filename string) (*ImportResult, error) {
|
||||||
|
if !strings.HasSuffix(strings.ToLower(filename), ".csv") {
|
||||||
|
return nil, fmt.Errorf("file must be .csv format")
|
||||||
|
}
|
||||||
|
|
||||||
|
headerErr := i.validateHeaders(file)
|
||||||
|
if headerErr != nil {
|
||||||
|
return nil, headerErr
|
||||||
|
}
|
||||||
|
|
||||||
|
rowCount, err := csvlib.CountRows(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to count rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rowCount <= 1 {
|
||||||
|
return &ImportResult{
|
||||||
|
TotalRows: 0,
|
||||||
|
Imported: 0,
|
||||||
|
Skipped: 0,
|
||||||
|
Logs: []ImportLog{},
|
||||||
|
Errors: []string{"CSV file is empty or has only headers"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDataRows := rowCount - 1
|
||||||
|
|
||||||
|
if totalDataRows >= 10000 {
|
||||||
|
return i.processAsync(file, userID, totalDataRows)
|
||||||
|
}
|
||||||
|
|
||||||
|
return i.processSync(file, userID, totalDataRows)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) validateHeaders(file io.Reader) error {
|
||||||
|
reader := csv.NewReader(file)
|
||||||
|
header, err := reader.Read()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read CSV headers: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedHeaders := i.Handler.GetTemplateHeaders()
|
||||||
|
|
||||||
|
if len(header) != len(expectedHeaders) {
|
||||||
|
return fmt.Errorf("invalid CSV headers. Expected: %s. Got: %s",
|
||||||
|
strings.Join(expectedHeaders, ", "),
|
||||||
|
strings.Join(header, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, h := range header {
|
||||||
|
if strings.TrimSpace(strings.ToLower(h)) != strings.TrimSpace(strings.ToLower(expectedHeaders[idx])) {
|
||||||
|
return fmt.Errorf("invalid CSV headers. Expected: %s. Got: %s",
|
||||||
|
strings.Join(expectedHeaders, ", "),
|
||||||
|
strings.Join(header, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) processSync(file io.Reader, userID string, totalRows int) (*ImportResult, error) {
|
||||||
|
db := i.Helper.GetDB("master")
|
||||||
|
|
||||||
|
var imported, skipped int
|
||||||
|
var logs []ImportLog
|
||||||
|
var errors []string
|
||||||
|
var batch []RowData
|
||||||
|
batchSize := 500
|
||||||
|
|
||||||
|
csvlib.ReadCSV(file, func(row []string, rowNumber int) error {
|
||||||
|
data, rowErrors := i.Handler.ValidateRow(row, rowNumber)
|
||||||
|
if len(rowErrors) > 0 {
|
||||||
|
for _, e := range rowErrors {
|
||||||
|
errorMsg := fmt.Sprintf("Row %d: %s", rowNumber, e.Error())
|
||||||
|
errors = append(errors, errorMsg)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "error",
|
||||||
|
Data: strings.Join(row, ","),
|
||||||
|
Message: errorMsg,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
skipped++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Handler.IsDuplicate(db, data) {
|
||||||
|
dataStr := i.Handler.GetDataString(data)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "skipped",
|
||||||
|
Data: dataStr,
|
||||||
|
Message: fmt.Sprintf("Row %d: '%s' already exists, skipped", rowNumber, dataStr),
|
||||||
|
})
|
||||||
|
skipped++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
batch = append(batch, data)
|
||||||
|
if len(batch) >= batchSize {
|
||||||
|
if err := i.insertBatch(db, batch); err != nil {
|
||||||
|
errorMsg := fmt.Sprintf("Batch insert error: %v", err)
|
||||||
|
errors = append(errors, errorMsg)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "error",
|
||||||
|
Data: strings.Join(row, ","),
|
||||||
|
Message: errorMsg,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
for _, b := range batch {
|
||||||
|
dataStr := i.Handler.GetDataString(b)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "inserted",
|
||||||
|
Data: dataStr,
|
||||||
|
Message: fmt.Sprintf("Row %d: '%s' inserted successfully", rowNumber, dataStr),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
imported += len(batch)
|
||||||
|
}
|
||||||
|
batch = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(batch) > 0 {
|
||||||
|
if err := i.insertBatch(db, batch); err != nil {
|
||||||
|
errorMsg := fmt.Sprintf("Batch insert error: %v", err)
|
||||||
|
errors = append(errors, errorMsg)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: totalRows + 1,
|
||||||
|
Status: "error",
|
||||||
|
Data: "",
|
||||||
|
Message: errorMsg,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
for _, b := range batch {
|
||||||
|
dataStr := i.Handler.GetDataString(b)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: imported + 1,
|
||||||
|
Status: "inserted",
|
||||||
|
Data: dataStr,
|
||||||
|
Message: fmt.Sprintf("'%s' inserted successfully", dataStr),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
imported += len(batch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ImportResult{
|
||||||
|
TotalRows: totalRows,
|
||||||
|
Imported: imported,
|
||||||
|
Skipped: skipped,
|
||||||
|
Logs: logs,
|
||||||
|
Errors: errors,
|
||||||
|
IsAsync: false,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) processAsync(file io.Reader, userID string, totalRows int) (*ImportResult, error) {
|
||||||
|
jobID := uuid.New().String()
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
metadata := map[string]string{
|
||||||
|
"user_id": userID,
|
||||||
|
"table": i.Handler.GetTemplateHeaders()[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := i.JobQ.CreateJob(ctx, jobID, totalRows, metadata); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create job: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go i.processAsyncWorker(file, jobID, userID, totalRows)
|
||||||
|
|
||||||
|
return &ImportResult{
|
||||||
|
JobID: jobID,
|
||||||
|
TotalRows: totalRows,
|
||||||
|
IsAsync: true,
|
||||||
|
Message: fmt.Sprintf("Import started. Poll /import/status/%s for progress.", jobID),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) processAsyncWorker(file io.Reader, jobID string, userID string, totalRows int) {
|
||||||
|
db := i.Helper.GetDB("master")
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var imported, skipped int
|
||||||
|
var logs []ImportLog
|
||||||
|
var errors []string
|
||||||
|
var batch []RowData
|
||||||
|
batchSize := 500
|
||||||
|
|
||||||
|
i.JobQ.UpdateProgress(ctx, jobID, 0, 0, nil)
|
||||||
|
|
||||||
|
csvlib.ReadCSV(file, func(row []string, rowNumber int) error {
|
||||||
|
data, rowErrors := i.Handler.ValidateRow(row, rowNumber)
|
||||||
|
if len(rowErrors) > 0 {
|
||||||
|
for _, e := range rowErrors {
|
||||||
|
errorMsg := fmt.Sprintf("Row %d: %s", rowNumber, e.Error())
|
||||||
|
errors = append(errors, errorMsg)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "error",
|
||||||
|
Data: strings.Join(row, ","),
|
||||||
|
Message: errorMsg,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
skipped++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Handler.IsDuplicate(db, data) {
|
||||||
|
dataStr := i.Handler.GetDataString(data)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "skipped",
|
||||||
|
Data: dataStr,
|
||||||
|
Message: fmt.Sprintf("Row %d: '%s' already exists, skipped", rowNumber, dataStr),
|
||||||
|
})
|
||||||
|
skipped++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
batch = append(batch, data)
|
||||||
|
if len(batch) >= batchSize {
|
||||||
|
if err := i.insertBatch(db, batch); err != nil {
|
||||||
|
errorMsg := fmt.Sprintf("Batch insert error: %v", err)
|
||||||
|
errors = append(errors, errorMsg)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "error",
|
||||||
|
Data: strings.Join(row, ","),
|
||||||
|
Message: errorMsg,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
for _, b := range batch {
|
||||||
|
dataStr := i.Handler.GetDataString(b)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: rowNumber,
|
||||||
|
Status: "inserted",
|
||||||
|
Data: dataStr,
|
||||||
|
Message: fmt.Sprintf("Row %d: '%s' inserted successfully", rowNumber, dataStr),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
imported += len(batch)
|
||||||
|
}
|
||||||
|
batch = nil
|
||||||
|
i.saveJobLogs(ctx, jobID, logs, imported, skipped, errors)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(batch) > 0 {
|
||||||
|
if err := i.insertBatch(db, batch); err != nil {
|
||||||
|
errorMsg := fmt.Sprintf("Batch insert error: %v", err)
|
||||||
|
errors = append(errors, errorMsg)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: totalRows + 1,
|
||||||
|
Status: "error",
|
||||||
|
Data: "",
|
||||||
|
Message: errorMsg,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
for _, b := range batch {
|
||||||
|
dataStr := i.Handler.GetDataString(b)
|
||||||
|
logs = append(logs, ImportLog{
|
||||||
|
Row: imported + 1,
|
||||||
|
Status: "inserted",
|
||||||
|
Data: dataStr,
|
||||||
|
Message: fmt.Sprintf("'%s' inserted successfully", dataStr),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
imported += len(batch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i.JobQ.CompleteJob(ctx, jobID, imported, skipped, errors)
|
||||||
|
i.saveJobLogs(ctx, jobID, logs, imported, skipped, errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) saveJobLogs(ctx context.Context, jobID string, logs []ImportLog, imported int, skipped int, errors []string) {
|
||||||
|
logsJSON, _ := json.Marshal(logs)
|
||||||
|
key := fmt.Sprintf("import_job:%s:logs", jobID)
|
||||||
|
i.Helper.GetRedis("master").Set(ctx, key, logsJSON, 24*time.Hour)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) insertBatch(db *gorm.DB, batch []RowData) error {
|
||||||
|
if len(batch) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.CreateInBatches(batch, 500).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) GetTemplate() string {
|
||||||
|
headers := i.Handler.GetTemplateHeaders()
|
||||||
|
rows := i.Handler.GetTemplateRows()
|
||||||
|
return csvlib.WriteCSV(headers, rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) ServeTemplate(w http.ResponseWriter) {
|
||||||
|
template := i.GetTemplate()
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "text/csv")
|
||||||
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s_template.csv", time.Now().Format("20060102")))
|
||||||
|
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(template)))
|
||||||
|
w.Write([]byte(template))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Importer) GetJobStatus(jobID string) (*jobqueue.Job, []ImportLog, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
job, err := i.JobQ.GetJob(ctx, jobID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var logs []ImportLog
|
||||||
|
key := fmt.Sprintf("import_job:%s:logs", jobID)
|
||||||
|
logsJSON, err := i.Helper.GetRedis("slave").Get(ctx, key).Result()
|
||||||
|
if err == nil {
|
||||||
|
json.Unmarshal([]byte(logsJSON), &logs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return job, logs, nil
|
||||||
|
}
|
||||||
207
pkg/jobqueue/jobqueue.go
Normal file
207
pkg/jobqueue/jobqueue.go
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
package jobqueue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JobStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusPending JobStatus = "pending"
|
||||||
|
StatusProcessing JobStatus = "processing"
|
||||||
|
StatusCompleted JobStatus = "completed"
|
||||||
|
StatusFailed JobStatus = "failed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Job struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Status JobStatus `json:"status"`
|
||||||
|
Total int `json:"total"`
|
||||||
|
Imported int `json:"imported"`
|
||||||
|
Skipped int `json:"skipped"`
|
||||||
|
Progress int `json:"progress"`
|
||||||
|
Errors []string `json:"errors,omitempty"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
FinishedAt *time.Time `json:"finished_at,omitempty"`
|
||||||
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobQueue struct {
|
||||||
|
Redis *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJobQueue(redis *redis.Client) *JobQueue {
|
||||||
|
return &JobQueue{Redis: redis}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jq *JobQueue) CreateJob(ctx context.Context, jobID string, total int, metadata map[string]string) error {
|
||||||
|
key := fmt.Sprintf("import_job:%s", jobID)
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
job := map[string]interface{}{
|
||||||
|
"id": jobID,
|
||||||
|
"status": string(StatusPending),
|
||||||
|
"total": total,
|
||||||
|
"imported": 0,
|
||||||
|
"skipped": 0,
|
||||||
|
"progress": 0,
|
||||||
|
"created_at": now.Format(time.RFC3339),
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata != nil {
|
||||||
|
for k, v := range metadata {
|
||||||
|
job["meta_"+k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := jq.Redis.HSet(ctx, key, job).Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
jq.Redis.Expire(ctx, key, 24*time.Hour)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jq *JobQueue) UpdateProgress(ctx context.Context, jobID string, imported int, skipped int, errors []string) error {
|
||||||
|
key := fmt.Sprintf("import_job:%s", jobID)
|
||||||
|
|
||||||
|
job, err := jq.Redis.HGetAll(ctx, key).Result()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
total := parseInt(job["total"])
|
||||||
|
progress := 0
|
||||||
|
if total > 0 {
|
||||||
|
progress = ((imported + skipped) * 100) / total
|
||||||
|
}
|
||||||
|
|
||||||
|
update := map[string]interface{}{
|
||||||
|
"status": string(StatusProcessing),
|
||||||
|
"imported": imported,
|
||||||
|
"skipped": skipped,
|
||||||
|
"progress": progress,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
update["errors"] = joinErrors(errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return jq.Redis.HSet(ctx, key, update).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jq *JobQueue) CompleteJob(ctx context.Context, jobID string, imported int, skipped int, errors []string) error {
|
||||||
|
key := fmt.Sprintf("import_job:%s", jobID)
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
update := map[string]interface{}{
|
||||||
|
"status": string(StatusCompleted),
|
||||||
|
"imported": imported,
|
||||||
|
"skipped": skipped,
|
||||||
|
"progress": 100,
|
||||||
|
"finished_at": now.Format(time.RFC3339),
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
update["errors"] = joinErrors(errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return jq.Redis.HSet(ctx, key, update).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jq *JobQueue) FailJob(ctx context.Context, jobID string, errMsg string) error {
|
||||||
|
key := fmt.Sprintf("import_job:%s", jobID)
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
return jq.Redis.HSet(ctx, key, map[string]interface{}{
|
||||||
|
"status": string(StatusFailed),
|
||||||
|
"finished_at": now.Format(time.RFC3339),
|
||||||
|
"errors": errMsg,
|
||||||
|
}).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jq *JobQueue) GetJob(ctx context.Context, jobID string) (*Job, error) {
|
||||||
|
key := fmt.Sprintf("import_job:%s", jobID)
|
||||||
|
data, err := jq.Redis.HGetAll(ctx, key).Result()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, fmt.Errorf("job not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
job := &Job{
|
||||||
|
ID: data["id"],
|
||||||
|
Status: JobStatus(data["status"]),
|
||||||
|
Total: parseInt(data["total"]),
|
||||||
|
Imported: parseInt(data["imported"]),
|
||||||
|
Skipped: parseInt(data["skipped"]),
|
||||||
|
Progress: parseInt(data["progress"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
if data["errors"] != "" {
|
||||||
|
job.Errors = splitErrors(data["errors"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, err := time.Parse(time.RFC3339, data["created_at"]); err == nil {
|
||||||
|
job.CreatedAt = t
|
||||||
|
}
|
||||||
|
|
||||||
|
if data["finished_at"] != "" {
|
||||||
|
if t, err := time.Parse(time.RFC3339, data["finished_at"]); err == nil {
|
||||||
|
job.FinishedAt = &t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return job, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jq *JobQueue) DeleteJob(ctx context.Context, jobID string) error {
|
||||||
|
key := fmt.Sprintf("import_job:%s", jobID)
|
||||||
|
return jq.Redis.Del(ctx, key).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInt(s string) int {
|
||||||
|
n := 0
|
||||||
|
for _, c := range s {
|
||||||
|
if c >= '0' && c <= '9' {
|
||||||
|
n = n*10 + int(c-'0')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinErrors(errors []string) string {
|
||||||
|
result := ""
|
||||||
|
for i, e := range errors {
|
||||||
|
if i > 0 {
|
||||||
|
result += "||"
|
||||||
|
}
|
||||||
|
result += e
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitErrors(s string) []string {
|
||||||
|
result := []string{}
|
||||||
|
current := ""
|
||||||
|
for _, c := range s {
|
||||||
|
if c == '|' {
|
||||||
|
if current != "" {
|
||||||
|
result = append(result, current)
|
||||||
|
}
|
||||||
|
current = ""
|
||||||
|
} else {
|
||||||
|
current += string(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if current != "" {
|
||||||
|
result = append(result, current)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@ -687,3 +687,117 @@
|
|||||||
{"level":"info","ts":"2026-08-17T14:21:37.526+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
{"level":"info","ts":"2026-08-17T14:21:37.526+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
{"level":"info","ts":"2026-08-17T14:21:37.550+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-17T14:21:37.550+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-17T14:21:37.621+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":201,"method":"POST","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.095641333,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
{"level":"info","ts":"2026-08-17T14:21:37.621+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":201,"method":"POST","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.095641333,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.586+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.681+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.681+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.752+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.856+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:13.926+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:13.950+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-17T14:25:14.035+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"DELETE","path":"/master-data/provinces/1a00e98ea5f87d9a1026ba6441","query":"","ip":"127.0.0.1","latency":0.1097195,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:32.443+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:32.474+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-17T14:25:32.600+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":201,"method":"POST","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.157767833,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.138+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.281+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.281+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.363+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.481+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.947+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.968+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-17T14:29:02.064+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"PUT","path":"/master-data/provinces/1a00e9c80365466b3d2a04918c","query":"","ip":"127.0.0.1","latency":0.117066958,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.255+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.350+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.350+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.424+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.532+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:34.315+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:34.340+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-17T14:30:34.428+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"PUT","path":"/master-data/provinces/1a00e9c80365466b3d2a04918c","query":"","ip":"127.0.0.1","latency":0.113493,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:32:39.551+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:32:39.592+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-17T14:32:39.657+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"DELETE","path":"/master-data/provinces/1a00e9c80365466b3d2a04918c","query":"","ip":"127.0.0.1","latency":0.108803959,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:27.830+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:27.951+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:27.951+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.024+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.135+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:10.542+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:10.568+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-17T14:39:10.654+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.113548917,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.378+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.470+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.470+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.543+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.656+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:50.136+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:50.160+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-17T14:39:50.234+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.099099792,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:13.477+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTI0NDksImlhdCI6MTc4Njk0ODg0OX0.Zl6rY1vRR7pf7xkq3YU7L2cfNUsth9ZriJ3ANZVh14g"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:13.517+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-17T14:40:13.593+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.117934,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:47.694+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:47.855+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:47.855+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:47.976+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:48.089+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"warn","ts":"2026-08-17T14:40:52.337+0700","caller":"handlers/handlers.go:64","msg":"Client Error","status":401,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.000458083,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:58.800+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"POST","path":"/login","query":"","ip":"127.0.0.1","latency":0.180353416,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:41:02.287+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:41:02.315+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-17T14:41:02.440+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.153650875,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:37.997+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.100+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.100+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.180+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.286+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:40.017+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:40.041+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-17T14:42:40.111+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.0938845,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.312+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.433+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.433+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.513+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.623+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.660+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.681+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-17T14:43:03.742+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"","ip":"127.0.0.1","latency":0.082196166,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:45:05.375+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:45:05.402+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-17T14:45:05.466+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"name=aceh","ip":"127.0.0.1","latency":0.093297541,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.706+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.793+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.794+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.875+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:34.004+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:41.249+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:41.276+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-17T14:59:52.379+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.469+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.469+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.543+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.653+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:56.806+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:56.837+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-17T14:59:56.919+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"name=aceh","ip":"127.0.0.1","latency":0.113733667,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:02:00.031+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:02:00.064+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-17T15:02:00.145+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/","query":"name=ACEH","ip":"127.0.0.1","latency":0.116235959,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.336+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.443+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.443+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.515+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.623+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:29:04.258+0700","caller":"middleware/auth.go:62","msg":"session_login : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIxOWZmMTA0YzE2NTIyYTIyNTJjYmFjYTI0ZCIsImlzcyI6ImNhcmdvLXBsYXRmb3JtIiwic3ViIjoiMTlmZjEwNGMxNjUyMmEyMjUyY2JhY2EyNGQiLCJleHAiOjE3ODY5NTYwNTgsImlhdCI6MTc4Njk1MjQ1OH0.TZXGJLNng6TyfzspOkA6HuEyFi61K-wnie_L6ybYzyY"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:29:04.289+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-17T15:29:04.291+0700","caller":"handlers/handlers.go:66","msg":"Request Success","status":200,"method":"GET","path":"/master-data/provinces/template","query":"","ip":"127.0.0.1","latency":0.034353167,"user-agent":"Apidog/1.0.0 (https://apidog.com)"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.151+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.222+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.223+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.274+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.356+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.406+0700","caller":"database/database.go:53","msg":"Connect To Master DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.467+0700","caller":"database/database.go:63","msg":"DB Master Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.467+0700","caller":"database/database.go:76","msg":"Connect To Slave DB"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.514+0700","caller":"database/database.go:86","msg":"DB Connection Done"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.609+0700","caller":"handlers/handlers.go:113","msg":"Starting Apps"}
|
||||||
|
|||||||
@ -3358,3 +3358,108 @@
|
|||||||
{"level":"info","ts":"2026-08-17T14:21:30.235+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
{"level":"info","ts":"2026-08-17T14:21:30.235+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
{"level":"info","ts":"2026-08-17T14:21:30.290+0700","caller":"database/redis.go:62","msg":"Connected"}
|
{"level":"info","ts":"2026-08-17T14:21:30.290+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
{"level":"info","ts":"2026-08-17T14:21:37.620+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:100","elapsed":0.064875875,"rows":1,"sql":"INSERT INTO \"province\" (\"name\",\"created_by\",\"created_on\",\"updated_by\",\"updated_on\",\"merchant_id\") VALUES ('tambahan','19ff104c16522a2252cbaca24d','2026-08-17 14:21:37.555','19ff104c16522a2252cbaca24d','2026-08-17 14:21:37.555','19ff111bca6c2c382d9eb43b3c') RETURNING \"id\""}
|
{"level":"info","ts":"2026-08-17T14:21:37.620+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:100","elapsed":0.064875875,"rows":1,"sql":"INSERT INTO \"province\" (\"name\",\"created_by\",\"created_on\",\"updated_by\",\"updated_on\",\"merchant_id\") VALUES ('tambahan','19ff104c16522a2252cbaca24d','2026-08-17 14:21:37.555','19ff104c16522a2252cbaca24d','2026-08-17 14:21:37.555','19ff111bca6c2c382d9eb43b3c') RETURNING \"id\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.752+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.753+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.802+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.802+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.802+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:11.856+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:14.035+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:135","elapsed":0.062923208,"rows":1,"sql":"DELETE FROM \"province\" WHERE id = '1a00e98ea5f87d9a1026ba6441'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:25:32.594+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:100","elapsed":0.081571459,"rows":1,"sql":"INSERT INTO \"province\" (\"name\",\"created_by\",\"created_on\",\"updated_by\",\"updated_on\",\"merchant_id\") VALUES ('tambahan','19ff104c16522a2252cbaca24d','2026-08-17 14:25:32.504','19ff104c16522a2252cbaca24d','2026-08-17 14:25:32.504','19ff111bca6c2c382d9eb43b3c') RETURNING \"id\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.363+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.363+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.426+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.426+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.426+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:01.481+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:02.013+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:114","elapsed":0.044179208,"rows":1,"sql":"SELECT * FROM \"province\" WHERE id = '1a00e9c80365466b3d2a04918c' ORDER BY \"province\".\"id\" LIMIT 1"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:29:02.064+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:123","elapsed":0.050348583,"rows":1,"sql":"UPDATE \"province\" SET \"name\"='tambahan xxx',\"created_by\"='19ff104c16522a2252cbaca24d',\"created_on\"='2026-08-17 14:25:32.504',\"updated_by\"='19ff104c16522a2252cbaca24d',\"updated_on\"='2026-08-17 14:29:02.024',\"merchant_id\"='19ff111bca6c2c382d9eb43b3c' WHERE \"id\" = '1a00e9c80365466b3d2a04918c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.424+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.424+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.477+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.477+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.477+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:30.531+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:34.384+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:114","elapsed":0.040815125,"rows":1,"sql":"SELECT * FROM \"province\" WHERE id = '1a00e9c80365466b3d2a04918c' ORDER BY \"province\".\"id\" LIMIT 1"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:30:34.428+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:123","elapsed":0.043398083,"rows":1,"sql":"UPDATE \"province\" SET \"name\"='tambahan xxx',\"created_by\"='19ff104c16522a2252cbaca24d',\"created_on\"='2026-08-17 14:25:32.504',\"updated_by\"='19ff104c16522a2252cbaca24d',\"updated_on\"='2026-08-17 14:30:34.395',\"merchant_id\"='19ff111bca6c2c382d9eb43b3c' WHERE \"id\" = '1a00e9c80365466b3d2a04918c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:32:39.655+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:135","elapsed":0.056869167,"rows":1,"sql":"DELETE FROM \"province\" WHERE id = '1a00e9c80365466b3d2a04918c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.024+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.025+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.076+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.076+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.076+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:38:28.134+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:10.622+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:37","elapsed":0.040459209,"rows":1,"sql":"SELECT count(*) FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:10.653+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:39","elapsed":0.030940792,"rows":34,"sql":"SELECT * FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.543+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.543+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.599+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.600+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.600+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:47.656+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:50.204+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:37","elapsed":0.039307917,"rows":1,"sql":"SELECT count(*) FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:39:50.234+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:39","elapsed":0.029045833,"rows":34,"sql":"SELECT * FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:13.574+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:37","elapsed":0.028055875,"rows":1,"sql":"SELECT count(*) FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:13.588+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:39","elapsed":0.013114458,"rows":34,"sql":"SELECT * FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:47.976+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:47.976+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:48.031+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:48.031+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:48.031+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:48.088+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:58.695+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.020184542,"rows":1,"sql":"SELECT * FROM \"users_roles\" WHERE \"users_roles\".\"id\" = '19fe814c5350d67814c3e6057c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:40:58.697+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.072182583,"rows":1,"sql":"SELECT * FROM \"users\" WHERE email='gcx@gmail.com'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:41:02.382+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:37","elapsed":0.064269583,"rows":1,"sql":"SELECT count(*) FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:41:02.440+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:39","elapsed":0.056326958,"rows":34,"sql":"SELECT * FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.180+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.180+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.234+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.234+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.234+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:38.286+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:40.080+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:38","elapsed":0.03832,"rows":1,"sql":"SELECT count(*) FROM \"province\" WHERE merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:42:40.111+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:40","elapsed":0.029813584,"rows":34,"sql":"SELECT * FROM \"province\""}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.513+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.513+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.569+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.569+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.569+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.623+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.715+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:38","elapsed":0.033541541,"rows":1,"sql":"SELECT count(*) FROM \"province\" WHERE merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:43:03.742+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:40","elapsed":0.026353084,"rows":34,"sql":"SELECT * FROM \"province\" WHERE merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c' ORDER BY name ASC"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:45:05.446+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:38","elapsed":0.032110583,"rows":1,"sql":"SELECT count(*) FROM \"province\" WHERE merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:45:05.465+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:40","elapsed":0.017382292,"rows":34,"sql":"SELECT * FROM \"province\" WHERE merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c' ORDER BY name ASC"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.875+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.876+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.933+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.934+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:33.934+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:50:34.000+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.543+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.544+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.598+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.599+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.599+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:52.652+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:56.871+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:51","elapsed":0.033292084,"rows":1,"sql":"SELECT count(*) FROM \"province\" WHERE (merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c') AND name='aceh'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T14:59:56.918+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:53","elapsed":0.046337875,"rows":0,"sql":"SELECT * FROM \"province\" WHERE (merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c') AND name='aceh' ORDER BY name ASC"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:02:00.123+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:51","elapsed":0.03923575,"rows":1,"sql":"SELECT count(*) FROM \"province\" WHERE (merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c') AND name='ACEH'"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:02:00.143+0700","caller":"logger/database.go:90","msg":"[GORM] query execution","line":"/Users/teguh/Documents/project/cargo/cargo-erp-deploy/app/backend/internal/usecases/province.go:53","elapsed":0.018068625,"rows":1,"sql":"SELECT * FROM \"province\" WHERE (merchant_id IS NULL OR merchant_id='19ff111bca6c2c382d9eb43b3c') AND name='ACEH' ORDER BY name ASC"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.516+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.516+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.572+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.572+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.572+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T15:28:06.622+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.279+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.279+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.317+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.317+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.317+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:38:50.355+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.514+0700","caller":"database/redis.go:34","msg":"Parse config master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.515+0700","caller":"database/redis.go:49","msg":"Connecting to Redis master"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.550+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.550+0700","caller":"database/redis.go:34","msg":"Parse config slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.551+0700","caller":"database/redis.go:49","msg":"Connecting to Redis slave"}
|
||||||
|
{"level":"info","ts":"2026-08-17T18:39:33.584+0700","caller":"database/redis.go:62","msg":"Connected"}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user