mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Merge branch 'feat/BE/Sprint-6' into 'dev/teguh' - merge all closing methods
This commit is contained in:
@@ -53,15 +53,15 @@ func (u *ClosingController) GetAll(c *fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *ClosingController) GetOne(c *fiber.Ctx) error {
|
func (u *ClosingController) GetClosingSummary(c *fiber.Ctx) error {
|
||||||
param := c.Params("id")
|
param := c.Params("projectFlockId")
|
||||||
|
|
||||||
id, err := strconv.Atoi(param)
|
id, err := strconv.Atoi(param)
|
||||||
if err != nil {
|
if err != nil || id <= 0 {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid projectFlockId")
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := u.ClosingService.GetOne(c, uint(id))
|
result, err := u.ClosingService.GetClosingSummary(c, uint(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -70,8 +70,8 @@ func (u *ClosingController) GetOne(c *fiber.Ctx) error {
|
|||||||
JSON(response.Success{
|
JSON(response.Success{
|
||||||
Code: fiber.StatusOK,
|
Code: fiber.StatusOK,
|
||||||
Status: "success",
|
Status: "success",
|
||||||
Message: "Get closing successfully",
|
Message: "Retrieved project information successfully",
|
||||||
Data: dto.ToClosingListDTO(*result),
|
Data: result,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dto
|
package dto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
@@ -26,6 +27,67 @@ type ClosingDetailDTO struct {
|
|||||||
ClosingListDTO
|
ClosingListDTO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClosingSummaryDTO struct {
|
||||||
|
LocationID uint `json:"location_id"`
|
||||||
|
Periode int `json:"periode"`
|
||||||
|
JenisProduk string `json:"jenis_produk"`
|
||||||
|
LabelPopulasi string `json:"label_populasi"`
|
||||||
|
JumlahPopulasi int `json:"jumlah_populasi"`
|
||||||
|
JumlahPopulasiFormatted string `json:"jumlah_populasi_formatted"`
|
||||||
|
JenisProject string `json:"jenis_project"`
|
||||||
|
KandangAktif int `json:"kandang_aktif"`
|
||||||
|
KandangAktifFormatted string `json:"kandang_aktif_formatted"`
|
||||||
|
StatusPembayaranPenjualan string `json:"status_pembayaran_penjualan"`
|
||||||
|
StatusPembayaranMitra string `json:"status_pembayaran_mitra"`
|
||||||
|
StatusProject string `json:"status_project"`
|
||||||
|
StatusClosing string `json:"status_closing"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToClosingSummaryDTO(project entity.ProjectFlock, statusProject, statusClosing string) ClosingSummaryDTO {
|
||||||
|
history := project.KandangHistory
|
||||||
|
|
||||||
|
period := maxPeriod(history)
|
||||||
|
kandangCount := len(history)
|
||||||
|
population := sumPopulation(history)
|
||||||
|
populationInt := int(population)
|
||||||
|
|
||||||
|
return ClosingSummaryDTO{
|
||||||
|
LocationID: project.LocationId,
|
||||||
|
Periode: period,
|
||||||
|
JenisProduk: project.Category,
|
||||||
|
LabelPopulasi: "",
|
||||||
|
JumlahPopulasi: populationInt,
|
||||||
|
JumlahPopulasiFormatted: fmt.Sprintf("%d Ekor", populationInt),
|
||||||
|
JenisProject: "",
|
||||||
|
KandangAktif: kandangCount,
|
||||||
|
KandangAktifFormatted: fmt.Sprintf("%d Kandang", kandangCount),
|
||||||
|
StatusPembayaranPenjualan: "Tempo",
|
||||||
|
StatusPembayaranMitra: "",
|
||||||
|
StatusProject: statusProject,
|
||||||
|
StatusClosing: statusClosing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxPeriod(history []entity.ProjectFlockKandang) int {
|
||||||
|
max := 0
|
||||||
|
for _, h := range history {
|
||||||
|
if h.Period > max {
|
||||||
|
max = h.Period
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
func sumPopulation(history []entity.ProjectFlockKandang) float64 {
|
||||||
|
var total float64
|
||||||
|
for _, h := range history {
|
||||||
|
for _, chickin := range h.Chickins {
|
||||||
|
total += chickin.UsageQty + chickin.PendingUsageQty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
// === Mapper Functions ===
|
// === Mapper Functions ===
|
||||||
|
|
||||||
func ToClosingRelationDTO(e entity.ProjectFlock) ClosingRelationDTO {
|
func ToClosingRelationDTO(e entity.ProjectFlock) ClosingRelationDTO {
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import (
|
|||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
|
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||||
rClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories"
|
rClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories"
|
||||||
sClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/services"
|
sClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/services"
|
||||||
rMarketings "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
rMarketings "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||||
|
|
||||||
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||||
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||||
)
|
)
|
||||||
@@ -21,7 +22,10 @@ func (ClosingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *
|
|||||||
marketingRepo := rMarketings.NewMarketingRepository(db)
|
marketingRepo := rMarketings.NewMarketingRepository(db)
|
||||||
marketingDeliveryProductRepo := rMarketings.NewMarketingDeliveryProductRepository(db)
|
marketingDeliveryProductRepo := rMarketings.NewMarketingDeliveryProductRepository(db)
|
||||||
|
|
||||||
closingService := sClosing.NewClosingService(closingRepo, marketingRepo, marketingDeliveryProductRepo, validate)
|
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||||
|
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
||||||
|
|
||||||
|
closingService := sClosing.NewClosingService(closingRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, validate)
|
||||||
userService := sUser.NewUserService(userRepo, validate)
|
userService := sUser.NewUserService(userRepo, validate)
|
||||||
|
|
||||||
ClosingRoutes(router, userService, closingService)
|
ClosingRoutes(router, userService, closingService)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService) {
|
func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService) {
|
||||||
ctrl := controller.NewClosingController(s)
|
ctrl := controller.NewClosingController(s)
|
||||||
|
|
||||||
route := v1.Group("/closings")
|
route := v1.Group("/closing")
|
||||||
|
|
||||||
// route.Get("/", m.Auth(u), ctrl.GetAll)
|
// route.Get("/", m.Auth(u), ctrl.GetAll)
|
||||||
// route.Post("/", m.Auth(u), ctrl.CreateOne)
|
// route.Post("/", m.Auth(u), ctrl.CreateOne)
|
||||||
@@ -22,6 +22,6 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService
|
|||||||
|
|
||||||
route.Get("/", ctrl.GetAll)
|
route.Get("/", ctrl.GetAll)
|
||||||
route.Get("/:id", ctrl.GetOne)
|
route.Get("/:id", ctrl.GetOne)
|
||||||
|
route.Get("/:projectFlockId", ctrl.GetClosingSummary)
|
||||||
route.Get("/:project_flock_id/penjualan", ctrl.GetPenjualan)
|
route.Get("/:project_flock_id/penjualan", ctrl.GetPenjualan)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/modules/closings/dto"
|
||||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories"
|
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories"
|
||||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/validations"
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/validations"
|
||||||
marketingDeliveryProductRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
marketingDeliveryProductRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||||
marketingRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
marketingRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
|
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@@ -20,6 +24,7 @@ type ClosingService interface {
|
|||||||
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, error)
|
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, error)
|
||||||
GetOne(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error)
|
GetOne(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error)
|
||||||
GetPenjualan(ctx *fiber.Ctx, projectFlockID uint) ([]entity.MarketingDeliveryProduct, error)
|
GetPenjualan(ctx *fiber.Ctx, projectFlockID uint) ([]entity.MarketingDeliveryProduct, error)
|
||||||
|
GetClosingSummary(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type closingService struct {
|
type closingService struct {
|
||||||
@@ -28,15 +33,17 @@ type closingService struct {
|
|||||||
Repository repository.ClosingRepository
|
Repository repository.ClosingRepository
|
||||||
MarketingRepo marketingRepository.MarketingRepository
|
MarketingRepo marketingRepository.MarketingRepository
|
||||||
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
||||||
|
ApprovalSvc commonSvc.ApprovalService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClosingService(repo repository.ClosingRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, validate *validator.Validate) ClosingService {
|
func NewClosingService(repo repository.ClosingRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, validate *validator.Validate) ClosingService {
|
||||||
return &closingService{
|
return &closingService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
Validate: validate,
|
Validate: validate,
|
||||||
Repository: repo,
|
Repository: repo,
|
||||||
MarketingRepo: marketingRepo,
|
MarketingRepo: marketingRepo,
|
||||||
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
||||||
|
ApprovalSvc: approvalSvc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +51,12 @@ func (s closingService) withRelations(db *gorm.DB) *gorm.DB {
|
|||||||
return db.Preload("CreatedUser")
|
return db.Preload("CreatedUser")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s closingService) withClosingRelations(db *gorm.DB) *gorm.DB {
|
||||||
|
return s.withRelations(db).
|
||||||
|
Preload("KandangHistory").
|
||||||
|
Preload("KandangHistory.Chickins")
|
||||||
|
}
|
||||||
|
|
||||||
func (s closingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, error) {
|
func (s closingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, error) {
|
||||||
if err := s.Validate.Struct(params); err != nil {
|
if err := s.Validate.Struct(params); err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -103,3 +116,73 @@ func (s closingService) GetPenjualan(c *fiber.Ctx, projectFlockID uint) ([]entit
|
|||||||
}
|
}
|
||||||
return realisasi, nil
|
return realisasi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s closingService) GetClosingSummary(c *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error) {
|
||||||
|
if projectFlockID == 0 {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id")
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := s.Repository.GetByID(c.Context(), projectFlockID, s.withClosingRelations)
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, fiber.NewError(fiber.StatusNotFound, "Project flock not found")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Failed get project flock %d for closing summary: %+v", projectFlockID, err)
|
||||||
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch project flock")
|
||||||
|
}
|
||||||
|
|
||||||
|
statusProject, statusClosing, err := s.getApprovalStatuses(c.Context(), projectFlockID)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Failed to retrieve approval statuses for project flock %d: %+v", projectFlockID, err)
|
||||||
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch approval status")
|
||||||
|
}
|
||||||
|
|
||||||
|
summary := dto.ToClosingSummaryDTO(*project, statusProject, statusClosing)
|
||||||
|
|
||||||
|
return &summary, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s closingService) getApprovalStatuses(ctx context.Context, projectFlockID uint) (string, string, error) {
|
||||||
|
if s.ApprovalSvc == nil {
|
||||||
|
return "", "Belum Selesai", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
records, _, err := s.ApprovalSvc.List(ctx, utils.ApprovalWorkflowProjectFlock.String(), &projectFlockID, 1, 1000, "")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
minStep uint16
|
||||||
|
statusProject string
|
||||||
|
completed int
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, rec := range records {
|
||||||
|
if minStep == 0 || rec.StepNumber < minStep {
|
||||||
|
minStep = rec.StepNumber
|
||||||
|
statusProject = rec.StepName
|
||||||
|
}
|
||||||
|
if rec.StepNumber == uint16(utils.ProjectFlockStepSelesai) {
|
||||||
|
completed++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if statusProject == "" && minStep > 0 {
|
||||||
|
if label, ok := approvalutils.ApprovalStepName(utils.ApprovalWorkflowProjectFlock, approvalutils.ApprovalStep(minStep)); ok {
|
||||||
|
statusProject = label
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statusClosing := "Belum Selesai"
|
||||||
|
switch {
|
||||||
|
case len(records) == 0 || completed == 0:
|
||||||
|
statusClosing = "Belum Selesai"
|
||||||
|
case completed < len(records):
|
||||||
|
statusClosing = "Sebagian"
|
||||||
|
default:
|
||||||
|
statusClosing = "Selesai"
|
||||||
|
}
|
||||||
|
|
||||||
|
return statusProject, statusClosing, nil
|
||||||
|
}
|
||||||
|
|||||||
+3
-3
@@ -151,7 +151,7 @@ func (r *ProductWarehouseRepositoryImpl) AdjustQuantities(ctx context.Context, d
|
|||||||
}
|
}
|
||||||
if err := base.Model(&entity.ProductWarehouse{}).
|
if err := base.Model(&entity.ProductWarehouse{}).
|
||||||
Where("id = ?", id).
|
Where("id = ?", id).
|
||||||
Update("quantity", gorm.Expr("COALESCE(quantity,0) + ?", delta)).Error; err != nil {
|
Update("qty", gorm.Expr("COALESCE(qty,0) + ?", delta)).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ func (r *ProductWarehouseRepositoryImpl) CleanupEmpty(ctx context.Context, affec
|
|||||||
var emptyIDs []uint
|
var emptyIDs []uint
|
||||||
if err := r.DB().WithContext(ctx).
|
if err := r.DB().WithContext(ctx).
|
||||||
Model(&entity.ProductWarehouse{}).
|
Model(&entity.ProductWarehouse{}).
|
||||||
Where("id IN ? AND COALESCE(quantity,0) <= 0", ids).
|
Where("id IN ? AND COALESCE(qty,0) <= 0", ids).
|
||||||
Pluck("id", &emptyIDs).Error; err != nil {
|
Pluck("id", &emptyIDs).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ func (r *ProductWarehouseRepositoryImpl) GetByFlagAndWarehouseID(ctx context.Con
|
|||||||
Joins("JOIN products ON products.id = product_warehouses.product_id").
|
Joins("JOIN products ON products.id = product_warehouses.product_id").
|
||||||
Joins("JOIN flags ON flags.flagable_id = products.id AND flags.flagable_type = 'products'").
|
Joins("JOIN flags ON flags.flagable_id = products.id AND flags.flagable_type = 'products'").
|
||||||
Where("flags.name = ? AND product_warehouses.warehouse_id = ?", flagName, warehouseId).
|
Where("flags.name = ? AND product_warehouses.warehouse_id = ?", flagName, warehouseId).
|
||||||
Order("product_warehouses.created_at DESC").
|
Order("product_warehouses.id DESC").
|
||||||
Preload("Product").Preload("Warehouse").
|
Preload("Product").Preload("Warehouse").
|
||||||
Find(&productWarehouses).Error
|
Find(&productWarehouses).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user