Mhamdans17 commited on
Commit
8879e0b
·
1 Parent(s): 5cd9ed5

feat: add max branches and cashiers limit, refine admin UI settings, implement tier-based qris fee

Browse files
controllers/auth_controller.go CHANGED
@@ -686,13 +686,20 @@ func CreateKasir(c *gin.Context) {
686
  return
687
  }
688
 
689
- if !company.EnableMultiKasir {
690
  var kasirCount int64
691
  config.DB.Model(&models.User{}).Where("company_id = ? AND role = ?", *owner.CompanyID, "kasir").Count(&kasirCount)
692
  if kasirCount >= 1 {
693
  c.JSON(http.StatusForbidden, gin.H{"detail": "Paket perusahaan Anda tidak mendukung pembuatan lebih dari 1 kasir"})
694
  return
695
  }
 
 
 
 
 
 
 
696
  }
697
 
698
  hashedPassword, _ := middleware.HashPassword(req.Password)
 
686
  return
687
  }
688
 
689
+ if !company.EnableMultiKasir && company.MaxCashiers <= 0 {
690
  var kasirCount int64
691
  config.DB.Model(&models.User{}).Where("company_id = ? AND role = ?", *owner.CompanyID, "kasir").Count(&kasirCount)
692
  if kasirCount >= 1 {
693
  c.JSON(http.StatusForbidden, gin.H{"detail": "Paket perusahaan Anda tidak mendukung pembuatan lebih dari 1 kasir"})
694
  return
695
  }
696
+ } else if company.MaxCashiers > 0 {
697
+ var kasirCount int64
698
+ config.DB.Model(&models.User{}).Where("company_id = ? AND role = ?", *owner.CompanyID, "kasir").Count(&kasirCount)
699
+ if kasirCount >= int64(company.MaxCashiers) {
700
+ c.JSON(http.StatusForbidden, gin.H{"detail": fmt.Sprintf("Batas maksimal kasir (%d) telah tercapai untuk perusahaan Anda", company.MaxCashiers)})
701
+ return
702
+ }
703
  }
704
 
705
  hashedPassword, _ := middleware.HashPassword(req.Password)
