Compare commits

...

16 Commits

Author SHA1 Message Date
Habib Fatkhul Rohman fd664c5c3f feat: integrate logging and audit trail in inventory transaction service
Deploy Application / deploy (push) Failing after 16s Details
2025-12-04 15:05:15 +07:00
Habib Fatkhul Rohman e6b19a2478 feat: integrate logging and audit trail in inventory storage service 2025-12-04 15:00:43 +07:00
Habib Fatkhul Rohman bcc73a0f99 feat: integrate logging and audit trail in inventory return service 2025-12-04 14:54:54 +07:00
Habib Fatkhul Rohman 844a41eb78 feat: integrate logging and audit trail in inventory request service 2025-12-04 14:24:56 +07:00
Habib Fatkhul Rohman 7e4e7cc5a8 feat: integrate logging and audit trail in inventory receipt service 2025-12-04 14:11:55 +07:00
Habib Fatkhul Rohman f36380873c feat: integrate logging and audit trail in inventory movement service 2025-12-04 13:39:12 +07:00
Habib Fatkhul Rohman 41dacd0e3e feat: integrate logging and audit trail in inventory issue service 2025-12-04 13:20:14 +07:00
Habib Fatkhul Rohman e6c025f675 feat: enhance aisle service with logging and audit trail integration 2025-12-03 15:10:51 +07:00
Habib Fatkhul Rohman cf51d7f0c9 feat: integrate logging and audit trail in category service and DTOs 2025-12-03 14:58:00 +07:00
Habib Fatkhul Rohman 6c757e2065 feat: integrate logging and audit trail in client service operations 2025-12-03 14:51:01 +07:00
Habib Fatkhul Rohman cd60dc109f feat: refactor menu service to use ToMenuResponse for response mapping and integrate logging 2025-12-03 14:39:10 +07:00
Habib Fatkhul Rohman 6296fc623c feat: add logging and audit trail to vendor service operations 2025-12-03 14:22:52 +07:00
Habib Fatkhul Rohman b2b1067e00 feat: enhance product service with logging and audit trail functionality 2025-12-03 13:57:47 +07:00
Habib Fatkhul Rohman 8d852521c4 feat: add ToRoleResponse function and integrate logging in role service 2025-12-03 13:30:59 +07:00
Habib Fatkhul Rohman 02c3c97a76 feat: implement ZonaResponse conversion and enhance logging in Zona service 2025-12-03 12:03:48 +07:00
Habib Fatkhul Rohman db82ad3364 feat: refactor configuration management to use viper for environment variables 2025-12-03 11:43:00 +07:00
28 changed files with 1137 additions and 529 deletions

View File

