cargo-platform/internal/usecases/basic_pricing.go
2026-08-25 14:10:33 +07:00

295 lines
10 KiB
Go

package usecases
import (
"cargo-erp-backend/internal/domain"
"cargo-erp-backend/internal/handlers/dto"
"cargo-erp-backend/pkg/datatable"
"cargo-erp-backend/pkg/helpers"
"fmt"
"reflect"
"time"
"gorm.io/gorm"
)
type BasicPricingUsecaseInterface interface {
GetAll(filter dto.BasicPricingFilterAllRequest) ([]dto.CreateBasicPricingResponse, int64, error)
GetList(dto.DataTableRequest) (dto.DataTableResponse, error)
GetByID(id string) (dto.CreateBasicPricingResponse, error)
Create(req dto.CreateBasicPricingRequest, createdBy string, merchantid *string) (dto.CreateBasicPricingResponse, error)
Update(id string, req dto.CreateBasicPricingRequest, updatedBy string) (dto.CreateBasicPricingResponse, error)
Delete(id string) error
}
type BasicPricingUsecase struct {
Helper helpers.HelperInterface
AuthUser domain.User
}
func NewBasicPricingUsecase(helper helpers.HelperInterface, authUser domain.User) BasicPricingUsecaseInterface {
return &BasicPricingUsecase{Helper: helper, AuthUser: authUser}
}
func (u *BasicPricingUsecase) loadComponents(pricingIDs []string) (map[string][]domain.BasicPricingComponent, error) {
if len(pricingIDs) == 0 {
return make(map[string][]domain.BasicPricingComponent), nil
}
var components []domain.BasicPricingComponent
db := u.Helper.GetDB("slave")
if err := db.Where("basic_pricing_id IN ?", pricingIDs).Find(&components).Error; err != nil {
return nil, err
}
componentsMap := make(map[string][]domain.BasicPricingComponent)
for _, c := range components {
if c.BasicPricingID != nil {
componentsMap[*c.BasicPricingID] = append(componentsMap[*c.BasicPricingID], c)
}
}
return componentsMap, nil
}
func (u *BasicPricingUsecase) toResponse(pricing domain.BasicPricing, components []domain.BasicPricingComponent) dto.CreateBasicPricingResponse {
resp := dto.CreateBasicPricingResponse{
ID: pricing.ID,
Name: pricing.Name,
ProvinceSourceID: pricing.ProvinceSourceID,
CitySourceID: pricing.CitySourceID,
DistrictSourceID: pricing.DistrictSourceID,
SubdistrictSourceID: pricing.SubdistrictSourceID,
PostalCodeSourceID: pricing.PostalCodeSourceID,
ProvinceDestinationID: pricing.ProvinceDestinationID,
CityDestinationID: pricing.CityDestinationID,
DistrictDestinationID: pricing.DistrictDestinationID,
SubdistrictDestinationID: pricing.SubdistrictDestinationID,
PostalCodeDestinationID: pricing.PostalCodeDestinationID,
PackageTypeID: pricing.PackageTypeID,
ModaID: pricing.ModaID,
MerchantID: pricing.MerchantID,
}
resp.Components = make([]dto.BasicPricingComponentResponse, 0, len(components))
for _, c := range components {
resp.Components = append(resp.Components, dto.BasicPricingComponentResponse{
ID: c.ID,
CostComponentID: c.CostComponentID,
Value: c.Value,
})
}
return resp
}
func (u *BasicPricingUsecase) GetAll(filter dto.BasicPricingFilterAllRequest) ([]dto.CreateBasicPricingResponse, int64, error) {
var pricings []domain.BasicPricing
var total int64
db := u.Helper.GetDB("slave")
tx := db.Model(&pricings)
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
tx = tx.Where(db.Where("merchant_id IS NULL").Or("merchant_id=?", u.AuthUser.MerchantID))
}
v := reflect.ValueOf(filter)
t := reflect.TypeOf(filter)
for i := 0; i < v.NumField(); i++ {
if v.Field(i).String() != "" {
tagKey := t.Field(i).Tag.Get("form")
tx = tx.Where(fmt.Sprintf("%v=?", tagKey), v.Field(i))
}
}
tx.Model(&domain.BasicPricing{}).Count(&total)
tx.Order("name ASC")
if err := tx.Find(&pricings).Error; err != nil {
return nil, 0, err
}
pricingIDs := make([]string, 0, len(pricings))
for _, p := range pricings {
pricingIDs = append(pricingIDs, p.ID)
}
componentsMap, err := u.loadComponents(pricingIDs)
if err != nil {
return nil, 0, err
}
responses := make([]dto.CreateBasicPricingResponse, 0, len(pricings))
for _, p := range pricings {
components := componentsMap[p.ID]
responses = append(responses, u.toResponse(p, components))
}
return responses, total, nil
}
func (u *BasicPricingUsecase) GetList(req dto.DataTableRequest) (dto.DataTableResponse, error) {
var response dto.DataTableResponse
db := u.Helper.GetDB("slave")
tx := db.Table("basic_pricing").
Joins("LEFT JOIN province AS ps ON basic_pricing.province_source_id=ps.id").
Joins("LEFT JOIN city AS cs ON basic_pricing.city_source_id=cs.id").
Joins("LEFT JOIN province AS pd ON basic_pricing.province_destination_id=pd.id").
Joins("LEFT JOIN city AS cd ON basic_pricing.city_destination_id=cd.id").
Joins("LEFT JOIN merchant ON basic_pricing.merchant_id=merchant.id")
dt := datatable.NewDatatable(tx, req)
coldef := make([]dto.DataTableColDef, 0)
coldef = append(coldef, dto.DataTableColDef{
Field: "basic_pricing.name",
Alias: "name",
})
coldef = append(coldef, dto.DataTableColDef{
Field: "basic_pricing.id",
Alias: "id",
})
response = dt.Render(coldef)
return response, nil
}
func (u *BasicPricingUsecase) GetByID(id string) (dto.CreateBasicPricingResponse, error) {
var pricing domain.BasicPricing
db := u.Helper.GetDB("slave")
if err := db.Where("id = ?", id).First(&pricing).Error; err != nil {
return dto.CreateBasicPricingResponse{}, err
}
var components []domain.BasicPricingComponent
if err := db.Where("basic_pricing_id = ?", id).Find(&components).Error; err != nil {
return dto.CreateBasicPricingResponse{}, err
}
return u.toResponse(pricing, components), nil
}
func (u *BasicPricingUsecase) Create(req dto.CreateBasicPricingRequest, createdBy string, merchantid *string) (dto.CreateBasicPricingResponse, error) {
now := time.Now()
db := u.Helper.GetDB("master")
var pricing domain.BasicPricing
var savedComponents []domain.BasicPricingComponent
err := db.Transaction(func(tx *gorm.DB) error {
pricing = domain.BasicPricing{
Name: &req.Name,
ProvinceSourceID: strPtr(req.ProvinceSourceID),
CitySourceID: strPtr(req.CitySourceID),
DistrictSourceID: strPtr(req.DistrictSourceID),
SubdistrictSourceID: strPtr(req.SubdistrictSourceID),
PostalCodeSourceID: strPtr(req.PostalCodeSourceID),
ProvinceDestinationID: strPtr(req.ProvinceDestinationID),
CityDestinationID: strPtr(req.CityDestinationID),
DistrictDestinationID: strPtr(req.DistrictDestinationID),
SubdistrictDestinationID: strPtr(req.SubdistrictDestinationID),
PostalCodeDestinationID: strPtr(req.PostalCodeDestinationID),
PackageTypeID: strPtr(req.PackageTypeID),
ModaID: strPtr(req.ModaID),
MerchantID: merchantid,
CreatedBy: &createdBy,
CreatedOn: &now,
UpdatedBy: &createdBy,
UpdatedOn: &now,
}
if err := tx.Create(&pricing).Error; err != nil {
return err
}
for _, comp := range req.Components {
c := domain.BasicPricingComponent{
BasicPricingID: &pricing.ID,
CostComponentID: &comp.CostComponentID,
Value: &comp.Value,
}
if err := tx.Create(&c).Error; err != nil {
return err
}
savedComponents = append(savedComponents, c)
}
return nil
})
if err != nil {
return dto.CreateBasicPricingResponse{}, err
}
return u.toResponse(pricing, savedComponents), nil
}
func (u *BasicPricingUsecase) Update(id string, req dto.CreateBasicPricingRequest, updatedBy string) (dto.CreateBasicPricingResponse, error) {
db := u.Helper.GetDB("master")
var pricing domain.BasicPricing
var savedComponents []domain.BasicPricingComponent
err := db.Transaction(func(tx *gorm.DB) error {
q := tx
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
q = tx.Where("merchant_id=?", u.AuthUser.MerchantID)
}
if err := q.Where("id = ?", id).First(&pricing).Error; err != nil {
return err
}
now := time.Now()
pricing.Name = &req.Name
pricing.ProvinceSourceID = strPtr(req.ProvinceSourceID)
pricing.CitySourceID = strPtr(req.CitySourceID)
pricing.DistrictSourceID = strPtr(req.DistrictSourceID)
pricing.SubdistrictSourceID = strPtr(req.SubdistrictSourceID)
pricing.PostalCodeSourceID = strPtr(req.PostalCodeSourceID)
pricing.ProvinceDestinationID = strPtr(req.ProvinceDestinationID)
pricing.CityDestinationID = strPtr(req.CityDestinationID)
pricing.DistrictDestinationID = strPtr(req.DistrictDestinationID)
pricing.SubdistrictDestinationID = strPtr(req.SubdistrictDestinationID)
pricing.PostalCodeDestinationID = strPtr(req.PostalCodeDestinationID)
pricing.PackageTypeID = strPtr(req.PackageTypeID)
pricing.ModaID = strPtr(req.ModaID)
pricing.UpdatedBy = &updatedBy
pricing.UpdatedOn = &now
if err := tx.Save(&pricing).Error; err != nil {
return err
}
if err := tx.Where("basic_pricing_id = ?", id).Delete(&domain.BasicPricingComponent{}).Error; err != nil {
return err
}
for _, comp := range req.Components {
c := domain.BasicPricingComponent{
BasicPricingID: &pricing.ID,
CostComponentID: &comp.CostComponentID,
Value: &comp.Value,
}
if err := tx.Create(&c).Error; err != nil {
return err
}
savedComponents = append(savedComponents, c)
}
return nil
})
if err != nil {
return dto.CreateBasicPricingResponse{}, err
}
return u.toResponse(pricing, savedComponents), nil
}
func (u *BasicPricingUsecase) Delete(id string) error {
db := u.Helper.GetDB("master")
return db.Transaction(func(tx *gorm.DB) error {
q := tx
if u.AuthUser.UsersRole_Relation == nil || u.AuthUser.UsersRole_Relation.RoleKey != "SPM" {
q = tx.Where("merchant_id=?", u.AuthUser.MerchantID)
}
var pricing domain.BasicPricing
if err := q.Where("id = ?", id).First(&pricing).Error; err != nil {
return err
}
if err := tx.Where("basic_pricing_id = ?", id).Delete(&domain.BasicPricingComponent{}).Error; err != nil {
return err
}
if err := tx.Delete(&pricing).Error; err != nil {
return err
}
return nil
})
}
func strPtr(s string) *string {
if s == "" {
return nil
}
return &s
}