controllers/company_controller.go CHANGED
@@ -26,6 +26,7 @@ type CompanyResponse struct {
26
  IsActive bool `json:"is_active"`
27
  FeePercentage float64 `json:"fee_percentage"`
28
  CashFeeRules string `json:"cash_fee_rules"`
 
29
  QrisFeePercentage float64 `json:"qris_fee_percentage"`
30
  QrisFeeFixed int `json:"qris_fee_fixed"`
31
  QrisFeeMin int `json:"qris_fee_min"`
@@ -37,7 +38,9 @@ type CompanyResponse struct {
37
  EnableMember bool `json:"enable_member"`
38
  EnableVoucher bool `json:"enable_voucher"`
39
  EnableMultiBranch bool `json:"enable_multi_branch"`
 
40
  EnableMultiKasir bool `json:"enable_multi_kasir"`
 
41
  ApprovedAt *time.Time `json:"approved_at"`
42
  OwnerVerified *bool `json:"owner_verified,omitempty"`
43
  OwnerName string `json:"owner_name,omitempty"`
@@ -207,6 +210,7 @@ func ListCompanies(c *gin.Context) {
207
  OwnerPhone: ownerPhone,
208
  PointRules: comp.PointRules,
209
  CashFeeRules: comp.CashFeeRules,
 
210
  QrisFeePercentage: comp.QrisFeePercentage,
211
  QrisFeeFixed: comp.QrisFeeFixed,
212
  QrisFeeMin: comp.QrisFeeMin,
@@ -218,7 +222,9 @@ func ListCompanies(c *gin.Context) {
218
  EnableMember: comp.EnableMember,
219
  EnableVoucher: comp.EnableVoucher,
220
  EnableMultiBranch: comp.EnableMultiBranch,
 
221
  EnableMultiKasir: comp.EnableMultiKasir,
 
222
  CreatedAt: comp.CreatedAt,
223
  })
224
  }
@@ -721,13 +727,20 @@ func CreateBranch(c *gin.Context) {
721
  return
722
  }
723
 
724
- if !company.EnableMultiBranch {
725
  var branchCount int64
726
  config.DB.Model(&models.Branch{}).Where("company_id = ?", *owner.CompanyID).Count(&branchCount)
727
  if branchCount >= 1 {
728
  c.JSON(http.StatusForbidden, gin.H{"detail": "Paket perusahaan Anda tidak mendukung pembuatan lebih dari 1 cabang"})
729
  return
730
  }
 
 
 
 
 
 
 
731
  }
732
 
733
  isPointEnabled := true
@@ -963,7 +976,9 @@ type UpdateCompanySettingsRequest struct {
963
  EnableMember *bool `json:"enable_member"`
964
  EnableVoucher *bool `json:"enable_voucher"`
965
  EnableMultiBranch *bool `json:"enable_multi_branch"`
 
966
  EnableMultiKasir *bool `json:"enable_multi_kasir"`
 
967
  }
968
 
969
  func AdminUpdateCompanySettings(c *gin.Context) {
@@ -1001,6 +1016,12 @@ func AdminUpdateCompanySettings(c *gin.Context) {
1001
  if req.EnableMultiKasir != nil {
1002
  company.EnableMultiKasir = *req.EnableMultiKasir
1003
  }
 
 
 
 
 
 
1004
 
1005
  if err := config.DB.Save(&company).Error; err != nil {
1006
  c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal menyimpan pengaturan"})
 
26
  IsActive bool `json:"is_active"`
27
  FeePercentage float64 `json:"fee_percentage"`
28
  CashFeeRules string `json:"cash_fee_rules"`
29
+ QrisFeeRules string `json:"qris_fee_rules"`
30
  QrisFeePercentage float64 `json:"qris_fee_percentage"`
31
  QrisFeeFixed int `json:"qris_fee_fixed"`
32
  QrisFeeMin int `json:"qris_fee_min"`
 
38
  EnableMember bool `json:"enable_member"`
39
  EnableVoucher bool `json:"enable_voucher"`
40
  EnableMultiBranch bool `json:"enable_multi_branch"`
41
+ MaxBranches int `json:"max_branches"`
42
  EnableMultiKasir bool `json:"enable_multi_kasir"`
43
+ MaxCashiers int `json:"max_cashiers"`
44
  ApprovedAt *time.Time `json:"approved_at"`
45
  OwnerVerified *bool `json:"owner_verified,omitempty"`
46
  OwnerName string `json:"owner_name,omitempty"`
 
210
  OwnerPhone: ownerPhone,
211
  PointRules: comp.PointRules,
212
  CashFeeRules: comp.CashFeeRules,
213
+ QrisFeeRules: comp.QrisFeeRules,
214
  QrisFeePercentage: comp.QrisFeePercentage,
215
  QrisFeeFixed: comp.QrisFeeFixed,
216
  QrisFeeMin: comp.QrisFeeMin,
 
222
  EnableMember: comp.EnableMember,
223
  EnableVoucher: comp.EnableVoucher,
224
  EnableMultiBranch: comp.EnableMultiBranch,
225
+ MaxBranches: comp.MaxBranches,
226
  EnableMultiKasir: comp.EnableMultiKasir,
227
+ MaxCashiers: comp.MaxCashiers,
228
  CreatedAt: comp.CreatedAt,
229
  })
230
  }
 
727
  return
728
  }
729
 
730
+ if !company.EnableMultiBranch && company.MaxBranches <= 0 {
731
  var branchCount int64
732
  config.DB.Model(&models.Branch{}).Where("company_id = ?", *owner.CompanyID).Count(&branchCount)
733
  if branchCount >= 1 {
734
  c.JSON(http.StatusForbidden, gin.H{"detail": "Paket perusahaan Anda tidak mendukung pembuatan lebih dari 1 cabang"})
735
  return
736
  }
737
+ } else if company.MaxBranches > 0 {
738
+ var branchCount int64
739
+ config.DB.Model(&models.Branch{}).Where("company_id = ?", *owner.CompanyID).Count(&branchCount)
740
+ if branchCount >= int64(company.MaxBranches) {
741
+ c.JSON(http.StatusForbidden, gin.H{"detail": fmt.Sprintf("Batas maksimal cabang (%d) telah tercapai untuk perusahaan Anda", company.MaxBranches)})
742
+ return
743
+ }
744
  }