@ -33,6 +33,7 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/warehouse" "github.com/Caknoooo/go-gin-clean-starter/modules/warehouse"
"github.com/Caknoooo/go-gin-clean-starter/modules/zona" "github.com/Caknoooo/go-gin-clean-starter/modules/zona"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/viper"
swaggerFiles "github.com/swaggo/files" swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
@ -58,13 +59,13 @@ func args(injector *do.Injector) bool {
func run(server *gin.Engine) { func run(server *gin.Engine) {
server.Static("/assets", "./assets") server.Static("/assets", "./assets")
port := os.Getenv("GOLANG_PORT") port := viper.GetString("GOLANG_PORT")
if port == "" { if port == "" {
port = "8888" port = "8888"
} }
var serve string var serve string
if os.Getenv("APP_ENV") == "localhost" { if viper.GetString("APP_ENV") == "localhost" {
serve = "0.0.0.0:" + port serve = "0.0.0.0:" + port
} else { } else {
serve = ":" + port serve = ":" + port
@ -102,6 +103,13 @@ func run(server *gin.Engine) {
// @externalDocs.description OpenAPI // @externalDocs.description OpenAPI
// @externalDocs.url https://swagger.io/resources/open-api/ // @externalDocs.url https://swagger.io/resources/open-api/
func main() { func main() {
viper.SetConfigFile(".env")
err := viper.ReadInConfig()
if err != nil {
log.Fatal("Error loading .env file")
}
viper.AutomaticEnv()
var ( var (
injector = do.New() injector = do.New()

View File

@ -2,10 +2,10 @@ package config
import ( import (
"fmt" "fmt"
"os"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/spf13/viper"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -15,18 +15,18 @@ func RunExtension(db *gorm.DB) {
} }
func SetUpDatabaseConnection() *gorm.DB { func SetUpDatabaseConnection() *gorm.DB {
if os.Getenv("APP_ENV") != constants.ENUM_RUN_PRODUCTION { if viper.GetString("APP_ENV") != constants.ENUM_RUN_PRODUCTION {
err := godotenv.Load(".env") err := godotenv.Load(".env")
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
dbUser := os.Getenv("DB_USER") dbUser := viper.GetString("DB_USER")
dbPass := os.Getenv("DB_PASS") dbPass := viper.GetString("DB_PASS")
dbHost := os.Getenv("DB_HOST") dbHost := viper.GetString("DB_HOST")
dbName := os.Getenv("DB_NAME") dbName := viper.GetString("DB_NAME")
dbPort := os.Getenv("DB_PORT") dbPort := viper.GetString("DB_PORT")
dsn := fmt.Sprintf("host=%v user=%v password=%v dbname=%v port=%v", dbHost, dbUser, dbPass, dbName, dbPort) dsn := fmt.Sprintf("host=%v user=%v password=%v dbname=%v port=%v", dbHost, dbUser, dbPass, dbName, dbPort)

View File

@ -15,6 +15,7 @@ type EmailConfig struct {
func NewEmailConfig() (*EmailConfig, error) { func NewEmailConfig() (*EmailConfig, error) {
viper.SetConfigFile(".env") viper.SetConfigFile(".env")
if err := viper.ReadInConfig(); err != nil { if err := viper.ReadInConfig(); err != nil {
return nil, err return nil, err
} }

View File

@ -11,6 +11,7 @@ import (
amqp "github.com/rabbitmq/amqp091-go" amqp "github.com/rabbitmq/amqp091-go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/viper"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
) )
@ -70,12 +71,12 @@ func SetupLoggerLogrus() *logrus.Logger {
// ✔️ Pasang RabbitMQ Hook kalau channel berhasil connect // ✔️ Pasang RabbitMQ Hook kalau channel berhasil connect
if RabbitChannel != nil { if RabbitChannel != nil {
queue := os.Getenv("RABBITMQ_LOG_QUEUE") // contoh: log_queue queue := viper.GetString("RABBITMQ_LOG_QUEUE") // contoh: log_queue
hook := NewRabbitMQHook(RabbitChannel, queue) hook := NewRabbitMQHook(RabbitChannel, queue)
logger.AddHook(hook) logger.AddHook(hook)
} }
logLevel := strings.ToLower(os.Getenv("LOG_LEVEL")) logLevel := strings.ToLower(viper.GetString("LOG_LEVEL"))
if logLevel == "production" { if logLevel == "production" {
logger.SetLevel(logrus.WarnLevel) logger.SetLevel(logrus.WarnLevel)
} else { } else {

View File

@ -3,20 +3,20 @@ package config
import ( import (
"fmt" "fmt"
"log" "log"
"os"
amqp "github.com/rabbitmq/amqp091-go" amqp "github.com/rabbitmq/amqp091-go"
"github.com/spf13/viper"
) )
var RabbitConn *amqp.Connection var RabbitConn *amqp.Connection
var RabbitChannel *amqp.Channel var RabbitChannel *amqp.Channel
func InitRabbitMQ() { func InitRabbitMQ() {
host := os.Getenv("RABBITMQ_HOST") host := viper.GetString("RABBITMQ_HOST")
port := os.Getenv("RABBITMQ_PORT") port := viper.GetString("RABBITMQ_PORT")
user := os.Getenv("RABBITMQ_USER") user := viper.GetString("RABBITMQ_USER")
pass := os.Getenv("RABBITMQ_PASSWORD") pass := viper.GetString("RABBITMQ_PASSWORD")
queue := os.Getenv("RABBITMQ_LOG_QUEUE") // contoh: log_queue queue := viper.GetString("RABBITMQ_LOG_QUEUE") // contoh: log_queue
uri := fmt.Sprintf("amqp://%s:%s@%s:%s/", uri := fmt.Sprintf("amqp://%s:%s@%s:%s/",
user, pass, host, port, user, pass, host, port,

View File

@ -3,7 +3,9 @@ package dto
import ( import (
"errors" "errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid"
) )
const ( const (
@ -75,3 +77,48 @@ type AisleResponse struct {
WeightUom pkgdto.IdNameResponse `json:"weight_uom_id"` WeightUom pkgdto.IdNameResponse `json:"weight_uom_id"`
Client pkgdto.IdNameResponse `json:"client_id"` Client pkgdto.IdNameResponse `json:"client_id"`
} }
func ToAisleResponse(e entities.MAisleEntity) AisleResponse {
zona := pkgdto.IdNameResponse{}
if e.Zona.ID != uuid.Nil {
zona.ID = e.Zona.ID.String()
zona.Name = e.Zona.Name
}
dimUom := pkgdto.IdNameResponse{}
if e.DimUom.ID != uuid.Nil {
dimUom.ID = e.DimUom.ID.String()
dimUom.Name = e.DimUom.Name
}
weightUom := pkgdto.IdNameResponse{}
if e.WeightUom.ID != uuid.Nil {
weightUom.ID = e.WeightUom.ID.String()
weightUom.Name = e.WeightUom.Name
}
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client.ID = e.Client.ID.String()
client.Name = e.Client.Name
}
return AisleResponse{
ID: e.ID.String(),
Code: e.Code,
Name: e.Name,
IsleX: e.IsleX,
BinY: e.BinY,
LevelZ: e.LevelZ,
DimLength: e.DimLength,
DimWidth: e.DimWidth,
DimHeight: e.DimHeight,
Weight: e.Weight,
QrCodeAisle: e.QrCodeAisle,
IsActive: e.IsActive,
Zone: zona,
DimUom: dimUom,
WeightUom: weightUom,
Client: client,
}
}

View File

@ -7,8 +7,10 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/aisle/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/aisle/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/aisle/query" "github.com/Caknoooo/go-gin-clean-starter/modules/aisle/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/aisle/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/aisle/repository"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -23,51 +25,7 @@ type AisleService interface {
type aisleService struct { type aisleService struct {
db *gorm.DB db *gorm.DB
aisleRepo repository.AisleRepository aisleRepo repository.AisleRepository
} log *logrus.Logger
func toAisleResponse(e entities.MAisleEntity) dto.AisleResponse {
zona := pkgdto.IdNameResponse{}
if e.Zona.ID != uuid.Nil {
zona.ID = e.Zona.ID.String()
zona.Name = e.Zona.Name
}
dimUom := pkgdto.IdNameResponse{}
if e.DimUom.ID != uuid.Nil {
dimUom.ID = e.DimUom.ID.String()
dimUom.Name = e.DimUom.Name
}
weightUom := pkgdto.IdNameResponse{}
if e.WeightUom.ID != uuid.Nil {
weightUom.ID = e.WeightUom.ID.String()
weightUom.Name = e.WeightUom.Name
}
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client.ID = e.Client.ID.String()
client.Name = e.Client.Name
}
return dto.AisleResponse{
ID: e.ID.String(),
Code: e.Code,
Name: e.Name,
IsleX: e.IsleX,
BinY: e.BinY,
LevelZ: e.LevelZ,
DimLength: e.DimLength,
DimWidth: e.DimWidth,
DimHeight: e.DimHeight,
Weight: e.Weight,
QrCodeAisle: e.QrCodeAisle,
IsActive: e.IsActive,
Zone: zona,
DimUom: dimUom,
WeightUom: weightUom,
Client: client,
}
} }
func (s *aisleService) Create(ctx context.Context, req dto.AisleCreateRequest) (dto.AisleResponse, error) { func (s *aisleService) Create(ctx context.Context, req dto.AisleCreateRequest) (dto.AisleResponse, error) {
@ -113,6 +71,7 @@ func (s *aisleService) Create(ctx context.Context, req dto.AisleCreateRequest) (
DimUomID: dimUomUUID, DimUomID: dimUomUUID,
WeightUomID: weightUomUUID, WeightUomID: weightUomUUID,
ClientID: clientUUID, ClientID: clientUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.aisleRepo.Create(ctx, tx, aisle) created, err := s.aisleRepo.Create(ctx, tx, aisle)
if err != nil { if err != nil {
@ -124,7 +83,13 @@ func (s *aisleService) Create(ctx context.Context, req dto.AisleCreateRequest) (
if err != nil { if err != nil {
return dto.AisleResponse{}, err return dto.AisleResponse{}, err
} }
return toAisleResponse(result), nil s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "aisle",
"entity_id": created.ID.String(),
}).Info("Aisle created")
return dto.ToAisleResponse(result), nil
} }
func (s *aisleService) GetById(ctx context.Context, aisleId string) (dto.AisleResponse, error) { func (s *aisleService) GetById(ctx context.Context, aisleId string) (dto.AisleResponse, error) {
@ -132,7 +97,7 @@ func (s *aisleService) GetById(ctx context.Context, aisleId string) (dto.AisleRe
if err != nil { if err != nil {
return dto.AisleResponse{}, err return dto.AisleResponse{}, err
} }
return toAisleResponse(aisle), nil return dto.ToAisleResponse(aisle), nil
} }
func (s *aisleService) GetAll(ctx context.Context, filter query.AisleFilter) ([]dto.AisleResponse, int64, error) { func (s *aisleService) GetAll(ctx context.Context, filter query.AisleFilter) ([]dto.AisleResponse, int64, error) {
@ -142,7 +107,7 @@ func (s *aisleService) GetAll(ctx context.Context, filter query.AisleFilter) ([]
} }
var responses []dto.AisleResponse var responses []dto.AisleResponse
for _, e := range aisles { for _, e := range aisles {
responses = append(responses, toAisleResponse(e)) responses = append(responses, dto.ToAisleResponse(e))
} }
if responses == nil { if responses == nil {
responses = make([]dto.AisleResponse, 0) responses = make([]dto.AisleResponse, 0)
@ -193,6 +158,7 @@ func (s *aisleService) Update(ctx context.Context, req dto.AisleUpdateRequest, a
aisle.QrCodeAisle = req.QrCodeAisle aisle.QrCodeAisle = req.QrCodeAisle
} }
aisle.IsActive = req.IsActive aisle.IsActive = req.IsActive
aisle.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.aisleRepo.Update(ctx, tx, aisle) updated, err := s.aisleRepo.Update(ctx, tx, aisle)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -203,7 +169,13 @@ func (s *aisleService) Update(ctx context.Context, req dto.AisleUpdateRequest, a
if err != nil { if err != nil {
return dto.AisleResponse{}, err return dto.AisleResponse{}, err
} }
return toAisleResponse(result), nil s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "aisle",
"entity_id": aisleId,
}).Info("Aisle updated")
return dto.ToAisleResponse(result), nil
} }
func (s *aisleService) Delete(ctx context.Context, aisleId string) error { func (s *aisleService) Delete(ctx context.Context, aisleId string) error {
@ -213,17 +185,34 @@ func (s *aisleService) Delete(ctx context.Context, aisleId string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
aisle, err := s.aisleRepo.GetById(ctx, tx, aisleId)
if err != nil {
tx.Rollback()
return err
}
aisle.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.aisleRepo.Update(ctx, tx, aisle); err != nil {
tx.Rollback()
return err
}
if err := s.aisleRepo.Delete(ctx, tx, aisleId); err != nil { if err := s.aisleRepo.Delete(ctx, tx, aisleId); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "aisle",
"entity_id": aisleId,
}).Info("Aisle deleted")
return nil return nil
} }
func NewAisleService(aisleRepo repository.AisleRepository, db *gorm.DB) AisleService { func NewAisleService(aisleRepo repository.AisleRepository, db *gorm.DB, log *logrus.Logger) AisleService {
return &aisleService{ return &aisleService{
aisleRepo: aisleRepo, aisleRepo: aisleRepo,
db: db, db: db,
log: log,
} }
} }

View File

@ -5,10 +5,10 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"log" "log"
"os"
"time" "time"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
"github.com/spf13/viper"
) )
type UserTokenInfo struct { type UserTokenInfo struct {
@ -51,7 +51,7 @@ func NewJWTService() JWTService {
} }
func getSecretKey() string { func getSecretKey() string {
secretKey := os.Getenv("JWT_SECRET") secretKey := viper.GetString("JWT_SECRET")
if secretKey == "" { if secretKey == "" {
secretKey = "WMS-WareifySecretKey" secretKey = "WMS-WareifySecretKey"
} }

View File

@ -3,8 +3,8 @@ package dto
import ( import (
"errors" "errors"
// staticDto "github.com/Caknoooo/go-gin-clean-starter/modules/static/dto" "github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
) )
const ( const (
@ -48,5 +48,19 @@ type CategoryResponse struct {
SearchKey string `json:"search_key"` SearchKey string `json:"search_key"`
Description string `json:"description"` Description string `json:"description"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
Client dto.ClientResponse `json:"client"` Client pkgdto.IdNameResponse `json:"client"`
}
func ToCategoryResponse(e entities.MCategoryEntity) CategoryResponse {
return CategoryResponse{
ID: e.ID.String(),
Name: e.Name,
SearchKey: e.SearchKey,
Description: e.Description,
IsActive: e.IsActive,
Client: pkgdto.IdNameResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
},
}
} }

View File

@ -7,8 +7,10 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/category/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/category/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/category/query" "github.com/Caknoooo/go-gin-clean-starter/modules/category/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/category/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/category/repository"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -23,12 +25,14 @@ type CategoryService interface {
type categoryService struct { type categoryService struct {
db *gorm.DB db *gorm.DB
categoryRepo repository.CategoryRepository categoryRepo repository.CategoryRepository
log *logrus.Logger
} }
func NewCategoryService(categoryRepo repository.CategoryRepository, db *gorm.DB) CategoryService { func NewCategoryService(categoryRepo repository.CategoryRepository, db *gorm.DB, log *logrus.Logger) CategoryService {
return &categoryService{ return &categoryService{
categoryRepo: categoryRepo, categoryRepo: categoryRepo,
db: db, db: db,
log: log,
} }
} }
@ -44,6 +48,7 @@ func (s *categoryService) Create(ctx context.Context, req dto.CategoryCreateRequ
SearchKey: req.SearchKey, SearchKey: req.SearchKey,
Description: req.Description, Description: req.Description,
IsActive: req.IsActive, IsActive: req.IsActive,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
clientUUID, err := uuid.Parse(req.ClientID) clientUUID, err := uuid.Parse(req.ClientID)
if err != nil { if err != nil {
@ -62,7 +67,13 @@ func (s *categoryService) Create(ctx context.Context, req dto.CategoryCreateRequ
if err != nil { if err != nil {
return dto.CategoryResponse{}, err return dto.CategoryResponse{}, err
} }
return toCategoryResponse(result), nil s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "category",
"entity_id": created.ID.String(),
}).Info("Category created")
return dto.ToCategoryResponse(result), nil
} }
func (s *categoryService) GetById(ctx context.Context, categoryId string) (dto.CategoryResponse, error) { func (s *categoryService) GetById(ctx context.Context, categoryId string) (dto.CategoryResponse, error) {
@ -70,7 +81,7 @@ func (s *categoryService) GetById(ctx context.Context, categoryId string) (dto.C
if err != nil { if err != nil {
return dto.CategoryResponse{}, err return dto.CategoryResponse{}, err
} }
return toCategoryResponse(category), nil return dto.ToCategoryResponse(category), nil
} }
func (s *categoryService) GetAll(ctx context.Context, filter query.CategoryFilter) ([]dto.CategoryResponse, int64, error) { func (s *categoryService) GetAll(ctx context.Context, filter query.CategoryFilter) ([]dto.CategoryResponse, int64, error) {
@ -80,7 +91,7 @@ func (s *categoryService) GetAll(ctx context.Context, filter query.CategoryFilte
} }
var responses []dto.CategoryResponse var responses []dto.CategoryResponse
for _, c := range categories { for _, c := range categories {
responses = append(responses, toCategoryResponse(c)) responses = append(responses, dto.ToCategoryResponse(c))
} }
if responses == nil { if responses == nil {
responses = make([]dto.CategoryResponse, 0) responses = make([]dto.CategoryResponse, 0)
@ -104,6 +115,7 @@ func (s *categoryService) Update(ctx context.Context, req dto.CategoryUpdateRequ
category.SearchKey = req.SearchKey category.SearchKey = req.SearchKey
category.Description = req.Description category.Description = req.Description
category.IsActive = req.IsActive category.IsActive = req.IsActive
category.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.categoryRepo.Update(ctx, tx, category) updated, err := s.categoryRepo.Update(ctx, tx, category)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -115,7 +127,13 @@ func (s *categoryService) Update(ctx context.Context, req dto.CategoryUpdateRequ
if err != nil { if err != nil {
return dto.CategoryResponse{}, err return dto.CategoryResponse{}, err
} }
return toCategoryResponse(result), nil s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "category",
"entity_id": categoryId,
}).Info("Category updated")
return dto.ToCategoryResponse(result), nil
} }
func (s *categoryService) Delete(ctx context.Context, categoryId string) error { func (s *categoryService) Delete(ctx context.Context, categoryId string) error {
@ -125,24 +143,27 @@ func (s *categoryService) Delete(ctx context.Context, categoryId string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
category, err := s.categoryRepo.GetById(ctx, tx, categoryId)
if err != nil {
tx.Rollback()
return err
}
category.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.categoryRepo.Update(ctx, tx, category); err != nil {
tx.Rollback()
return err
}
if err := s.categoryRepo.Delete(ctx, tx, categoryId); err != nil { if err := s.categoryRepo.Delete(ctx, tx, categoryId); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "category",
"entity_id": categoryId,
}).Info("Category deleted")
return nil return nil
} }
func toCategoryResponse(e entities.MCategoryEntity) dto.CategoryResponse {
return dto.CategoryResponse{
ID: e.ID.String(),
Name: e.Name,
SearchKey: e.SearchKey,
Description: e.Description,
IsActive: e.IsActive,
Client: pkgdto.ClientResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
},
}
}

View File

@ -7,6 +7,9 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/client/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/client/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/client/query" "github.com/Caknoooo/go-gin-clean-starter/modules/client/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/client/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/client/repository"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -24,6 +27,7 @@ type ClientService interface {
type clientService struct { type clientService struct {
db *gorm.DB db *gorm.DB
clientRepo repository.ClientRepository clientRepo repository.ClientRepository
log *logrus.Logger
} }
func (s *clientService) GetAll(ctx context.Context, filter query.ClientFilter) ([]dto.ClientResponse, int64, error) { func (s *clientService) GetAll(ctx context.Context, filter query.ClientFilter) ([]dto.ClientResponse, int64, error) {
@ -63,13 +67,15 @@ func (s *clientService) Create(ctx context.Context, req dto.ClientCreateRequest)
} }
}() }()
userID := utils.GetUserID(ctx)
client := entities.M_Client{ client := entities.M_Client{
Name: req.Name, Name: req.Name,
PIC: req.PIC, PIC: req.PIC,
Phone: req.Phone, Phone: req.Phone,
Email: req.Email, Email: req.Email,
Address: req.Address, Address: req.Address,
Logo: req.Logo, // []byte, sudah benar untuk simpan file Logo: req.Logo,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
createdClient, err := s.clientRepo.Create(ctx, tx, client) createdClient, err := s.clientRepo.Create(ctx, tx, client)
@ -83,11 +89,12 @@ func (s *clientService) Create(ctx context.Context, req dto.ClientCreateRequest)
return dto.ClientResponse{}, err return dto.ClientResponse{}, err
} }
// Mapping entity ke response (Logo bisa dikonversi ke base64 jika perlu) s.log.WithFields(logrus.Fields{
// logoBase64 := "" "user_id": userID,
// if len(createdClient.Logo) > 0 { "action": "create",
// logoBase64 = base64.StdEncoding.EncodeToString(createdClient.Logo) "entity": "client",
// } "entity_id": createdClient.ID.String(),
}).Info("Client created")
result, err := s.GetById(ctx, createdClient.ID.String()) result, err := s.GetById(ctx, createdClient.ID.String())
if err != nil { if err != nil {
@ -177,6 +184,8 @@ func (s *clientService) Update(ctx context.Context, req dto.ClientUpdateRequest,
if req.Logo != nil { if req.Logo != nil {
client.Logo = *req.Logo client.Logo = *req.Logo
} }
userID := utils.GetUserID(ctx)
client.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updatedClient, err := s.clientRepo.Update(ctx, tx, client) updatedClient, err := s.clientRepo.Update(ctx, tx, client)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -187,10 +196,13 @@ func (s *clientService) Update(ctx context.Context, req dto.ClientUpdateRequest,
tx.Rollback() tx.Rollback()
return dto.ClientResponse{}, err return dto.ClientResponse{}, err
} }
// logoBase64 := ""
// if len(updatedClient.Logo) > 0 { s.log.WithFields(logrus.Fields{
// logoBase64 = base64.StdEncoding.EncodeToString(updatedClient.Logo) "user_id": userID,
// } "action": "update",
"entity": "client",
"entity_id": clientId,
}).Info("Client updated")
result, err := s.GetById(ctx, updatedClient.ID.String()) result, err := s.GetById(ctx, updatedClient.ID.String())
if err != nil { if err != nil {
@ -206,7 +218,18 @@ func (s *clientService) Delete(ctx context.Context, clientId string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
err := s.clientRepo.Delete(ctx, tx, clientId) client, err := s.clientRepo.GetById(ctx, tx, clientId)
if err != nil {
tx.Rollback()
return err
}
userID := utils.GetUserID(ctx)
client.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.clientRepo.Update(ctx, tx, client); err != nil {
tx.Rollback()
return err
}
err = s.clientRepo.Delete(ctx, tx, clientId)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return err return err
@ -216,6 +239,13 @@ func (s *clientService) Delete(ctx context.Context, clientId string) error {
tx.Rollback() tx.Rollback()
return err return err
} }
s.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "delete",
"entity": "client",
"entity_id": clientId,
}).Info("Client deleted")
return nil return nil
} }
@ -237,9 +267,10 @@ func (s *clientService) RemoveMenusFromClient(ctx context.Context, clientId stri
return s.clientRepo.RemoveMenusFromClient(ctx, s.db, clientId, menuIds) return s.clientRepo.RemoveMenusFromClient(ctx, s.db, clientId, menuIds)
} }
func NewClientService(clientRepo repository.ClientRepository, db *gorm.DB) ClientService { func NewClientService(clientRepo repository.ClientRepository, db *gorm.DB, log *logrus.Logger) ClientService {
return &clientService{ return &clientService{
clientRepo: clientRepo, clientRepo: clientRepo,
db: db, db: db,
log: log,
} }
} }

View File

@ -8,9 +8,11 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/repository"
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -31,6 +33,7 @@ type inventoryIssueService struct {
issueRepo repository.InventoryIssueRepository issueRepo repository.InventoryIssueRepository
issueLineRepo repository.InventoryIssueLineRepository issueLineRepo repository.InventoryIssueLineRepository
sequenceService sequenceservice.SequenceService sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
// GetLinesByIssueId implements InventoryIssueService. // GetLinesByIssueId implements InventoryIssueService.
@ -42,8 +45,8 @@ func (s *inventoryIssueService) GetLinesByIssueId(ctx context.Context, issueId s
return dtodomain.ToInventoryIssueLineResponses(lines), nil return dtodomain.ToInventoryIssueLineResponses(lines), nil
} }
func NewInventoryIssueService(db *gorm.DB, issueRepo repository.InventoryIssueRepository, issueLineRepo repository.InventoryIssueLineRepository, sequenceService sequenceservice.SequenceService) InventoryIssueService { func NewInventoryIssueService(db *gorm.DB, issueRepo repository.InventoryIssueRepository, issueLineRepo repository.InventoryIssueLineRepository, sequenceService sequenceservice.SequenceService, log *logrus.Logger) InventoryIssueService {
return &inventoryIssueService{db: db, issueRepo: issueRepo, issueLineRepo: issueLineRepo, sequenceService: sequenceService} return &inventoryIssueService{db: db, issueRepo: issueRepo, issueLineRepo: issueLineRepo, sequenceService: sequenceService, log: log}
} }
func (s *inventoryIssueService) Create(ctx context.Context, req dtodomain.InventoryIssueCreateRequest) (dtodomain.InventoryIssueResponse, error) { func (s *inventoryIssueService) Create(ctx context.Context, req dtodomain.InventoryIssueCreateRequest) (dtodomain.InventoryIssueResponse, error) {
@ -85,6 +88,7 @@ func (s *inventoryIssueService) Create(ctx context.Context, req dtodomain.Invent
InvRequestID: invRequestUUID, InvRequestID: invRequestUUID,
ClientID: clientUUID, ClientID: clientUUID,
Status: req.Status, Status: req.Status,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.issueRepo.Create(ctx, tx, issue) created, err := s.issueRepo.Create(ctx, tx, issue)
if err != nil { if err != nil {
@ -129,6 +133,12 @@ func (s *inventoryIssueService) Create(ctx context.Context, req dtodomain.Invent
} }
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "inventory_issue",
"entity_id": created.ID.String(),
}).Info("Inventory Issue created")
result, err := s.issueRepo.GetById(ctx, nil, created.ID.String()) result, err := s.issueRepo.GetById(ctx, nil, created.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryIssueResponse{}, err return dtodomain.InventoryIssueResponse{}, err
@ -171,19 +181,34 @@ func (s *inventoryIssueService) Update(ctx context.Context, req dtodomain.Invent
tx.Rollback() tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err return dtodomain.InventoryIssueResponse{}, err
} }
before := issue
issue.DocumentDate = utils.StringToDateTime(req.DocumentDate) issue.DocumentDate = utils.StringToDateTime(req.DocumentDate)
issue.DueDate = utils.StringToDateTime(req.DueDate) issue.DueDate = utils.StringToDateTime(req.DueDate)
issue.Status = req.Status issue.Status = req.Status
issue.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.issueRepo.Update(ctx, tx, issue) updated, err := s.issueRepo.Update(ctx, tx, issue)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err return dtodomain.InventoryIssueResponse{}, err
} }
tx.Commit() tx.Commit()
result, err := s.issueRepo.GetById(ctx, nil, updated.ID.String()) result, err := s.issueRepo.GetById(ctx, nil, updated.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryIssueResponse{}, err return dtodomain.InventoryIssueResponse{}, err
} }
changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "inventory_issue",
"entity_id": id,
"changes": changes,
}).Info("Inventory Issue updated")
return dtodomain.ToInventoryIssueResponse(result), nil return dtodomain.ToInventoryIssueResponse(result), nil
} }
@ -194,11 +219,27 @@ func (s *inventoryIssueService) Delete(ctx context.Context, id string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
issue, err := s.issueRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return err
}
issue.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.issueRepo.Update(ctx, tx, issue); err != nil {
tx.Rollback()
return err
}
if err := s.issueRepo.Delete(ctx, tx, id); err != nil { if err := s.issueRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "inventory_issue",
"entity_id": id,
}).Info("Inventory Issue deleted")
return nil return nil
} }

View File

@ -8,8 +8,10 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/repository"
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -30,6 +32,7 @@ type inventoryMovementService struct {
movementRepo repository.InventoryMovementRepository movementRepo repository.InventoryMovementRepository
movementLineRepo repository.InventoryMovementLineRepository movementLineRepo repository.InventoryMovementLineRepository
sequenceService sequenceservice.SequenceService sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
// GetLinesByMovementId implements InventoryMovementService. // GetLinesByMovementId implements InventoryMovementService.
@ -73,6 +76,7 @@ func (s *inventoryMovementService) Create(ctx context.Context, req dtodomain.Inv
Status: req.Status, Status: req.Status,
SourceLocationID: uuid.MustParse(req.SourceLocationID), SourceLocationID: uuid.MustParse(req.SourceLocationID),
DestinationLocationID: uuid.MustParse(req.DestinationLocationID), DestinationLocationID: uuid.MustParse(req.DestinationLocationID),
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.movementRepo.Create(ctx, tx, movement) created, err := s.movementRepo.Create(ctx, tx, movement)
if err != nil { if err != nil {
@ -116,6 +120,14 @@ func (s *inventoryMovementService) Create(ctx context.Context, req dtodomain.Inv
if err != nil { if err != nil {
return dtodomain.InventoryMovementResponse{}, err return dtodomain.InventoryMovementResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "inventory_movement",
"entity_id": created.ID.String(),
}).Info("Inventory Movement created")
return dtodomain.ToInventoryMovementResponse(result), nil return dtodomain.ToInventoryMovementResponse(result), nil
} }
@ -154,12 +166,14 @@ func (s *inventoryMovementService) Update(ctx context.Context, req dtodomain.Inv
tx.Rollback() tx.Rollback()
return dtodomain.InventoryMovementResponse{}, err return dtodomain.InventoryMovementResponse{}, err
} }
// if req.MovementNumber != "" {
// movement.MovementNumber = req.MovementNumber before := movement
// }
movement.MovementDate = utils.StringToDateTime(req.MovementDate) movement.MovementDate = utils.StringToDateTime(req.MovementDate)
movement.MovementType = req.MovementType movement.MovementType = req.MovementType
movement.Status = req.Status movement.Status = req.Status
movement.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.movementRepo.Update(ctx, tx, movement) updated, err := s.movementRepo.Update(ctx, tx, movement)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -170,6 +184,15 @@ func (s *inventoryMovementService) Update(ctx context.Context, req dtodomain.Inv
if err != nil { if err != nil {
return dtodomain.InventoryMovementResponse{}, err return dtodomain.InventoryMovementResponse{}, err
} }
changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "inventory_movement",
"entity_id": id,
"changes": changes,
}).Info("Inventory Movement updated")
return dtodomain.ToInventoryMovementResponse(result), nil return dtodomain.ToInventoryMovementResponse(result), nil
} }
@ -180,11 +203,29 @@ func (s *inventoryMovementService) Delete(ctx context.Context, id string) error
tx.Rollback() tx.Rollback()
} }
}() }()
movement, err := s.movementRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return err
}
movement.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.movementRepo.Update(ctx, tx, movement); err != nil {
tx.Rollback()
return err
}
if err := s.movementRepo.Delete(ctx, tx, id); err != nil { if err := s.movementRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "inventory_movement",
"entity_id": id,
}).Info("Inventory Movement deleted")
return nil return nil
} }
@ -211,11 +252,19 @@ func (s *inventoryMovementService) CreateLine(ctx context.Context, movementId st
StorageID: uuid.MustParse(req.StorageID), StorageID: uuid.MustParse(req.StorageID),
ClientID: clientLineUUID, ClientID: clientLineUUID,
Status: req.Status, Status: req.Status,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.movementLineRepo.Create(ctx, nil, line) created, err := s.movementLineRepo.Create(ctx, nil, line)
if err != nil { if err != nil {
return dtodomain.InventoryMovementLineResponse{}, err return dtodomain.InventoryMovementLineResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "inventory_movement_line",
"entity_id": created.ID.String(),
}).Info("Inventory Movement Line created")
return dtodomain.ToInventoryMovementLineResponse(created), nil return dtodomain.ToInventoryMovementLineResponse(created), nil
} }
@ -224,6 +273,7 @@ func (s *inventoryMovementService) UpdateLine(ctx context.Context, lineId string
if err != nil { if err != nil {
return dtodomain.InventoryMovementLineResponse{}, err return dtodomain.InventoryMovementLineResponse{}, err
} }
before := line
if req.MovedQuantity != nil { if req.MovedQuantity != nil {
line.MovedQuantity = *req.MovedQuantity line.MovedQuantity = *req.MovedQuantity
} }
@ -234,18 +284,47 @@ func (s *inventoryMovementService) UpdateLine(ctx context.Context, lineId string
if err != nil { if err != nil {
return dtodomain.InventoryMovementLineResponse{}, err return dtodomain.InventoryMovementLineResponse{}, err
} }
changes := utils.GetChangedFields(before, updated)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "inventory_movement_line",
"entity_id": lineId,
"changes": changes,
}).Info("Inventory Movement Line updated")
return dtodomain.ToInventoryMovementLineResponse(updated), nil return dtodomain.ToInventoryMovementLineResponse(updated), nil
} }
func (s *inventoryMovementService) DeleteLine(ctx context.Context, lineId string) error { func (s *inventoryMovementService) DeleteLine(ctx context.Context, lineId string) error {
return s.movementLineRepo.Delete(ctx, nil, lineId) line, err := s.movementLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return err
}
line.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.movementLineRepo.Update(ctx, nil, line); err != nil {
return err
}
result := s.movementLineRepo.Delete(ctx, nil, lineId)
if result != nil {
return result
}
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "inventory_movement_line",
"entity_id": lineId,
}).Info("Inventory Movement Line deleted")
return nil
} }
func NewInventoryMovementService(db *gorm.DB, movementRepo repository.InventoryMovementRepository, movementLineRepo repository.InventoryMovementLineRepository, sequenceService sequenceservice.SequenceService) InventoryMovementService { func NewInventoryMovementService(db *gorm.DB, movementRepo repository.InventoryMovementRepository, movementLineRepo repository.InventoryMovementLineRepository, sequenceService sequenceservice.SequenceService, log *logrus.Logger) InventoryMovementService {
return &inventoryMovementService{ return &inventoryMovementService{
db: db, db: db,
movementRepo: movementRepo, movementRepo: movementRepo,
movementLineRepo: movementLineRepo, movementLineRepo: movementLineRepo,
sequenceService: sequenceService, sequenceService: sequenceService,
log: log,
} }
} }

View File

@ -16,6 +16,7 @@ import (
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -40,6 +41,7 @@ type inventoryReceiptService struct {
uomRepo uomrepository.UomRepository uomRepo uomrepository.UomRepository
invStorageRepository invstoragerepository.InventoryStorageRepository invStorageRepository invstoragerepository.InventoryStorageRepository
sequenceService sequenceservice.SequenceService sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
func (s *inventoryReceiptService) GetLinesByReceiptId(ctx context.Context, id string) ([]dtodomain.InventoryReceiptLineResponse, error) { func (s *inventoryReceiptService) GetLinesByReceiptId(ctx context.Context, id string) ([]dtodomain.InventoryReceiptLineResponse, error) {
@ -115,7 +117,28 @@ func (s *inventoryReceiptService) OnComplete(ctx context.Context, id string) (dt
// DeleteLine implements InventoryReceiptService. // DeleteLine implements InventoryReceiptService.
func (s *inventoryReceiptService) DeleteLine(ctx context.Context, lineId string) error { func (s *inventoryReceiptService) DeleteLine(ctx context.Context, lineId string) error {
return s.receiptLineRepo.Delete(ctx, nil, lineId) line, err := s.receiptLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return err
}
line.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
_, err = s.receiptLineRepo.Update(ctx, nil, line)
if err != nil {
return err
}
result := s.receiptLineRepo.Delete(ctx, nil, lineId)
if result != nil {
return result
}
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "inventory_receipt_line",
"entity_id": lineId,
}).Info("Inventory Receipt Line deleted")
return nil
} }
// UpdateLine implements InventoryReceiptService. // UpdateLine implements InventoryReceiptService.
@ -124,6 +147,9 @@ func (s *inventoryReceiptService) UpdateLine(ctx context.Context, lineId string,
if err != nil { if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err return dtodomain.InventoryReceiptLineResponse{}, err
} }
before := line
if req.Quantity != nil { if req.Quantity != nil {
line.Quantity = *req.Quantity line.Quantity = *req.Quantity
} }
@ -155,10 +181,22 @@ func (s *inventoryReceiptService) UpdateLine(ctx context.Context, lineId string,
line.ProductID = uuid.Nil line.ProductID = uuid.Nil
} }
} }
line.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.receiptLineRepo.Update(ctx, nil, line) updated, err := s.receiptLineRepo.Update(ctx, nil, line)
if err != nil { if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err return dtodomain.InventoryReceiptLineResponse{}, err
} }
changes := utils.GetChangedFields(before, updated)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "inventory_receipt_line",
"entity_id": lineId,
"changes": changes,
}).Info("Inventory Receipt Line updated")
var repackUomID *string var repackUomID *string
if updated.RepackUomID != nil { if updated.RepackUomID != nil {
tmp := updated.RepackUomID.String() tmp := updated.RepackUomID.String()
@ -313,12 +351,14 @@ func (s *inventoryReceiptService) Create(ctx context.Context, req dtodomain.Inve
QrCodeFile: req.QrCodeFile, QrCodeFile: req.QrCodeFile,
ClientID: clientUUID, ClientID: clientUUID,
Status: req.Status, Status: req.Status,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.receiptRepo.Create(ctx, tx, receipt) created, err := s.receiptRepo.Create(ctx, tx, receipt)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
} }
// Bulk create lines // Bulk create lines
var lines []entities.TInventoryReceiptLineEntity var lines []entities.TInventoryReceiptLineEntity
// var invStorages []entities.InventoryStorageEntity // var invStorages []entities.InventoryStorageEntity
@ -403,6 +443,14 @@ func (s *inventoryReceiptService) Create(ctx context.Context, req dtodomain.Inve
// } // }
// } // }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "inventory_receipt",
"entity_id": created.ID.String(),
}).Info("Inventory Receipt created")
result, err := s.receiptRepo.GetById(ctx, nil, created.ID.String()) result, err := s.receiptRepo.GetById(ctx, nil, created.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
@ -445,6 +493,7 @@ func (s *inventoryReceiptService) Update(ctx context.Context, req dtodomain.Inve
tx.Rollback() tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
} }
before := receipt
if req.ReferenceNumber != "" { if req.ReferenceNumber != "" {
receipt.ReferenceNumber = req.ReferenceNumber receipt.ReferenceNumber = req.ReferenceNumber
} }
@ -452,16 +501,27 @@ func (s *inventoryReceiptService) Update(ctx context.Context, req dtodomain.Inve
receipt.Source = req.Source receipt.Source = req.Source
receipt.QrCodeFile = req.QrCodeFile receipt.QrCodeFile = req.QrCodeFile
receipt.Status = req.Status receipt.Status = req.Status
receipt.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.receiptRepo.Update(ctx, tx, receipt) updated, err := s.receiptRepo.Update(ctx, tx, receipt)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
} }
tx.Commit() tx.Commit()
result, err := s.receiptRepo.GetById(ctx, nil, updated.ID.String()) result, err := s.receiptRepo.GetById(ctx, nil, updated.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
} }
changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "inventory_receipt",
"entity_id": id,
"changes": changes,
}).Info("Inventory Receipt updated")
return toInventoryReceiptResponse(result), nil return toInventoryReceiptResponse(result), nil
} }
@ -472,11 +532,30 @@ func (s *inventoryReceiptService) Delete(ctx context.Context, id string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
receipt, err := s.receiptRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return err
}
receipt.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
_, err = s.receiptRepo.Update(ctx, tx, receipt)
if err != nil {
tx.Rollback()
return err
}
if err := s.receiptRepo.Delete(ctx, tx, id); err != nil { if err := s.receiptRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "inventory_receipt",
"entity_id": id,
}).Info("Inventory Receipt deleted")
return nil return nil
} }
@ -528,11 +607,20 @@ func (s *inventoryReceiptService) CreateLine(ctx context.Context, receiptId stri
InvReceiptID: receiptUUID, InvReceiptID: receiptUUID,
ProductID: productUUID, ProductID: productUUID,
ClientID: clientLineUUID, ClientID: clientLineUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.receiptLineRepo.Create(ctx, nil, line) created, err := s.receiptLineRepo.Create(ctx, nil, line)
if err != nil { if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err return dtodomain.InventoryReceiptLineResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "inventory_receipt_line",
"entity_id": created.ID.String(),
}).Info("Inventory Receipt Line created")
var repackUomID *string var repackUomID *string
if created.RepackUomID != nil { if created.RepackUomID != nil {
tmp := created.RepackUomID.String() tmp := created.RepackUomID.String()
@ -564,7 +652,7 @@ func NewInventoryReceiptService(db *gorm.DB,
productRepo productrepository.ProductRepository, productRepo productrepository.ProductRepository,
uomRepo uomrepository.UomRepository, uomRepo uomrepository.UomRepository,
invStorageRepository invstoragerepository.InventoryStorageRepository, invStorageRepository invstoragerepository.InventoryStorageRepository,
sequenceService sequenceservice.SequenceService) InventoryReceiptService { sequenceService sequenceservice.SequenceService, log *logrus.Logger) InventoryReceiptService {
return &inventoryReceiptService{ return &inventoryReceiptService{
db: db, db: db,
receiptRepo: receiptRepo, receiptRepo: receiptRepo,
@ -573,5 +661,6 @@ func NewInventoryReceiptService(db *gorm.DB,
uomRepo: uomRepo, uomRepo: uomRepo,
invStorageRepository: invStorageRepository, invStorageRepository: invStorageRepository,
sequenceService: sequenceService, sequenceService: sequenceService,
log: log,
} }
} }

View File

@ -8,9 +8,11 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/repository"
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -31,6 +33,7 @@ type inventoryRequestService struct {
requestRepo repository.InventoryRequestRepository requestRepo repository.InventoryRequestRepository
requestLineRepo repository.InventoryRequestLineRepository requestLineRepo repository.InventoryRequestLineRepository
sequenceService sequenceservice.SequenceService sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
// GetLinesByRequestId implements InventoryRequestService. // GetLinesByRequestId implements InventoryRequestService.
@ -43,7 +46,29 @@ func (s *inventoryRequestService) GetLinesByRequestId(ctx context.Context, reque
} }
func (s *inventoryRequestService) DeleteLine(ctx context.Context, lineId string) error { func (s *inventoryRequestService) DeleteLine(ctx context.Context, lineId string) error {
return s.requestLineRepo.Delete(ctx, nil, lineId) line, err := s.requestLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return err
}
line.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
_, err = s.requestLineRepo.Update(ctx, nil, line)
if err != nil {
return err
}
result := s.requestLineRepo.Delete(ctx, nil, lineId)
if result != nil {
return result
}
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.DELETE,
"entity": "inventory_request_line",
"entity_id": lineId,
}).Info("Inventory Request Line deleted")
return nil
} }
func (s *inventoryRequestService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryRequestLineUpdateRequest) (dtodomain.InventoryRequestLineResponse, error) { func (s *inventoryRequestService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryRequestLineUpdateRequest) (dtodomain.InventoryRequestLineResponse, error) {
@ -51,6 +76,10 @@ func (s *inventoryRequestService) UpdateLine(ctx context.Context, lineId string,
if err != nil { if err != nil {
return dtodomain.InventoryRequestLineResponse{}, err return dtodomain.InventoryRequestLineResponse{}, err
} }
before := line
line.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
if req.Quantity != nil { if req.Quantity != nil {
line.Quantity = *req.Quantity line.Quantity = *req.Quantity
} }
@ -69,6 +98,16 @@ func (s *inventoryRequestService) UpdateLine(ctx context.Context, lineId string,
if err != nil { if err != nil {
return dtodomain.InventoryRequestLineResponse{}, err return dtodomain.InventoryRequestLineResponse{}, err
} }
changes := utils.GetChangedFields(before, updated)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.UPDATE,
"entity": "inventory_request_line",
"entity_id": lineId,
"changes": changes,
}).Info("Inventory Request Line updated")
product := dtodomain.InventoryRequestLineProductResponse{} product := dtodomain.InventoryRequestLineProductResponse{}
if updated.Product.ID != uuid.Nil { if updated.Product.ID != uuid.Nil {
product = dtodomain.InventoryRequestLineProductResponse{ product = dtodomain.InventoryRequestLineProductResponse{
@ -119,6 +158,7 @@ func (s *inventoryRequestService) Create(ctx context.Context, req dtodomain.Inve
Note: req.Note, Note: req.Note,
ClientID: clientUUID, ClientID: clientUUID,
Status: req.Status, Status: req.Status,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.requestRepo.Create(ctx, tx, request) created, err := s.requestRepo.Create(ctx, tx, request)
if err != nil { if err != nil {
@ -157,6 +197,15 @@ func (s *inventoryRequestService) Create(ctx context.Context, req dtodomain.Inve
} }
} }
tx.Commit() tx.Commit()
// Log the creation of the inventory request
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.CREATE,
"entity": "inventory_request",
"entity_id": created.ID.String(),
}).Info("Inventory Request created")
result, err := s.requestRepo.GetById(ctx, nil, created.ID.String()) result, err := s.requestRepo.GetById(ctx, nil, created.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryRequestResponse{}, err return dtodomain.InventoryRequestResponse{}, err
@ -199,6 +248,11 @@ func (s *inventoryRequestService) Update(ctx context.Context, req dtodomain.Inve
tx.Rollback() tx.Rollback()
return dtodomain.InventoryRequestResponse{}, err return dtodomain.InventoryRequestResponse{}, err
} }
before := request
request.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
if req.ReferenceNumber != "" { if req.ReferenceNumber != "" {
request.ReferenceNumber = req.ReferenceNumber request.ReferenceNumber = req.ReferenceNumber
} }
@ -217,6 +271,15 @@ func (s *inventoryRequestService) Update(ctx context.Context, req dtodomain.Inve
if err != nil { if err != nil {
return dtodomain.InventoryRequestResponse{}, err return dtodomain.InventoryRequestResponse{}, err
} }
changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.UPDATE,
"entity": "inventory_request",
"entity_id": id,
"changes": changes,
}).Info("Inventory Request updated")
return dtodomain.ToInventoryRequestResponse(result), nil return dtodomain.ToInventoryRequestResponse(result), nil
} }
@ -227,11 +290,31 @@ func (s *inventoryRequestService) Delete(ctx context.Context, id string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
request, err := s.requestRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return err
}
request.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.requestRepo.Update(ctx, tx, request); err != nil {
tx.Rollback()
return err
}
if err := s.requestRepo.Delete(ctx, tx, id); err != nil { if err := s.requestRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.DELETE,
"entity": "inventory_request",
"entity_id": id,
}).Info("Inventory Request deleted")
return nil return nil
} }
@ -283,11 +366,12 @@ func (s *inventoryRequestService) CreateLine(ctx context.Context, requestId stri
}, nil }, nil
} }
func NewInventoryRequestService(db *gorm.DB, requestRepo repository.InventoryRequestRepository, requestLineRepo repository.InventoryRequestLineRepository, sequenceService sequenceservice.SequenceService) InventoryRequestService { func NewInventoryRequestService(db *gorm.DB, requestRepo repository.InventoryRequestRepository, requestLineRepo repository.InventoryRequestLineRepository, sequenceService sequenceservice.SequenceService, log *logrus.Logger) InventoryRequestService {
return &inventoryRequestService{ return &inventoryRequestService{
db: db, db: db,
requestRepo: requestRepo, requestRepo: requestRepo,
requestLineRepo: requestLineRepo, requestLineRepo: requestLineRepo,
sequenceService: sequenceService, sequenceService: sequenceService,
log: log,
} }
} }

View File

@ -11,9 +11,11 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_return/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_return/repository"
productrepository "github.com/Caknoooo/go-gin-clean-starter/modules/product/repository" productrepository "github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -36,6 +38,7 @@ type inventoryReturnService struct {
issueLineRepo issueRepository.InventoryIssueLineRepository issueLineRepo issueRepository.InventoryIssueLineRepository
productRepo productrepository.ProductRepository productRepo productrepository.ProductRepository
sequenceService sequenceservice.SequenceService sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
// GetLinesByReturnId implements InventoryReturnService. // GetLinesByReturnId implements InventoryReturnService.
@ -49,7 +52,29 @@ func (s *inventoryReturnService) GetLinesByReturnId(ctx context.Context, returnI
// DeleteLine implements InventoryReturnService. // DeleteLine implements InventoryReturnService.
func (s *inventoryReturnService) DeleteLine(ctx context.Context, lineId string) error { func (s *inventoryReturnService) DeleteLine(ctx context.Context, lineId string) error {
return s.returnLineRepo.Delete(ctx, nil, lineId) ireturn, err := s.returnLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return err
}
ireturn.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
_, err = s.returnLineRepo.Update(ctx, nil, ireturn)
if err != nil {
return err
}
result := s.returnLineRepo.Delete(ctx, nil, lineId)
if result != nil {
return result
}
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.DELETE,
"entity": "inventory_return_line",
"entity_id": lineId,
}).Info("Inventory Return Line deleted")
return nil
} }
// UpdateLine implements InventoryReturnService. // UpdateLine implements InventoryReturnService.
@ -59,6 +84,8 @@ func (s *inventoryReturnService) UpdateLine(ctx context.Context, lineId string,
return dtodomain.InventoryReturnLineResponse{}, err return dtodomain.InventoryReturnLineResponse{}, err
} }
before := line
// Ambil product untuk cek returnable // Ambil product untuk cek returnable
product, err := s.productRepo.GetById(ctx, nil, line.ProductID.String()) product, err := s.productRepo.GetById(ctx, nil, line.ProductID.String())
if err != nil { if err != nil {
@ -87,11 +114,27 @@ func (s *inventoryReturnService) UpdateLine(ctx context.Context, lineId string,
if req.ClientID != nil { if req.ClientID != nil {
line.ClientID = uuid.MustParse(*req.ClientID) line.ClientID = uuid.MustParse(*req.ClientID)
} }
line.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updatedLine, err := s.returnLineRepo.Update(ctx, nil, line) updatedLine, err := s.returnLineRepo.Update(ctx, nil, line)
if err != nil { if err != nil {
return dtodomain.InventoryReturnLineResponse{}, err return dtodomain.InventoryReturnLineResponse{}, err
} }
return dtodomain.ToInventoryReturnLineResponse(updatedLine), nil
result, err := s.returnLineRepo.GetById(ctx, nil, updatedLine.ID.String())
if err != nil {
return dtodomain.InventoryReturnLineResponse{}, err
}
changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.UPDATE,
"entity": "inventory_return_line",
"entity_id": lineId,
"changes": changes,
}).Info("Inventory Return Line updated")
return dtodomain.ToInventoryReturnLineResponse(result), nil
} }
func (s *inventoryReturnService) Create(ctx context.Context, req dtodomain.InventoryReturnCreateRequest) (dtodomain.InventoryReturnResponse, error) { func (s *inventoryReturnService) Create(ctx context.Context, req dtodomain.InventoryReturnCreateRequest) (dtodomain.InventoryReturnResponse, error) {
@ -128,6 +171,7 @@ func (s *inventoryReturnService) Create(ctx context.Context, req dtodomain.Inven
Status: req.Status, Status: req.Status,
InvIssueID: invIssueId, InvIssueID: invIssueId,
ClientID: clientUUID, ClientID: clientUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.returnRepo.Create(ctx, tx, entity) created, err := s.returnRepo.Create(ctx, tx, entity)
if err != nil { if err != nil {
@ -169,6 +213,14 @@ func (s *inventoryReturnService) Create(ctx context.Context, req dtodomain.Inven
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.CREATE,
"entity": "inventory_return",
"entity_id": created.ID.String(),
}).Info("Inventory Return created")
result, err := s.returnRepo.GetById(ctx, nil, created.ID.String()) result, err := s.returnRepo.GetById(ctx, nil, created.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryReturnResponse{}, err return dtodomain.InventoryReturnResponse{}, err
@ -211,11 +263,13 @@ func (s *inventoryReturnService) Update(ctx context.Context, req dtodomain.Inven
tx.Rollback() tx.Rollback()
return dtodomain.InventoryReturnResponse{}, err return dtodomain.InventoryReturnResponse{}, err
} }
before := ret
ret.DocumentDate = utils.StringToDateTime(req.DocumentDate) ret.DocumentDate = utils.StringToDateTime(req.DocumentDate)
ret.Notes = req.Notes ret.Notes = req.Notes
ret.Status = req.Status ret.Status = req.Status
ret.InvIssueID = uuid.MustParse(req.InvIssueID) ret.InvIssueID = uuid.MustParse(req.InvIssueID)
ret.ClientID = uuid.MustParse(req.ClientID) ret.ClientID = uuid.MustParse(req.ClientID)
ret.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.returnRepo.Update(ctx, tx, ret) updated, err := s.returnRepo.Update(ctx, tx, ret)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -226,6 +280,15 @@ func (s *inventoryReturnService) Update(ctx context.Context, req dtodomain.Inven
if err != nil { if err != nil {
return dtodomain.InventoryReturnResponse{}, err return dtodomain.InventoryReturnResponse{}, err
} }
changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.UPDATE,
"entity": "inventory_return",
"entity_id": id,
"changes": changes,
}).Info("Inventory Return updated")
return dtodomain.ToInventoryReturnResponse(result), nil return dtodomain.ToInventoryReturnResponse(result), nil
} }
@ -236,11 +299,31 @@ func (s *inventoryReturnService) Delete(ctx context.Context, id string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
ret, err := s.returnRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return err
}
ret.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.returnRepo.Update(ctx, tx, ret); err != nil {
tx.Rollback()
return err
}
if err := s.returnRepo.Delete(ctx, tx, id); err != nil { if err := s.returnRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.DELETE,
"entity": "inventory_return",
"entity_id": id,
}).Info("Inventory Return deleted")
return nil return nil
} }
@ -264,11 +347,18 @@ func (s *inventoryReturnService) CreateLine(ctx context.Context, returnId string
InvReturnID: invReturnUUID, InvReturnID: invReturnUUID,
ProductID: productUUID, ProductID: productUUID,
ClientID: clientUUID, ClientID: clientUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.returnLineRepo.Create(ctx, nil, line) created, err := s.returnLineRepo.Create(ctx, nil, line)
if err != nil { if err != nil {
return dtodomain.InventoryReturnLineResponse{}, err return dtodomain.InventoryReturnLineResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.CREATE,
"entity": "inventory_return_line",
"entity_id": created.ID.String(),
}).Info("Inventory Return Line created")
return dtodomain.ToInventoryReturnLineResponse(created), nil return dtodomain.ToInventoryReturnLineResponse(created), nil
} }
@ -279,6 +369,7 @@ func NewInventoryReturnService(
issueLineRepo issueRepository.InventoryIssueLineRepository, issueLineRepo issueRepository.InventoryIssueLineRepository,
productRepo productrepository.ProductRepository, productRepo productrepository.ProductRepository,
sequenceService sequenceservice.SequenceService, sequenceService sequenceservice.SequenceService,
log *logrus.Logger,
) InventoryReturnService { ) InventoryReturnService {
return &inventoryReturnService{ return &inventoryReturnService{
db: db, db: db,
@ -287,5 +378,6 @@ func NewInventoryReturnService(
issueLineRepo: issueLineRepo, issueLineRepo: issueLineRepo,
productRepo: productRepo, productRepo: productRepo,
sequenceService: sequenceService, sequenceService: sequenceService,
log: log,
} }
} }

View File

@ -7,7 +7,10 @@ import (
dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/dto" dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/repository"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -22,6 +25,7 @@ type InventoryStorageService interface {
type inventoryStorageService struct { type inventoryStorageService struct {
db *gorm.DB db *gorm.DB
inventoryStorageRepo repository.InventoryStorageRepository inventoryStorageRepo repository.InventoryStorageRepository
log *logrus.Logger
} }
func (s *inventoryStorageService) Create(ctx context.Context, req dtodomain.InventoryStorageCreateRequest) (dtodomain.InventoryStorageResponse, error) { func (s *inventoryStorageService) Create(ctx context.Context, req dtodomain.InventoryStorageCreateRequest) (dtodomain.InventoryStorageResponse, error) {
@ -80,6 +84,7 @@ func (s *inventoryStorageService) Create(ctx context.Context, req dtodomain.Inve
InvReceiptID: InvReceiptID, InvReceiptID: InvReceiptID,
OnHandQuantity: req.OnHandQuantity, OnHandQuantity: req.OnHandQuantity,
AvailableQuantity: req.AvailableQuantity, AvailableQuantity: req.AvailableQuantity,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.inventoryStorageRepo.Create(ctx, tx, inventoryStorage) created, err := s.inventoryStorageRepo.Create(ctx, tx, inventoryStorage)
if err != nil { if err != nil {
@ -87,6 +92,14 @@ func (s *inventoryStorageService) Create(ctx context.Context, req dtodomain.Inve
return dtodomain.InventoryStorageResponse{}, err return dtodomain.InventoryStorageResponse{}, err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.CREATE,
"entity": "inventory_storage",
"entity_id": created.ID.String(),
}).Info("Inventory Storage created")
result, err := s.inventoryStorageRepo.GetById(ctx, nil, created.ID.String()) result, err := s.inventoryStorageRepo.GetById(ctx, nil, created.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryStorageResponse{}, err return dtodomain.InventoryStorageResponse{}, err
@ -129,8 +142,10 @@ func (s *inventoryStorageService) Update(ctx context.Context, req dtodomain.Inve
tx.Rollback() tx.Rollback()
return dtodomain.InventoryStorageResponse{}, err return dtodomain.InventoryStorageResponse{}, err
} }
before := inventoryStorage
inventoryStorage.OnHandQuantity = req.OnHandQuantity inventoryStorage.OnHandQuantity = req.OnHandQuantity
inventoryStorage.AvailableQuantity = req.AvailableQuantity inventoryStorage.AvailableQuantity = req.AvailableQuantity
inventoryStorage.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.inventoryStorageRepo.Update(ctx, tx, inventoryStorage) updated, err := s.inventoryStorageRepo.Update(ctx, tx, inventoryStorage)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -141,6 +156,16 @@ func (s *inventoryStorageService) Update(ctx context.Context, req dtodomain.Inve
if err != nil { if err != nil {
return dtodomain.InventoryStorageResponse{}, err return dtodomain.InventoryStorageResponse{}, err
} }
changes := utils.GetChangedFields(before, inventoryStorage)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.UPDATE,
"entity": "inventory_storage",
"entity_id": inventoryStorageId,
"changes": changes,
}).Info("Inventory Storage updated")
return dtodomain.ToInventoryStorageResponse(result), nil return dtodomain.ToInventoryStorageResponse(result), nil
} }
@ -151,17 +176,38 @@ func (s *inventoryStorageService) Delete(ctx context.Context, inventoryStorageId
tx.Rollback() tx.Rollback()
} }
}() }()
invStorage, err := s.inventoryStorageRepo.GetById(ctx, tx, inventoryStorageId)
if err != nil {
tx.Rollback()
return err
}
invStorage.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.inventoryStorageRepo.Update(ctx, tx, invStorage); err != nil {
tx.Rollback()
return err
}
if err := s.inventoryStorageRepo.Delete(ctx, tx, inventoryStorageId); err != nil { if err := s.inventoryStorageRepo.Delete(ctx, tx, inventoryStorageId); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.DELETE,
"entity": "inventory_storage",
"entity_id": inventoryStorageId,
}).Info("Inventory Storage deleted")
return nil return nil
} }
func NewInventoryStorageService(db *gorm.DB, inventoryStorageRepo repository.InventoryStorageRepository) InventoryStorageService { func NewInventoryStorageService(db *gorm.DB, inventoryStorageRepo repository.InventoryStorageRepository, log *logrus.Logger) InventoryStorageService {
return &inventoryStorageService{ return &inventoryStorageService{
db: db, db: db,
inventoryStorageRepo: inventoryStorageRepo, inventoryStorageRepo: inventoryStorageRepo,
log: log,
} }
} }

View File

@ -7,8 +7,10 @@ import (
dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_transaction/dto" dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_transaction/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_transaction/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_transaction/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_transaction/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_transaction/repository"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -23,6 +25,7 @@ type InventoryTransactionService interface {
type inventoryTransactionService struct { type inventoryTransactionService struct {
db *gorm.DB db *gorm.DB
inventoryTransactionRepo repository.InventoryTransactionRepository inventoryTransactionRepo repository.InventoryTransactionRepository
log *logrus.Logger
} }
func (s *inventoryTransactionService) Create(ctx context.Context, req dtodomain.InventoryTransactionCreateRequest) (dtodomain.InventoryTransactionResponse, error) { func (s *inventoryTransactionService) Create(ctx context.Context, req dtodomain.InventoryTransactionCreateRequest) (dtodomain.InventoryTransactionResponse, error) {
@ -77,6 +80,7 @@ func (s *inventoryTransactionService) Create(ctx context.Context, req dtodomain.
InvReceiptID: invReceiptUUID, InvReceiptID: invReceiptUUID,
InvIssueID: invIssueUUID, InvIssueID: invIssueUUID,
InvMoveID: invMoveUUID, InvMoveID: invMoveUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.inventoryTransactionRepo.Create(ctx, tx, entity) created, err := s.inventoryTransactionRepo.Create(ctx, tx, entity)
if err != nil { if err != nil {
@ -84,6 +88,12 @@ func (s *inventoryTransactionService) Create(ctx context.Context, req dtodomain.
return dtodomain.InventoryTransactionResponse{}, err return dtodomain.InventoryTransactionResponse{}, err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.CREATE,
"entity": "inventory_transaction",
"entity_id": created.ID.String(),
}).Info("Inventory Transaction created")
result, err := s.inventoryTransactionRepo.GetById(ctx, nil, created.ID.String()) result, err := s.inventoryTransactionRepo.GetById(ctx, nil, created.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryTransactionResponse{}, err return dtodomain.InventoryTransactionResponse{}, err
@ -126,6 +136,9 @@ func (s *inventoryTransactionService) Update(ctx context.Context, req dtodomain.
tx.Rollback() tx.Rollback()
return dtodomain.InventoryTransactionResponse{}, err return dtodomain.InventoryTransactionResponse{}, err
} }
before := entity
if req.TransactionType != "" { if req.TransactionType != "" {
entity.TransactionType = req.TransactionType entity.TransactionType = req.TransactionType
} }
@ -163,12 +176,23 @@ func (s *inventoryTransactionService) Update(ctx context.Context, req dtodomain.
entity.InvMoveID = &invMoveUUID entity.InvMoveID = &invMoveUUID
} }
} }
entity.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.inventoryTransactionRepo.Update(ctx, tx, entity) updated, err := s.inventoryTransactionRepo.Update(ctx, tx, entity)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return dtodomain.InventoryTransactionResponse{}, err return dtodomain.InventoryTransactionResponse{}, err
} }
tx.Commit() tx.Commit()
changes := utils.GetChangedFields(before, updated)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.UPDATE,
"entity": "inventory_transaction",
"entity_id": updated.ID.String(),
"changes": changes,
}).Info("Inventory Transaction updated")
result, err := s.inventoryTransactionRepo.GetById(ctx, nil, updated.ID.String()) result, err := s.inventoryTransactionRepo.GetById(ctx, nil, updated.ID.String())
if err != nil { if err != nil {
return dtodomain.InventoryTransactionResponse{}, err return dtodomain.InventoryTransactionResponse{}, err
@ -183,17 +207,37 @@ func (s *inventoryTransactionService) Delete(ctx context.Context, inventoryTrans
tx.Rollback() tx.Rollback()
} }
}() }()
invTransaction, err := s.inventoryTransactionRepo.GetById(ctx, tx, inventoryTransactionId)
if err != nil {
tx.Rollback()
return err
}
invTransaction.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.inventoryTransactionRepo.Update(ctx, tx, invTransaction); err != nil {
tx.Rollback()
return err
}
if err := s.inventoryTransactionRepo.Delete(ctx, tx, inventoryTransactionId); err != nil { if err := s.inventoryTransactionRepo.Delete(ctx, tx, inventoryTransactionId); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": constants.DELETE,
"entity": "inventory_transaction",
"entity_id": inventoryTransactionId,
}).Info("Inventory Transaction deleted")
return nil return nil
} }
func NewInventoryTransactionService(db *gorm.DB, repo repository.InventoryTransactionRepository) InventoryTransactionService { func NewInventoryTransactionService(db *gorm.DB, repo repository.InventoryTransactionRepository, log *logrus.Logger) InventoryTransactionService {
return &inventoryTransactionService{ return &inventoryTransactionService{
db: db, db: db,
inventoryTransactionRepo: repo, inventoryTransactionRepo: repo,
log: log,
} }
} }

View File

@ -4,7 +4,7 @@ import (
"errors" "errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -71,8 +71,8 @@ type (
Mode string `json:"mode"` Mode string `json:"mode"`
Status string `json:"status"` Status string `json:"status"`
Parent *MenuParentResponse `json:"parent"` Parent *MenuParentResponse `json:"parent"`
Permissions []dto.PermissionResponse `json:"permissions,omitempty"` Permissions []pkgdto.PermissionResponse `json:"permissions,omitempty"`
Clients []dto.ClientResponse `json:"clients,omitempty"` Clients []pkgdto.ClientResponse `json:"clients,omitempty"`
} }
MenuParentResponse struct { MenuParentResponse struct {
@ -82,7 +82,7 @@ type (
GetAllMenuRepositoryResponse struct { GetAllMenuRepositoryResponse struct {
Menus []entities.M_Menu `json:"menus"` Menus []entities.M_Menu `json:"menus"`
dto.PaginationResponse pkgdto.PaginationResponse
} }
MenuUpdateRequest struct { MenuUpdateRequest struct {
@ -96,3 +96,33 @@ type (
ParentID *uuid.UUID `json:"parent_id" form:"parent_id" binding:"omitempty"` ParentID *uuid.UUID `json:"parent_id" form:"parent_id" binding:"omitempty"`
} }
) )
func ToMenuResponse(entity entities.M_Menu) MenuResponse {
res := MenuResponse{
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
}
if entity.Parent != nil {
res.Parent = &MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &MenuParentResponse{ID: entity.ParentID.String()}
}
if len(entity.Permissions) > 0 {
res.Permissions = make([]pkgdto.PermissionResponse, 0, len(entity.Permissions))
for _, perm := range entity.Permissions {
res.Permissions = append(res.Permissions, pkgdto.PermissionResponse{
ID: perm.ID.String(),
Name: perm.Name,
})
}
}
return res
}

View File

@ -8,8 +8,8 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/auth/service" "github.com/Caknoooo/go-gin-clean-starter/modules/auth/service"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/menu/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/menu/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/menu/repository"
staticDto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -26,6 +26,7 @@ type menuService struct {
menuRepository repository.MenuRepository menuRepository repository.MenuRepository
jwtService service.JWTService jwtService service.JWTService
db *gorm.DB db *gorm.DB
log *logrus.Logger
} }
// GetAll implements MenuService. // GetAll implements MenuService.
@ -37,38 +38,8 @@ func (m *menuService) GetAll(ctx context.Context) ([]dto.MenuResponse, error) {
responses := make([]dto.MenuResponse, 0, len(entities)) responses := make([]dto.MenuResponse, 0, len(entities))
for _, entity := range entities { for _, entity := range entities {
res := dto.MenuResponse{ responses = append(responses, dto.ToMenuResponse(entity))
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
} }
if entity.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: entity.ParentID.String()}
}
if len(entity.Permissions) > 0 {
res.Permissions = make([]staticDto.PermissionResponse, 0, len(entity.Permissions))
for _, perm := range entity.Permissions {
res.Permissions = append(res.Permissions, staticDto.PermissionResponse{
ID: perm.ID.String(),
Name: perm.Name,
})
}
}
responses = append(responses, res)
}
return responses, nil return responses, nil
} }
@ -111,25 +82,7 @@ func (m *menuService) Create(ctx context.Context, menu dto.MenuResponse) (dto.Me
return dto.MenuResponse{}, err return dto.MenuResponse{}, err
} }
// map back to DTO res := dto.ToMenuResponse(created)
res := dto.MenuResponse{
ID: created.ID.String(),
Name: created.Name,
IconUrl: created.IconUrl,
Url: created.Url,
Sequence: created.Sequence,
Mode: created.Mode,
Status: created.Status,
}
if created.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: created.Parent.ID.String(),
Name: created.Parent.Name,
}
} else if created.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: created.ParentID.String()}
}
return res, nil return res, nil
} }
@ -147,37 +100,7 @@ func (m *menuService) GetById(ctx context.Context, menuId string) (dto.MenuRespo
return dto.MenuResponse{}, err return dto.MenuResponse{}, err
} }
res := dto.MenuResponse{ return dto.ToMenuResponse(entity), nil
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
}
if entity.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: entity.ParentID.String()}
}
if len(entity.Permissions) > 0 {
res.Permissions = make([]staticDto.PermissionResponse, 0, len(entity.Permissions))
for _, perm := range entity.Permissions {
res.Permissions = append(res.Permissions, staticDto.PermissionResponse{
ID: perm.ID.String(),
Name: perm.Name,
// Description: perm.Description,
// Code: perm.Code,
})
}
}
return res, nil
} }
// GetByName implements MenuService. // GetByName implements MenuService.
@ -187,24 +110,7 @@ func (m *menuService) GetByName(ctx context.Context, name string) (dto.MenuRespo
return dto.MenuResponse{}, err return dto.MenuResponse{}, err
} }
res := dto.MenuResponse{ res := dto.ToMenuResponse(entity)
ID: entity.ID.String(),
Name: entity.Name,
IconUrl: entity.IconUrl,
Url: entity.Url,
Sequence: entity.Sequence,
Mode: entity.Mode,
Status: entity.Status,
}
if entity.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: entity.Parent.ID.String(),
Name: entity.Parent.Name,
}
} else if entity.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: entity.ParentID.String()}
}
return res, nil return res, nil
} }
@ -250,24 +156,7 @@ func (m *menuService) Update(ctx context.Context, menuId string, menu dto.MenuUp
return dto.MenuResponse{}, err return dto.MenuResponse{}, err
} }
res := dto.MenuResponse{ res := dto.ToMenuResponse(updated)
ID: updated.ID.String(),
Name: updated.Name,
IconUrl: updated.IconUrl,
Url: updated.Url,
Sequence: updated.Sequence,
Mode: updated.Mode,
Status: updated.Status,
}
if updated.Parent != nil {
res.Parent = &dto.MenuParentResponse{
ID: updated.Parent.ID.String(),
Name: updated.Parent.Name,
}
} else if updated.ParentID != nil {
res.Parent = &dto.MenuParentResponse{ID: updated.ParentID.String()}
}
return res, nil return res, nil
} }
@ -276,10 +165,12 @@ func NewMenuService(
menuRepo repository.MenuRepository, menuRepo repository.MenuRepository,
jwtService service.JWTService, jwtService service.JWTService,
db *gorm.DB, db *gorm.DB,
log *logrus.Logger,
) MenuService { ) MenuService {
return &menuService{ return &menuService{
menuRepository: menuRepo, menuRepository: menuRepo,
jwtService: jwtService, jwtService: jwtService,
db: db, db: db,
log: log,
} }
} }

View File

@ -3,6 +3,7 @@ package dto
import ( import (
"errors" "errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
) )
@ -52,3 +53,18 @@ type VendorResponse struct {
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
Client pkgdto.IdNameResponse `json:"client"` Client pkgdto.IdNameResponse `json:"client"`
} }
func EntityToVendorResponse(e entities.MVendorEntity) VendorResponse {
return VendorResponse{
ID: e.ID.String(),
SearchKey: e.SearchKey,
Name: e.Name,
Address: e.Address,
ContactPerson: e.ContactPerson,
IsActive: e.IsActive,
Client: pkgdto.IdNameResponse{
ID: e.ClientID.String(),
Name: e.Client.Name,
},
}
}

View File

@ -8,9 +8,11 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/mvendor/query" "github.com/Caknoooo/go-gin-clean-starter/modules/mvendor/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/mvendor/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/mvendor/repository"
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -26,13 +28,15 @@ type vendorService struct {
db *gorm.DB db *gorm.DB
vendorRepo repository.VendorRepository vendorRepo repository.VendorRepository
sequenceService sequenceservice.SequenceService sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
func NewVendorService(vendorRepo repository.VendorRepository, sequenceService sequenceservice.SequenceService, db *gorm.DB) VendorService { func NewVendorService(vendorRepo repository.VendorRepository, sequenceService sequenceservice.SequenceService, db *gorm.DB, log *logrus.Logger) VendorService {
return &vendorService{ return &vendorService{
vendorRepo: vendorRepo, vendorRepo: vendorRepo,
sequenceService: sequenceService, sequenceService: sequenceService,
db: db, db: db,
log: log,
} }
} }
@ -44,6 +48,8 @@ func (s *vendorService) Create(ctx context.Context, req dto.VendorCreateRequest)
} }
}() }()
userID := utils.GetUserID(ctx)
suffix := utils.GetInitials(req.Name) suffix := utils.GetInitials(req.Name)
seqConfig := pkgdto.SequenceConfig{ seqConfig := pkgdto.SequenceConfig{
@ -64,6 +70,7 @@ func (s *vendorService) Create(ctx context.Context, req dto.VendorCreateRequest)
Address: req.Address, Address: req.Address,
ContactPerson: req.ContactPerson, ContactPerson: req.ContactPerson,
IsActive: req.IsActive, IsActive: req.IsActive,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
clientUUID, err := uuid.Parse(req.ClientID) clientUUID, err := uuid.Parse(req.ClientID)
if err != nil { if err != nil {
@ -76,8 +83,16 @@ func (s *vendorService) Create(ctx context.Context, req dto.VendorCreateRequest)
tx.Rollback() tx.Rollback()
return dto.VendorResponse{}, err return dto.VendorResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "create",
"entity": "vendor",
"entity_id": created.ID.String(),
}).Info("Vendor created")
tx.Commit() tx.Commit()
return entityToVendorResponse(created), nil return dto.EntityToVendorResponse(created), nil
} }
func (s *vendorService) GetById(ctx context.Context, vendorId string) (dto.VendorResponse, error) { func (s *vendorService) GetById(ctx context.Context, vendorId string) (dto.VendorResponse, error) {
@ -85,7 +100,7 @@ func (s *vendorService) GetById(ctx context.Context, vendorId string) (dto.Vendo
if err != nil { if err != nil {
return dto.VendorResponse{}, err return dto.VendorResponse{}, err
} }
return entityToVendorResponse(vendor), nil return dto.EntityToVendorResponse(vendor), nil
} }
func (s *vendorService) GetAll(ctx context.Context, filter query.VendorFilter) ([]dto.VendorResponse, int64, error) { func (s *vendorService) GetAll(ctx context.Context, filter query.VendorFilter) ([]dto.VendorResponse, int64, error) {
@ -95,7 +110,7 @@ func (s *vendorService) GetAll(ctx context.Context, filter query.VendorFilter) (
} }
responses := make([]dto.VendorResponse, len(vendors)) responses := make([]dto.VendorResponse, len(vendors))
for i, v := range vendors { for i, v := range vendors {
responses[i] = entityToVendorResponse(v) responses[i] = dto.EntityToVendorResponse(v)
} }
return responses, total, nil return responses, total, nil
} }
@ -107,6 +122,9 @@ func (s *vendorService) Update(ctx context.Context, req dto.VendorUpdateRequest,
tx.Rollback() tx.Rollback()
} }
}() }()
userID := utils.GetUserID(ctx)
vendor, err := s.vendorRepo.GetById(ctx, tx, vendorId) vendor, err := s.vendorRepo.GetById(ctx, tx, vendorId)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -130,13 +148,23 @@ func (s *vendorService) Update(ctx context.Context, req dto.VendorUpdateRequest,
} }
vendor.ClientID = clientUUID vendor.ClientID = clientUUID
} }
vendor.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.vendorRepo.Update(ctx, tx, vendor) updated, err := s.vendorRepo.Update(ctx, tx, vendor)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return dto.VendorResponse{}, err return dto.VendorResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "update",
"entity": "vendor",
"entity_id": vendorId,
}).Info("Vendor updated")
tx.Commit() tx.Commit()
return entityToVendorResponse(updated), nil return dto.EntityToVendorResponse(updated), nil
} }
func (s *vendorService) Delete(ctx context.Context, vendorId string) error { func (s *vendorService) Delete(ctx context.Context, vendorId string) error {
@ -146,26 +174,35 @@ func (s *vendorService) Delete(ctx context.Context, vendorId string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
userID := utils.GetUserID(ctx)
vendor, err := s.vendorRepo.GetById(ctx, tx, vendorId)
if err != nil {
tx.Rollback()
return err
}
vendor.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
_, err = s.vendorRepo.Update(ctx, tx, vendor)
if err != nil {
tx.Rollback()
return err
}
if err := s.vendorRepo.Delete(ctx, tx, vendorId); err != nil { if err := s.vendorRepo.Delete(ctx, tx, vendorId); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
s.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "delete",
"entity": "vendor",
"entity_id": vendorId,
}).Info("Vendor deleted")
tx.Commit() tx.Commit()
return nil return nil
} }
func entityToVendorResponse(e entities.MVendorEntity) dto.VendorResponse {
return dto.VendorResponse{
ID: e.ID.String(),
SearchKey: e.SearchKey,
Name: e.Name,
Address: e.Address,
ContactPerson: e.ContactPerson,
IsActive: e.IsActive,
Client: pkgdto.IdNameResponse{
ID: e.ClientID.String(),
Name: e.Client.Name,
},
}
}

View File

@ -11,8 +11,11 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/product/query" "github.com/Caknoooo/go-gin-clean-starter/modules/product/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/product/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -35,8 +38,8 @@ type productService struct {
inventoryTransactionRepo invtransactionrepo.InventoryTransactionRepository inventoryTransactionRepo invtransactionrepo.InventoryTransactionRepository
inventoryStorageRepo invstoragerepo.InventoryStorageRepository inventoryStorageRepo invstoragerepo.InventoryStorageRepository
categoryRepo categoryrepo.CategoryRepository categoryRepo categoryrepo.CategoryRepository
sequenceService sequenceservice.SequenceService // tambahkan ini sequenceService sequenceservice.SequenceService
log *logrus.Logger
} }
// GetCrossReferencesByProductAndClient implements ProductService. // GetCrossReferencesByProductAndClient implements ProductService.
@ -119,7 +122,7 @@ func (s *productService) RemoveCrossReference(ctx context.Context, productId str
} }
func NewProductService(productRepo repository.ProductRepository, db *gorm.DB, inventoryTransactionRepo invtransactionrepo.InventoryTransactionRepository, func NewProductService(productRepo repository.ProductRepository, db *gorm.DB, inventoryTransactionRepo invtransactionrepo.InventoryTransactionRepository,
inventoryStorageRepo invstoragerepo.InventoryStorageRepository, categoryRepo categoryrepo.CategoryRepository, sequenceService sequenceservice.SequenceService) ProductService { inventoryStorageRepo invstoragerepo.InventoryStorageRepository, categoryRepo categoryrepo.CategoryRepository, sequenceService sequenceservice.SequenceService, log *logrus.Logger) ProductService {
return &productService{ return &productService{
productRepo: productRepo, productRepo: productRepo,
db: db, db: db,
@ -127,6 +130,7 @@ func NewProductService(productRepo repository.ProductRepository, db *gorm.DB, in
inventoryStorageRepo: inventoryStorageRepo, inventoryStorageRepo: inventoryStorageRepo,
categoryRepo: categoryRepo, categoryRepo: categoryRepo,
sequenceService: sequenceService, sequenceService: sequenceService,
log: log,
} }
} }
@ -185,6 +189,8 @@ func (s *productService) Create(ctx context.Context, req dto.ProductCreateReques
CategoryID: &categoryUUID, CategoryID: &categoryUUID,
UomID: &uomUUID, UomID: &uomUUID,
ClientID: clientUUID, ClientID: clientUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
// DimLength: req.DimLength, // DimLength: req.DimLength,
// DimWidth: req.DimWidth, // DimWidth: req.DimWidth,
// DimHeight: req.DimHeight, // DimHeight: req.DimHeight,
@ -221,6 +227,12 @@ func (s *productService) Create(ctx context.Context, req dto.ProductCreateReques
tx.Rollback() tx.Rollback()
return dto.ProductResponse{}, err return dto.ProductResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "product",
"entity_id": created.ID.String(),
}).Info("Product created")
return s.GetById(ctx, created.ID.String()) return s.GetById(ctx, created.ID.String())
} }
@ -362,6 +374,8 @@ func (s *productService) Update(ctx context.Context, req dto.ProductUpdateReques
id := parseUUID(*req.UomToUomID) id := parseUUID(*req.UomToUomID)
product.UomToUomID = &id product.UomToUomID = &id
} }
product.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updated, err := s.productRepo.Update(ctx, tx, product) updated, err := s.productRepo.Update(ctx, tx, product)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -372,6 +386,12 @@ func (s *productService) Update(ctx context.Context, req dto.ProductUpdateReques
tx.Rollback() tx.Rollback()
return dto.ProductResponse{}, err return dto.ProductResponse{}, err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "product",
"entity_id": productId,
}).Info("Product Updated")
return s.GetById(ctx, updated.ID.String()) return s.GetById(ctx, updated.ID.String())
} }
@ -382,7 +402,18 @@ func (s *productService) Delete(ctx context.Context, productId string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
err := s.productRepo.Delete(ctx, tx, productId)
product, err := s.productRepo.GetById(ctx, tx, productId)
if err != nil {
tx.Rollback()
return err
}
product.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.productRepo.Update(ctx, tx, product); err != nil {
tx.Rollback()
return err
}
err = s.productRepo.Delete(ctx, tx, productId)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return err return err
@ -392,6 +423,12 @@ func (s *productService) Delete(ctx context.Context, productId string) error {
tx.Rollback() tx.Rollback()
return err return err
} }
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "product",
"entity_id": productId,
}).Info("Product Deleted")
return nil return nil
} }

View File

@ -3,7 +3,9 @@ package dto
import ( import (
"errors" "errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid"
) )
const ( const (
@ -145,3 +147,57 @@ type AssignMenuRequest struct {
type RemoveMenuRequest struct { type RemoveMenuRequest struct {
MenuID []string `json:"menu_ids" binding:"required,dive,uuid4"` MenuID []string `json:"menu_ids" binding:"required,dive,uuid4"`
} }
func ToRoleResponse(role entities.M_Role) RoleResponse {
var permissions []RolePermissionsResponse
for _, p := range role.Permissions {
permissions = append(permissions, RolePermissionsResponse{
ID: p.ID.String(),
Name: p.Name,
})
}
var client pkgdto.IdNameResponse
if role.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: role.Client.ID.String(),
Name: role.Client.Name,
}
}
var menus []RoleMenuResponse
for _, m := range role.Menus {
var parent *RoleMenuResponse
if m.Parent != nil {
parent = &RoleMenuResponse{
ID: m.Parent.ID.String(),
Name: m.Parent.Name,
IconUrl: m.Parent.IconUrl,
Url: m.Parent.Url,
Sequence: m.Parent.Sequence,
Parent: nil,
}
}
menus = append(menus, RoleMenuResponse{
ID: m.ID.String(),
Name: m.Name,
IconUrl: m.IconUrl,
Url: m.Url,
Sequence: m.Sequence,
Parent: parent,
})
}
return RoleResponse{
ID: role.ID.String(),
Name: role.Name,
Description: role.Description,
IconUrl: role.IconUrl,
Type: role.Type,
HomeUrl: role.HomeUrl,
Level: role.Level,
Client: client,
Permissions: permissions,
Menus: menus,
}
}

View File

@ -11,7 +11,8 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/role/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/role/repository"
userDto "github.com/Caknoooo/go-gin-clean-starter/modules/user/dto" userDto "github.com/Caknoooo/go-gin-clean-starter/modules/user/dto"
userService "github.com/Caknoooo/go-gin-clean-starter/modules/user/service" userService "github.com/Caknoooo/go-gin-clean-starter/modules/user/service"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
@ -40,6 +41,7 @@ type roleService struct {
jwtService service.JWTService jwtService service.JWTService
userService userService.UserService userService userService.UserService
db *gorm.DB db *gorm.DB
log *logrus.Logger
} }
// GetAll implements RoleService. // GetAll implements RoleService.
@ -51,13 +53,12 @@ func (r *roleService) GetAll(ctx context.Context) ([]dto.RoleResponse, error) {
var responses []dto.RoleResponse var responses []dto.RoleResponse
for _, role := range roles { for _, role := range roles {
responses = append(responses, ToRoleResponse(role)) responses = append(responses, dto.ToRoleResponse(role))
} }
return responses, nil return responses, nil
} }
// AssignMenusToRole implements RoleService.
// AssignMenusToRole implements RoleService. // AssignMenusToRole implements RoleService.
func (r *roleService) AssignMenusToRole(ctx context.Context, roleId string, menuIds []string) error { func (r *roleService) AssignMenusToRole(ctx context.Context, roleId string, menuIds []string) error {
if len(menuIds) == 0 { if len(menuIds) == 0 {
@ -257,14 +258,10 @@ func (r *roleService) AssignRolesToUser(ctx context.Context, userId string, role
// CreateRole implements RoleService. // CreateRole implements RoleService.
func (r *roleService) CreateRole(ctx context.Context, req dto.RoleCreateRequest) (dto.RoleResponse, error) { func (r *roleService) CreateRole(ctx context.Context, req dto.RoleCreateRequest) (dto.RoleResponse, error) {
// _, exists, err := r.roleRepo.CheckRoleName(ctx, r.db, req.Name) userID := ""
// if err != nil && err != gorm.ErrRecordNotFound { if ctx != nil {
// return dto.RoleResponse{}, err userID = utils.GetUserID(ctx)
// } }
// if exists {
// return dto.RoleResponse{}, dto.ErrRoleAlreadyExists
// }
clientUUID, err := uuid.Parse(req.ClientID) clientUUID, err := uuid.Parse(req.ClientID)
if err != nil { if err != nil {
return dto.RoleResponse{}, err return dto.RoleResponse{}, err
@ -277,27 +274,49 @@ func (r *roleService) CreateRole(ctx context.Context, req dto.RoleCreateRequest)
Type: req.Type, Type: req.Type,
HomeUrl: req.HomeUrl, HomeUrl: req.HomeUrl,
ClientID: clientUUID, ClientID: clientUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
createdRole, err := r.roleRepo.CreateRole(ctx, r.db, role) createdRole, err := r.roleRepo.CreateRole(ctx, r.db, role)
if err != nil { if err != nil {
return dto.RoleResponse{}, err return dto.RoleResponse{}, err
} }
result, err := r.roleRepo.GetRoleByID(ctx, r.db, createdRole.ID.String()) result, err := r.roleRepo.GetRoleByID(ctx, r.db, createdRole.ID.String())
if err != nil { if err != nil {
return dto.RoleResponse{}, err return dto.RoleResponse{}, err
} }
return ToRoleResponse(result), nil r.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "create",
"entity": "role",
"entity_id": createdRole.ID.String(),
}).Info("Role created")
return dto.ToRoleResponse(result), nil
} }
// DeleteRole implements RoleService. // DeleteRole implements RoleService.
func (r *roleService) DeleteRole(ctx context.Context, id string) error { func (r *roleService) DeleteRole(ctx context.Context, id string) error {
if _, err := r.roleRepo.GetRoleByID(ctx, r.db, id); err != nil { role, err := r.roleRepo.GetRoleByID(ctx, r.db, id)
if err != nil {
return dto.ErrRoleNotFound return dto.ErrRoleNotFound
} }
return r.roleRepo.DeleteRole(ctx, r.db, id) role.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := r.roleRepo.UpdateRole(ctx, r.db, role); err != nil {
return err
}
if err := r.roleRepo.DeleteRole(ctx, r.db, id); err != nil {
return err
}
userID := ""
if ctx != nil {
userID = utils.GetUserID(ctx)
}
r.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "delete",
"entity": "role",
"entity_id": id,
}).Info("Role deleted")
return nil
} }
// GetRoleByID implements RoleService. // GetRoleByID implements RoleService.
@ -307,7 +326,7 @@ func (r *roleService) GetRoleByID(ctx context.Context, id string) (dto.RoleRespo
return dto.RoleResponse{}, err return dto.RoleResponse{}, err
} }
return ToRoleResponse(role), nil return dto.ToRoleResponse(role), nil
} }
// GetRoles implements RoleService. // GetRoles implements RoleService.
@ -316,44 +335,6 @@ func (r *roleService) GetRoles(ctx context.Context, filter query.RoleFilter) ([]
} }
// GetRolesByUserID implements RoleService. // GetRolesByUserID implements RoleService.
// func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dto.RoleResponse, error) {
// if _, err := r.userService.GetUserById(ctx, userId); err != nil {
// return nil, userDto.ErrUserNotFound
// }
// roles, err := r.roleRepo.GetRolesByUserID(ctx, r.db, userId)
// if err != nil {
// logrus.Error("Error fetching roles for user ", userId, ": ", err)
// return nil, err
// }
// logrus.Info("Fetched ", len(roles), " roles for user ", userId)
// var responses []dto.RoleResponse
// for _, role := range roles {
// var permissions []dto.RolePermissionsResponse
// for _, p := range role.Permissions {
// permissions = append(permissions, dto.RolePermissionsResponse{
// ID: p.ID.String(),
// Name: p.Name,
// })
// }
// responses = append(responses, dto.RoleResponse{
// ID: role.ID.String(),
// Name: role.Name,
// Description: role.Description,
// IconUrl: role.IconUrl,
// Type: role.Type,
// HomeUrl: role.HomeUrl,
// ClientID: role.ClientID.String(),
// Permissions: permissions,
// })
// }
// return responses, nil
// }
func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dto.RoleResponse, error) { func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dto.RoleResponse, error) {
if _, err := r.userService.GetUserById(ctx, userId); err != nil { if _, err := r.userService.GetUserById(ctx, userId); err != nil {
return nil, userDto.ErrUserNotFound return nil, userDto.ErrUserNotFound
@ -366,7 +347,7 @@ func (r *roleService) GetRolesByUserID(ctx context.Context, userId string) ([]dt
var responses []dto.RoleResponse var responses []dto.RoleResponse
for _, role := range roles { for _, role := range roles {
responses = append(responses, ToRoleResponse(role)) responses = append(responses, dto.ToRoleResponse(role))
} }
return responses, nil return responses, nil
@ -470,16 +451,8 @@ func (r *roleService) UpdateRole(ctx context.Context, id string, req dto.RoleUpd
if err != nil { if err != nil {
return dto.RoleResponse{}, dto.ErrRoleNotFound return dto.RoleResponse{}, dto.ErrRoleNotFound
} }
before := existingRole
if req.Name != "" { if req.Name != "" {
// _, exists, err := r.roleRepo.CheckRoleName(ctx, r.db, req.Name)
// if err != nil {
// return dto.RoleResponse{}, err
// }
// if exists {
// return dto.RoleResponse{}, dto.ErrRoleAlreadyExists
// }
existingRole.Name = req.Name existingRole.Name = req.Name
} }
if req.Description != "" { if req.Description != "" {
@ -497,72 +470,28 @@ func (r *roleService) UpdateRole(ctx context.Context, id string, req dto.RoleUpd
if req.Level != 0 { if req.Level != 0 {
existingRole.Level = req.Level existingRole.Level = req.Level
} }
existingRole.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
updatedRole, err := r.roleRepo.UpdateRole(ctx, r.db, existingRole) updatedRole, err := r.roleRepo.UpdateRole(ctx, r.db, existingRole)
if err != nil { if err != nil {
return dto.RoleResponse{}, err return dto.RoleResponse{}, err
} }
result, err := r.roleRepo.GetRoleByID(ctx, r.db, updatedRole.ID.String()) result, err := r.roleRepo.GetRoleByID(ctx, r.db, updatedRole.ID.String())
if err != nil { if err != nil {
return dto.RoleResponse{}, err return dto.RoleResponse{}, err
} }
changes := utils.GetChangedFields(before, result)
return ToRoleResponse(result), nil userID := ""
} if ctx != nil {
userID = utils.GetUserID(ctx)
func ToRoleResponse(role entities.M_Role) dto.RoleResponse {
var permissions []dto.RolePermissionsResponse
for _, p := range role.Permissions {
permissions = append(permissions, dto.RolePermissionsResponse{
ID: p.ID.String(),
Name: p.Name,
})
}
var client pkgdto.IdNameResponse
if role.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: role.Client.ID.String(),
Name: role.Client.Name,
}
}
var menus []dto.RoleMenuResponse
for _, m := range role.Menus {
var parent *dto.RoleMenuResponse
if m.Parent != nil {
parent = &dto.RoleMenuResponse{
ID: m.Parent.ID.String(),
Name: m.Parent.Name,
IconUrl: m.Parent.IconUrl,
Url: m.Parent.Url,
Sequence: m.Parent.Sequence,
Parent: nil, // atau rekursif jika ingin nested lebih dalam
}
}
menus = append(menus, dto.RoleMenuResponse{
ID: m.ID.String(),
Name: m.Name,
IconUrl: m.IconUrl,
Url: m.Url,
Sequence: m.Sequence,
Parent: parent,
})
}
return dto.RoleResponse{
ID: role.ID.String(),
Name: role.Name,
Description: role.Description,
IconUrl: role.IconUrl,
Type: role.Type,
HomeUrl: role.HomeUrl,
Level: role.Level,
Client: client,
Permissions: permissions,
Menus: menus,
} }
r.log.WithFields(logrus.Fields{
"user_id": userID,
"action": "update",
"entity": "role",
"entity_id": id,
"changes": changes,
}).Info("Role updated")
return dto.ToRoleResponse(result), nil
} }
func NewRoleService( func NewRoleService(
@ -571,6 +500,7 @@ func NewRoleService(
jwtService service.JWTService, jwtService service.JWTService,
userService userService.UserService, userService userService.UserService,
db *gorm.DB, db *gorm.DB,
log *logrus.Logger,
) RoleService { ) RoleService {
return &roleService{ return &roleService{
roleRepo: roleRepo, roleRepo: roleRepo,
@ -578,5 +508,6 @@ func NewRoleService(
jwtService: jwtService, jwtService: jwtService,
userService: userService, userService: userService,
db: db, db: db,
log: log,
} }
} }

View File

@ -3,7 +3,9 @@ package dto
import ( import (
"errors" "errors"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/google/uuid"
) )
const ( const (
@ -63,3 +65,34 @@ type ZonaResponse struct {
Warehouse pkgdto.IdNameResponse `json:"warehouse"` Warehouse pkgdto.IdNameResponse `json:"warehouse"`
Client pkgdto.IdNameResponse `json:"client"` Client pkgdto.IdNameResponse `json:"client"`
} }
func ToZonaResponse(e entities.MZonaEntity) ZonaResponse {
warehouse := pkgdto.IdNameResponse{}
if e.Warehouse.ID != uuid.Nil {
warehouse = pkgdto.IdNameResponse{
ID: e.Warehouse.ID.String(),
Name: e.Warehouse.Name,
}
}
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
}
}
return ZonaResponse{
ID: e.ID.String(),
Code: e.Code,
Name: e.Name,
Type: e.Type,
Temperature: e.Temperature,
Hazardous: e.Hazardous,
QRCodeZone: e.QRCodeZone,
IsActive: e.IsActive,
Warehouse: warehouse,
Client: client,
}
}

View File

@ -7,8 +7,10 @@ import (
"github.com/Caknoooo/go-gin-clean-starter/modules/zona/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/zona/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/zona/query" "github.com/Caknoooo/go-gin-clean-starter/modules/zona/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/zona/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/zona/repository"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -23,38 +25,7 @@ type ZonaService interface {
type zonaService struct { type zonaService struct {
db *gorm.DB db *gorm.DB
zonaRepo repository.ZonaRepository zonaRepo repository.ZonaRepository
} log *logrus.Logger
func toZonaResponse(e entities.MZonaEntity) dto.ZonaResponse {
warehouse := pkgdto.IdNameResponse{}
if e.Warehouse.ID != uuid.Nil {
warehouse = pkgdto.IdNameResponse{
ID: e.Warehouse.ID.String(),
Name: e.Warehouse.Name,
}
}
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
}
}
return dto.ZonaResponse{
ID: e.ID.String(),
Code: e.Code,
Name: e.Name,
Type: e.Type,
Temperature: e.Temperature,
Hazardous: e.Hazardous,
QRCodeZone: e.QRCodeZone,
IsActive: e.IsActive,
Warehouse: warehouse,
Client: client,
}
} }
func (s *zonaService) Create(ctx context.Context, req dto.ZonaCreateRequest) (dto.ZonaResponse, error) { func (s *zonaService) Create(ctx context.Context, req dto.ZonaCreateRequest) (dto.ZonaResponse, error) {
@ -80,10 +51,9 @@ func (s *zonaService) Create(ctx context.Context, req dto.ZonaCreateRequest) (dt
Type: req.Type, Type: req.Type,
Temperature: req.Temperature, Temperature: req.Temperature,
Hazardous: req.Hazardous, Hazardous: req.Hazardous,
// QRCodeZone: req.QRCodeZone,
// IsActive: req.IsActive,
WarehouseID: warehouseUUID, WarehouseID: warehouseUUID,
ClientID: clientUUID, ClientID: clientUUID,
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
} }
created, err := s.zonaRepo.Create(ctx, tx, zona) created, err := s.zonaRepo.Create(ctx, tx, zona)
if err != nil { if err != nil {
@ -95,7 +65,13 @@ func (s *zonaService) Create(ctx context.Context, req dto.ZonaCreateRequest) (dt
if err != nil { if err != nil {
return dto.ZonaResponse{}, err return dto.ZonaResponse{}, err
} }
return toZonaResponse(result), nil s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "create",
"entity": "zona",
"entity_id": created.ID.String(),
}).Info("Zona created")
return dto.ToZonaResponse(result), nil
} }
func (s *zonaService) GetById(ctx context.Context, zonaId string) (dto.ZonaResponse, error) { func (s *zonaService) GetById(ctx context.Context, zonaId string) (dto.ZonaResponse, error) {
@ -103,7 +79,7 @@ func (s *zonaService) GetById(ctx context.Context, zonaId string) (dto.ZonaRespo
if err != nil { if err != nil {
return dto.ZonaResponse{}, err return dto.ZonaResponse{}, err
} }
return toZonaResponse(zona), nil return dto.ToZonaResponse(zona), nil
} }
func (s *zonaService) GetAll(ctx context.Context, filter query.ZonaFilter) ([]dto.ZonaResponse, int64, error) { func (s *zonaService) GetAll(ctx context.Context, filter query.ZonaFilter) ([]dto.ZonaResponse, int64, error) {
@ -113,7 +89,7 @@ func (s *zonaService) GetAll(ctx context.Context, filter query.ZonaFilter) ([]dt
} }
var responses []dto.ZonaResponse var responses []dto.ZonaResponse
for _, e := range zonas { for _, e := range zonas {
responses = append(responses, toZonaResponse(e)) responses = append(responses, dto.ToZonaResponse(e))
} }
if responses == nil { if responses == nil {
responses = make([]dto.ZonaResponse, 0) responses = make([]dto.ZonaResponse, 0)
@ -133,6 +109,7 @@ func (s *zonaService) Update(ctx context.Context, req dto.ZonaUpdateRequest, zon
tx.Rollback() tx.Rollback()
return dto.ZonaResponse{}, err return dto.ZonaResponse{}, err
} }
before := zona
if req.Code != "" { if req.Code != "" {
zona.Code = req.Code zona.Code = req.Code
} }
@ -144,20 +121,8 @@ func (s *zonaService) Update(ctx context.Context, req dto.ZonaUpdateRequest, zon
} }
zona.Temperature = req.Temperature zona.Temperature = req.Temperature
zona.Hazardous = req.Hazardous zona.Hazardous = req.Hazardous
// zona.QRCodeZone = req.QRCodeZone
zona.IsActive = req.IsActive zona.IsActive = req.IsActive
// if req.WarehouseID != "" { zona.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
// warehouseUUID, err := uuid.Parse(req.WarehouseID)
// if err == nil {
// zona.WarehouseID = warehouseUUID
// }
// }
// if req.ClientID != "" {
// clientUUID, err := uuid.Parse(req.ClientID)
// if err == nil {
// zona.ClientID = clientUUID
// }
// }
updated, err := s.zonaRepo.Update(ctx, tx, zona) updated, err := s.zonaRepo.Update(ctx, tx, zona)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -168,7 +133,15 @@ func (s *zonaService) Update(ctx context.Context, req dto.ZonaUpdateRequest, zon
if err != nil { if err != nil {
return dto.ZonaResponse{}, err return dto.ZonaResponse{}, err
} }
return toZonaResponse(result), nil changes := utils.GetChangedFields(before, result)
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "update",
"entity": "zona",
"entity_id": zonaId,
"changes": changes,
}).Info("Zona updated")
return dto.ToZonaResponse(result), nil
} }
func (s *zonaService) Delete(ctx context.Context, zonaId string) error { func (s *zonaService) Delete(ctx context.Context, zonaId string) error {
@ -178,17 +151,34 @@ func (s *zonaService) Delete(ctx context.Context, zonaId string) error {
tx.Rollback() tx.Rollback()
} }
}() }()
zona, err := s.zonaRepo.GetById(ctx, tx, zonaId)
if err != nil {
tx.Rollback()
return err
}
zona.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
if _, err := s.zonaRepo.Update(ctx, tx, zona); err != nil {
tx.Rollback()
return err
}
if err := s.zonaRepo.Delete(ctx, tx, zonaId); err != nil { if err := s.zonaRepo.Delete(ctx, tx, zonaId); err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
tx.Commit() tx.Commit()
s.log.WithFields(logrus.Fields{
"user_id": utils.GetUserID(ctx),
"action": "delete",
"entity": "zona",
"entity_id": zonaId,
}).Info("Zona deleted")
return nil return nil
} }
func NewZonaService(zonaRepo repository.ZonaRepository, db *gorm.DB) ZonaService { func NewZonaService(zonaRepo repository.ZonaRepository, db *gorm.DB, log *logrus.Logger) ZonaService {
return &zonaService{ return &zonaService{
zonaRepo: zonaRepo, zonaRepo: zonaRepo,
db: db, db: db,
log: log,
} }
} }

View File

@ -175,26 +175,26 @@ func RegisterDependencies(injector *do.Injector) {
// Service // Service
sequenceServ := sequenceService.NewSequenceService(sequenceRepository, db) sequenceServ := sequenceService.NewSequenceService(sequenceRepository, db)
userServ := userService.NewUserService(userRepository, roleRepository, warehouseRepository, clientRepository, refreshTokenRepository, jwtService, db) userServ := userService.NewUserService(userRepository, roleRepository, warehouseRepository, clientRepository, refreshTokenRepository, jwtService, db)
productService := productService.NewProductService(productRepository, db, inventoryTransactionRepository, inventoryStorageRepository, categoryRepository, sequenceServ) productService := productService.NewProductService(productRepository, db, inventoryTransactionRepository, inventoryStorageRepository, categoryRepository, sequenceServ, log)
roleServ := roleService.NewRoleService(roleRepository, refreshTokenRepository, jwtService, userServ, db) roleServ := roleService.NewRoleService(roleRepository, refreshTokenRepository, jwtService, userServ, db, log)
menuSvc := menuService.NewMenuService(menuRepository, jwtService, db) menuSvc := menuService.NewMenuService(menuRepository, jwtService, db, log)
maintenanceGroupServ := maintGroupService.NewMaintenanceGroupService(maintenanceGroupRepository, maintenanceGroupRoleRepository, maintenanceGroupRoleUserRepository, db) maintenanceGroupServ := maintGroupService.NewMaintenanceGroupService(maintenanceGroupRepository, maintenanceGroupRoleRepository, maintenanceGroupRoleUserRepository, db)
clientServ := clientService.NewClientService(clientRepository, db) clientServ := clientService.NewClientService(clientRepository, db, log)
permissionsServ := permissionsService.NewPermissionsService(permissionsRepository, db) permissionsServ := permissionsService.NewPermissionsService(permissionsRepository, db)
categoryServ := categoryService.NewCategoryService(categoryRepository, db) categoryServ := categoryService.NewCategoryService(categoryRepository, db, log)
uomServ := uomService.NewUomService(uomRepository, sequenceServ, db, log) uomServ := uomService.NewUomService(uomRepository, sequenceServ, db, log)
mvendorServ := mvendorService.NewVendorService(mvendorRepository, sequenceServ, db) mvendorServ := mvendorService.NewVendorService(mvendorRepository, sequenceServ, db, log)
warehouseServ := warehouseService.NewWarehouseService(warehouseRepository, db, log) warehouseServ := warehouseService.NewWarehouseService(warehouseRepository, db, log)
zonaServ := zonaService.NewZonaService(zonaRepository, db) zonaServ := zonaService.NewZonaService(zonaRepository, db, log)
aisleServ := aisleService.NewAisleService(aisleRepository, db) aisleServ := aisleService.NewAisleService(aisleRepository, db, log)
inventoryReceiptServ := inventoryReceiptService.NewInventoryReceiptService(db, inventoryReceiptRepository, inventoryReceiptLineRepository, productRepository, uomRepository, inventoryStorageRepository, sequenceServ) inventoryReceiptServ := inventoryReceiptService.NewInventoryReceiptService(db, inventoryReceiptRepository, inventoryReceiptLineRepository, productRepository, uomRepository, inventoryStorageRepository, sequenceServ, log)
assignmentServ := assignmentService.NewAssignmentService(db, assignmentRepository, assignmentUserRepository) assignmentServ := assignmentService.NewAssignmentService(db, assignmentRepository, assignmentUserRepository)
inventoryRequestServ := inventoryRequestService.NewInventoryRequestService(db, inventoryRequestRepository, inventoryRequestLineRepository, sequenceServ) inventoryRequestServ := inventoryRequestService.NewInventoryRequestService(db, inventoryRequestRepository, inventoryRequestLineRepository, sequenceServ, log)
inventoryIssueServ := inventoryIssueService.NewInventoryIssueService(db, inventoryIssueRepository, inventoryIssueLineRepository, sequenceServ) inventoryIssueServ := inventoryIssueService.NewInventoryIssueService(db, inventoryIssueRepository, inventoryIssueLineRepository, sequenceServ, log)
inventoryReturnServ := inventoryReturnService.NewInventoryReturnService(db, inventoryReturnRepository, inventoryReturnLineRepository, inventoryIssueLineRepository, productRepository, sequenceServ) inventoryReturnServ := inventoryReturnService.NewInventoryReturnService(db, inventoryReturnRepository, inventoryReturnLineRepository, inventoryIssueLineRepository, productRepository, sequenceServ, log)
inventoryMovementServ := inventoryMovementService.NewInventoryMovementService(db, inventoryMovementRepository, inventoryMovementLineRepository, sequenceServ) inventoryMovementServ := inventoryMovementService.NewInventoryMovementService(db, inventoryMovementRepository, inventoryMovementLineRepository, sequenceServ, log)
inventoryStorageService := inventoryStorageService.NewInventoryStorageService(db, inventoryStorageRepository) inventoryStorageService := inventoryStorageService.NewInventoryStorageService(db, inventoryStorageRepository, log)
inventoryTransactionServ := inventoryTransactionService.NewInventoryTransactionService(db, inventoryTransactionRepository) inventoryTransactionServ := inventoryTransactionService.NewInventoryTransactionService(db, inventoryTransactionRepository, log)
quarantineServ := quarantineService.NewQuarantineService(db, quarantineRepository, quarantineLineRepository, productRepository, uomRepository, inventoryStorageRepository) quarantineServ := quarantineService.NewQuarantineService(db, quarantineRepository, quarantineLineRepository, productRepository, uomRepository, inventoryStorageRepository)
// Controller // Controller