745
 
746
  isPointEnabled := true
 
976
  EnableMember *bool `json:"enable_member"`
977
  EnableVoucher *bool `json:"enable_voucher"`
978
  EnableMultiBranch *bool `json:"enable_multi_branch"`
979
+ MaxBranches *int `json:"max_branches"`
980
  EnableMultiKasir *bool `json:"enable_multi_kasir"`
981
+ MaxCashiers *int `json:"max_cashiers"`
982
  }
983
 
984
  func AdminUpdateCompanySettings(c *gin.Context) {
 
1016
  if req.EnableMultiKasir != nil {
1017
  company.EnableMultiKasir = *req.EnableMultiKasir
1018
  }
1019
+ if req.MaxBranches != nil {
1020
+ company.MaxBranches = *req.MaxBranches
1021
+ }
1022
+ if req.MaxCashiers != nil {
1023
+ company.MaxCashiers = *req.MaxCashiers
1024
+ }
1025
 
1026
  if err := config.DB.Save(&company).Error; err != nil {
1027
  c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal menyimpan pengaturan"})
controllers/fee_controller.go CHANGED
@@ -212,8 +212,17 @@ type CashFeeRule struct {
212
  Fee int `json:"fee"`
213
  }
214
 
 
 
 
 
 
 
 
 
215
  type UpdateFeeRequest struct {
216
  CashFeeRules []CashFeeRule `json:"cash_fee_rules"`
 
217
  QrisFeePercentage float64 `json:"qris_fee_percentage"`
218
  QrisFeeFixed int `json:"qris_fee_fixed"`
219
  QrisFeeMin int `json:"qris_fee_min"`
@@ -252,7 +261,14 @@ func SetCompanyFee(c *gin.Context) {
252
  return
253
  }
254
 
 
 
 
 
 
 
255
  company.CashFeeRules = string(rulesBytes)
 
256
  company.QrisFeePercentage = req.QrisFeePercentage
257
  company.QrisFeeFixed = req.QrisFeeFixed
258
  company.QrisFeeMin = req.QrisFeeMin
 
212
  Fee int `json:"fee"`
213
  }
214
 
215
+ type QrisFeeRule struct {
216
+ MinAmount int `json:"min_amount"`
217
+ MaxAmount int `json:"max_amount"`
218
+ FeePercentage float64 `json:"fee_percentage"`
219
+ FeeFixed int `json:"fee_fixed"`
220
+ FeeMin int `json:"fee_min"`
221
+ }
222
+
223
  type UpdateFeeRequest struct {
224
  CashFeeRules []CashFeeRule `json:"cash_fee_rules"`
225
+ QrisFeeRules []QrisFeeRule `json:"qris_fee_rules"`
226
  QrisFeePercentage float64 `json:"qris_fee_percentage"`
227
  QrisFeeFixed int `json:"qris_fee_fixed"`
228
  QrisFeeMin int `json:"qris_fee_min"`
 
261
  return
262
  }
263
 
264
+ qrisRulesBytes, err := json.Marshal(req.QrisFeeRules)
265
+ if err != nil {
266
+ c.JSON(http.StatusInternalServerError, gin.H{"detail": "Gagal memproses aturan fee qris"})
267
+ return
268
+ }
269
+
270
  company.CashFeeRules = string(rulesBytes)
271
+ company.QrisFeeRules = string(qrisRulesBytes)
272
  company.QrisFeePercentage = req.QrisFeePercentage
273
  company.QrisFeeFixed = req.QrisFeeFixed
274
  company.QrisFeeMin = req.QrisFeeMin
controllers/order_controller.go CHANGED
@@ -808,10 +808,32 @@ func TripayWebhook(c *gin.Context) {
808
  baseAmountForFee = order.SubtotalAmount
809
  }
810
 
811
- fee := int((float64(baseAmountForFee) * company.QrisFeePercentage / 100) + float64(company.QrisFeeFixed))
812
- if fee < company.QrisFeeMin {
813
- fee = company.QrisFeeMin
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
814
  }
 
815
  order.PlatformFee = fee
816
  awardPoints(tx, &order, &company)
817
  }
 
808
  baseAmountForFee = order.SubtotalAmount
809
  }
810
 
811
+ fee := 0
812
+ ruleApplied := false
813
+
814
+ if company.QrisFeeRules != "" && company.QrisFeeRules != "[]" {
815
+ var qrisRules []QrisFeeRule
816
+ if err := json.Unmarshal([]byte(company.QrisFeeRules), &qrisRules); err == nil {
817
+ for _, rule := range qrisRules {
818
+ if baseAmountForFee >= rule.MinAmount && baseAmountForFee <= rule.MaxAmount {
819
+ fee = int((float64(baseAmountForFee) * rule.FeePercentage / 100) + float64(rule.FeeFixed))
820
+ if fee < rule.FeeMin {
821
+ fee = rule.FeeMin
822
+ }
823
+ ruleApplied = true
824
+ break
825
+ }
826
+ }
827
+ }
828
+ }
829
+
830
+ if !ruleApplied {
831
+ fee = int((float64(baseAmountForFee) * company.QrisFeePercentage / 100) + float64(company.QrisFeeFixed))
832
+ if fee < company.QrisFeeMin {
833
+ fee = company.QrisFeeMin
834
+ }
835
  }
836
+
837
  order.PlatformFee = fee
838
  awardPoints(tx, &order, &company)
839
  }
models/models.go CHANGED
@@ -22,6 +22,7 @@ type Company struct {
22
  TripayPrivateKey string `gorm:"type:text" json:"tripay_private_key"`
23
  TripayProxyURL string `gorm:"type:text" json:"tripay_proxy_url"`
24
  CashFeeRules string `gorm:"type:text;default:'[]'" json:"cash_fee_rules"`
 
25
  QrisFeePercentage float64 `gorm:"type:float;default:1.7" json:"qris_fee_percentage"`
26
  QrisFeeFixed int `gorm:"default:500" json:"qris_fee_fixed"`
27
  QrisFeeMin int `gorm:"default:850" json:"qris_fee_min"`
@@ -33,7 +34,9 @@ type Company struct {
33
  EnableMember bool `gorm:"default:true" json:"enable_member"`
34
  EnableVoucher bool `gorm:"default:true" json:"enable_voucher"`
35
  EnableMultiBranch bool `gorm:"default:false" json:"enable_multi_branch"`
 
36
  EnableMultiKasir bool `gorm:"default:false" json:"enable_multi_kasir"`
 
37
  PointRules []PointRule `gorm:"foreignKey:CompanyID;constraint:OnDelete:CASCADE" json:"point_rules"`
38
  CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
39
  Branches []Branch `gorm:"foreignKey:CompanyID;constraint:OnDelete:CASCADE" json:"-"`
 
22
  TripayPrivateKey string `gorm:"type:text" json:"tripay_private_key"`
23
  TripayProxyURL string `gorm:"type:text" json:"tripay_proxy_url"`
24
  CashFeeRules string `gorm:"type:text;default:'[]'" json:"cash_fee_rules"`
25
+ QrisFeeRules string `gorm:"type:text;default:'[]'" json:"qris_fee_rules"`
26
  QrisFeePercentage float64 `gorm:"type:float;default:1.7" json:"qris_fee_percentage"`
27
  QrisFeeFixed int `gorm:"default:500" json:"qris_fee_fixed"`
28
  QrisFeeMin int `gorm:"default:850" json:"qris_fee_min"`
 
34
  EnableMember bool `gorm:"default:true" json:"enable_member"`
35
  EnableVoucher bool `gorm:"default:true" json:"enable_voucher"`
36
  EnableMultiBranch bool `gorm:"default:false" json:"enable_multi_branch"`
37
+ MaxBranches int `gorm:"default:0" json:"max_branches"`
38
  EnableMultiKasir bool `gorm:"default:false" json:"enable_multi_kasir"`
39
+ MaxCashiers int `gorm:"default:0" json:"max_cashiers"`
40
  PointRules []PointRule `gorm:"foreignKey:CompanyID;constraint:OnDelete:CASCADE" json:"point_rules"`
41
  CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
42
  Branches []Branch `gorm:"foreignKey:CompanyID;constraint:OnDelete:CASCADE" json:"-"`