mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat[BE]: create GetOverhead API, and fixing chickin use newest productwarehouse schema
This commit is contained in:
@@ -123,3 +123,25 @@ func (u *ClosingController) GetPenjualan(c *fiber.Ctx) error {
|
|||||||
Data: dto.ToPenjualanRealisasiResponseDTO(projectFlock.Category, uint(projectFlockID), result),
|
Data: dto.ToPenjualanRealisasiResponseDTO(projectFlock.Category, uint(projectFlockID), result),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ClosingController) GetOverhead(c *fiber.Ctx) error {
|
||||||
|
param := c.Params("project_flock_id")
|
||||||
|
|
||||||
|
projectFlockID, err := strconv.Atoi(param)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid Project Flock Id")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := u.ClosingService.GetOverhead(c, uint(projectFlockID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).
|
||||||
|
JSON(response.Success{
|
||||||
|
Code: fiber.StatusOK,
|
||||||
|
Status: "success",
|
||||||
|
Message: "Get overhead successfully",
|
||||||
|
Data: result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// === Response DTO ===
|
// === Response DTO ===
|
||||||
|
|
||||||
type SalesDTO struct {
|
type SalesDTO struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
RealizationDate time.Time `json:"realization_date"`
|
RealizationDate time.Time `json:"realization_date"`
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
import (
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
)
|
||||||
|
|
||||||
|
// === DTO Structs ===
|
||||||
|
|
||||||
|
type OverheadDTO struct {
|
||||||
|
ItemName string `json:"item_name"`
|
||||||
|
UOMName string `json:"uom_name"`
|
||||||
|
BudgetQuantity float64 `json:"budget_quantity"`
|
||||||
|
BudgetUnitPrice float64 `json:"budget_unit_price"`
|
||||||
|
BudgetTotalAmount float64 `json:"budget_total_amount"`
|
||||||
|
ActualDate string `json:"actual_date"`
|
||||||
|
ActualQuantity float64 `json:"actual_quantity"`
|
||||||
|
ActualUnitPrice float64 `json:"actual_unit_price"`
|
||||||
|
ActualTotalAmount float64 `json:"actual_total_amount"`
|
||||||
|
CostPerBird float64 `json:"cost_per_bird"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TotalDTO struct {
|
||||||
|
BudgetQuantity float64 `json:"budget_quantity"`
|
||||||
|
BudgetTotalAmount float64 `json:"budget_total_amount"`
|
||||||
|
ActualQuantity float64 `json:"actual_quantity"`
|
||||||
|
ActualTotalAmount float64 `json:"actual_total_amount"`
|
||||||
|
CostPerBird float64 `json:"cost_per_bird"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OverheadListDTO struct {
|
||||||
|
Total TotalDTO `json:"total"`
|
||||||
|
Overheads []OverheadDTO `json:"overheads"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Mapper Functions ===
|
||||||
|
|
||||||
|
func ToOverheadDTO(budget *entity.ProjectBudget, realization *entity.ExpenseRealization) OverheadDTO {
|
||||||
|
if budget == nil && realization == nil {
|
||||||
|
return OverheadDTO{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemName, itemUOM string
|
||||||
|
if budget != nil {
|
||||||
|
itemName, itemUOM = getItemInfo(budget.Nonstock)
|
||||||
|
}
|
||||||
|
|
||||||
|
if itemName == "" && realization != nil && realization.ExpenseNonstock != nil {
|
||||||
|
itemName, itemUOM = getItemInfo(realization.ExpenseNonstock.Nonstock)
|
||||||
|
}
|
||||||
|
|
||||||
|
dto := OverheadDTO{
|
||||||
|
ItemName: itemName,
|
||||||
|
UOMName: itemUOM,
|
||||||
|
}
|
||||||
|
|
||||||
|
if budget != nil {
|
||||||
|
dto.BudgetQuantity = budget.Qty
|
||||||
|
dto.BudgetUnitPrice = budget.Price
|
||||||
|
dto.BudgetTotalAmount = calculateTotal(budget.Qty, budget.Price)
|
||||||
|
}
|
||||||
|
|
||||||
|
if realization != nil {
|
||||||
|
dto.ActualQuantity = realization.Qty
|
||||||
|
dto.ActualUnitPrice = realization.Price
|
||||||
|
dto.ActualTotalAmount = calculateTotal(realization.Qty, realization.Price)
|
||||||
|
dto.ActualDate = formatRealizationDate(realization)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.ExpenseRealization, totalChickinQty float64) OverheadListDTO {
|
||||||
|
overheadsByNonstockID := make(map[uint]*OverheadDTO)
|
||||||
|
latestDateByNonstockID := make(map[uint]string)
|
||||||
|
|
||||||
|
for i := range budgets {
|
||||||
|
nonstockID := budgets[i].NonstockId
|
||||||
|
if overheadsByNonstockID[nonstockID] == nil {
|
||||||
|
overheadsByNonstockID[nonstockID] = &OverheadDTO{}
|
||||||
|
}
|
||||||
|
|
||||||
|
itemName, itemUOM := getItemInfo(budgets[i].Nonstock)
|
||||||
|
overheadsByNonstockID[nonstockID].ItemName = itemName
|
||||||
|
overheadsByNonstockID[nonstockID].UOMName = itemUOM
|
||||||
|
overheadsByNonstockID[nonstockID].BudgetQuantity = budgets[i].Qty
|
||||||
|
overheadsByNonstockID[nonstockID].BudgetUnitPrice = budgets[i].Price
|
||||||
|
overheadsByNonstockID[nonstockID].BudgetTotalAmount = calculateTotal(budgets[i].Qty, budgets[i].Price)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range realizations {
|
||||||
|
if realizations[i].ExpenseNonstock == nil || realizations[i].ExpenseNonstock.NonstockId == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
nonstockID := uint(*realizations[i].ExpenseNonstock.NonstockId)
|
||||||
|
if overheadsByNonstockID[nonstockID] == nil {
|
||||||
|
overheadsByNonstockID[nonstockID] = &OverheadDTO{}
|
||||||
|
}
|
||||||
|
|
||||||
|
overheadsByNonstockID[nonstockID].ActualQuantity += realizations[i].Qty
|
||||||
|
overheadsByNonstockID[nonstockID].ActualTotalAmount += calculateTotal(realizations[i].Qty, realizations[i].Price)
|
||||||
|
|
||||||
|
if overheadsByNonstockID[nonstockID].ItemName == "" {
|
||||||
|
itemName, itemUOM := getItemInfo(realizations[i].ExpenseNonstock.Nonstock)
|
||||||
|
overheadsByNonstockID[nonstockID].ItemName = itemName
|
||||||
|
overheadsByNonstockID[nonstockID].UOMName = itemUOM
|
||||||
|
}
|
||||||
|
|
||||||
|
realizationDateStr := formatRealizationDate(&realizations[i])
|
||||||
|
if realizationDateStr != "" {
|
||||||
|
if latestDateByNonstockID[nonstockID] == "" || realizationDateStr > latestDateByNonstockID[nonstockID] {
|
||||||
|
latestDateByNonstockID[nonstockID] = realizationDateStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalBudgetQuantity, totalBudgetAmount, totalActualQuantity, totalActualAmount float64
|
||||||
|
overheadItems := make([]OverheadDTO, 0, len(overheadsByNonstockID))
|
||||||
|
|
||||||
|
for nonstockID, overhead := range overheadsByNonstockID {
|
||||||
|
overhead.ActualDate = latestDateByNonstockID[nonstockID]
|
||||||
|
overhead.CostPerBird = calculateCostPerBird(overhead.ActualTotalAmount, totalChickinQty)
|
||||||
|
|
||||||
|
if overhead.ActualQuantity > 0 {
|
||||||
|
overhead.ActualUnitPrice = overhead.ActualTotalAmount / overhead.ActualQuantity
|
||||||
|
}
|
||||||
|
|
||||||
|
totalBudgetQuantity += overhead.BudgetQuantity
|
||||||
|
totalBudgetAmount += overhead.BudgetTotalAmount
|
||||||
|
totalActualQuantity += overhead.ActualQuantity
|
||||||
|
totalActualAmount += overhead.ActualTotalAmount
|
||||||
|
|
||||||
|
overheadItems = append(overheadItems, *overhead)
|
||||||
|
}
|
||||||
|
|
||||||
|
return OverheadListDTO{
|
||||||
|
Total: TotalDTO{
|
||||||
|
BudgetQuantity: totalBudgetQuantity,
|
||||||
|
BudgetTotalAmount: totalBudgetAmount,
|
||||||
|
ActualQuantity: totalActualQuantity,
|
||||||
|
ActualTotalAmount: totalActualAmount,
|
||||||
|
CostPerBird: calculateCostPerBird(totalActualAmount, totalChickinQty),
|
||||||
|
},
|
||||||
|
Overheads: overheadItems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Helper Functions ===
|
||||||
|
|
||||||
|
func getItemInfo(nonstock *entity.Nonstock) (string, string) {
|
||||||
|
if nonstock != nil && nonstock.Id != 0 {
|
||||||
|
return nonstock.Name, nonstock.Uom.Name
|
||||||
|
}
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateTotal(qty, price float64) float64 {
|
||||||
|
return qty * price
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateCostPerBird(totalPrice, totalChickinQty float64) float64 {
|
||||||
|
if totalChickinQty > 0 {
|
||||||
|
return totalPrice / totalChickinQty
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatRealizationDate(realization *entity.ExpenseRealization) string {
|
||||||
|
if realization != nil && realization.ExpenseNonstock != nil && realization.ExpenseNonstock.Expense != nil {
|
||||||
|
if !realization.ExpenseNonstock.Expense.RealizationDate.IsZero() {
|
||||||
|
return realization.ExpenseNonstock.Expense.RealizationDate.Format("2006-01-02T15:04:05Z07:00")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -9,7 +9,9 @@ import (
|
|||||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
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"
|
||||||
|
rExpenseRealization "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||||
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"
|
||||||
|
rChickin "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories"
|
||||||
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||||
|
|
||||||
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||||
@@ -22,12 +24,15 @@ func (ClosingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *
|
|||||||
closingRepo := rClosing.NewClosingRepository(db)
|
closingRepo := rClosing.NewClosingRepository(db)
|
||||||
userRepo := rUser.NewUserRepository(db)
|
userRepo := rUser.NewUserRepository(db)
|
||||||
projectFlockRepo := rProjectFlock.NewProjectflockRepository(db)
|
projectFlockRepo := rProjectFlock.NewProjectflockRepository(db)
|
||||||
|
projectBudgetRepo := rProjectFlock.NewProjectBudgetRepository(db)
|
||||||
marketingRepo := rMarketings.NewMarketingRepository(db)
|
marketingRepo := rMarketings.NewMarketingRepository(db)
|
||||||
marketingDeliveryProductRepo := rMarketings.NewMarketingDeliveryProductRepository(db)
|
marketingDeliveryProductRepo := rMarketings.NewMarketingDeliveryProductRepository(db)
|
||||||
|
expenseRealizationRepo := rExpenseRealization.NewExpenseRealizationRepository(db)
|
||||||
|
chickinRepo := rChickin.NewChickinRepository(db)
|
||||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||||
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
||||||
|
|
||||||
closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, validate)
|
closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, expenseRealizationRepo, projectBudgetRepo, chickinRepo, validate)
|
||||||
userService := sUser.NewUserService(userRepo, validate)
|
userService := sUser.NewUserService(userRepo, validate)
|
||||||
|
|
||||||
ClosingRoutes(router, userService, closingService)
|
ClosingRoutes(router, userService, closingService)
|
||||||
|
|||||||
@@ -22,5 +22,7 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService
|
|||||||
|
|
||||||
route.Get("/", ctrl.GetAll)
|
route.Get("/", ctrl.GetAll)
|
||||||
route.Get("/:project_flock_id/penjualan", ctrl.GetPenjualan)
|
route.Get("/:project_flock_id/penjualan", ctrl.GetPenjualan)
|
||||||
|
route.Get("/:project_flock_id/overhead", ctrl.GetOverhead)
|
||||||
route.Get("/:projectFlockId", ctrl.GetClosingSummary)
|
route.Get("/:projectFlockId", ctrl.GetClosingSummary)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import (
|
|||||||
"gitlab.com/mbugroup/lti-api.git/internal/modules/closings/dto"
|
"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"
|
||||||
|
expenseRealizationRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||||
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"
|
||||||
|
chickinRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories"
|
||||||
projectflockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
projectflockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/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"
|
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
||||||
@@ -26,6 +28,7 @@ type ClosingService interface {
|
|||||||
GetProjectFlockByID(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error)
|
GetProjectFlockByID(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)
|
GetClosingSummary(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error)
|
||||||
|
GetOverhead(ctx *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type closingService struct {
|
type closingService struct {
|
||||||
@@ -36,9 +39,12 @@ type closingService struct {
|
|||||||
MarketingRepo marketingRepository.MarketingRepository
|
MarketingRepo marketingRepository.MarketingRepository
|
||||||
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
||||||
ApprovalSvc commonSvc.ApprovalService
|
ApprovalSvc commonSvc.ApprovalService
|
||||||
|
ExpenseRealizationRepo expenseRealizationRepository.ExpenseRealizationRepository
|
||||||
|
ProjectBudgetRepo projectflockRepository.ProjectBudgetRepository
|
||||||
|
ChickinRepo chickinRepository.ProjectChickinRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClosingService(repo repository.ClosingRepository, projectFlockRepo projectflockRepository.ProjectflockRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, validate *validator.Validate) ClosingService {
|
func NewClosingService(repo repository.ClosingRepository, projectFlockRepo projectflockRepository.ProjectflockRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, expenseRealizationRepo expenseRealizationRepository.ExpenseRealizationRepository, projectBudgetRepo projectflockRepository.ProjectBudgetRepository, chickinRepo chickinRepository.ProjectChickinRepository, validate *validator.Validate) ClosingService {
|
||||||
return &closingService{
|
return &closingService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
Validate: validate,
|
Validate: validate,
|
||||||
@@ -47,6 +53,9 @@ func NewClosingService(repo repository.ClosingRepository, projectFlockRepo proje
|
|||||||
MarketingRepo: marketingRepo,
|
MarketingRepo: marketingRepo,
|
||||||
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
||||||
ApprovalSvc: approvalSvc,
|
ApprovalSvc: approvalSvc,
|
||||||
|
ExpenseRealizationRepo: expenseRealizationRepo,
|
||||||
|
ProjectBudgetRepo: projectBudgetRepo,
|
||||||
|
ChickinRepo: chickinRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,3 +197,29 @@ func (s closingService) getApprovalStatuses(ctx context.Context, projectFlockID
|
|||||||
|
|
||||||
return statusProject, statusClosing, nil
|
return statusProject, statusClosing, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s closingService) GetOverhead(c *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error) {
|
||||||
|
budgets, err := s.ProjectBudgetRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
realizations, err := s.ExpenseRealizationRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
chickins, err := s.ChickinRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalChickinQty float64
|
||||||
|
for _, chickin := range chickins {
|
||||||
|
totalChickinQty += chickin.UsageQty
|
||||||
|
}
|
||||||
|
|
||||||
|
result := dto.ToOverheadListDTOs(budgets, realizations, totalChickinQty)
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ type ExpenseRealizationRepository interface {
|
|||||||
repository.BaseRepository[entity.ExpenseRealization]
|
repository.BaseRepository[entity.ExpenseRealization]
|
||||||
IdExists(ctx context.Context, id uint64) (bool, error)
|
IdExists(ctx context.Context, id uint64) (bool, error)
|
||||||
GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error)
|
GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error)
|
||||||
|
GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExpenseRealizationRepositoryImpl struct {
|
type ExpenseRealizationRepositoryImpl struct {
|
||||||
@@ -30,11 +31,22 @@ func (r *ExpenseRealizationRepositoryImpl) IdExists(ctx context.Context, id uint
|
|||||||
|
|
||||||
func (r *ExpenseRealizationRepositoryImpl) GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error) {
|
func (r *ExpenseRealizationRepositoryImpl) GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error) {
|
||||||
var realization entity.ExpenseRealization
|
var realization entity.ExpenseRealization
|
||||||
err := r.DB().WithContext(ctx).
|
err := r.DB().WithContext(ctx).Where("expense_nonstock_id = ?", expenseNonstockID).First(&realization).Error
|
||||||
Where("expense_nonstock_id = ?", expenseNonstockID).
|
return &realization, err
|
||||||
First(&realization).Error
|
}
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
func (r *ExpenseRealizationRepositoryImpl) GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error) {
|
||||||
}
|
var realizations []entity.ExpenseRealization
|
||||||
return &realization, nil
|
err := r.DB().WithContext(ctx).
|
||||||
|
Preload("ExpenseNonstock").
|
||||||
|
Preload("ExpenseNonstock.Nonstock").
|
||||||
|
Preload("ExpenseNonstock.Nonstock.Uom").
|
||||||
|
Preload("ExpenseNonstock.Expense").
|
||||||
|
Joins("JOIN expense_nonstocks ON expense_nonstocks.id = expense_realizations.expense_nonstock_id").
|
||||||
|
Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = expense_nonstocks.project_flock_kandang_id").
|
||||||
|
Joins("JOIN expenses ON expenses.id = expense_nonstocks.expense_id").
|
||||||
|
Where("project_flock_kandangs.project_flock_id = ?", projectFlockID).
|
||||||
|
Where("expenses.category = ?", "BOP").
|
||||||
|
Find(&realizations).Error
|
||||||
|
return realizations, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
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"
|
||||||
|
middleware "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||||
expenseDto "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/dto"
|
expenseDto "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/dto"
|
||||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/validations"
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/validations"
|
||||||
@@ -188,7 +189,11 @@ func (s *expenseService) CreateOne(c *fiber.Ctx, req *validation.Create) (*expen
|
|||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate reference number")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate reference number")
|
||||||
}
|
}
|
||||||
|
|
||||||
createdBy := uint64(1) //todo get from auth
|
actorID, err := middleware.ActorIDFromContext(c)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context")
|
||||||
|
}
|
||||||
|
createdBy := uint64(actorID)
|
||||||
expense = &entity.Expense{
|
expense = &entity.Expense{
|
||||||
ReferenceNumber: referenceNumber,
|
ReferenceNumber: referenceNumber,
|
||||||
PoNumber: req.PoNumber,
|
PoNumber: req.PoNumber,
|
||||||
@@ -496,7 +501,10 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actorID := uint(1) // TODO: replace with authenticated user id
|
actorID, err := middleware.ActorIDFromContext(c)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context")
|
||||||
|
}
|
||||||
if *latestApproval.Action != entity.ApprovalActionUpdated {
|
if *latestApproval.Action != entity.ApprovalActionUpdated {
|
||||||
|
|
||||||
approvalAction := entity.ApprovalActionUpdated
|
approvalAction := entity.ApprovalActionUpdated
|
||||||
@@ -655,7 +663,10 @@ func (s *expenseService) CompleteExpense(c *fiber.Ctx, id uint, notes *string) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
actorID := uint(1) // TODO: replace with authenticated user id
|
actorID, err := middleware.ActorIDFromContext(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context")
|
||||||
|
}
|
||||||
|
|
||||||
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowExpense, id, nil)
|
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowExpense, id, nil)
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -960,11 +971,14 @@ func (s *expenseService) Approval(c *fiber.Ctx, req *validation.ApprovalRequest,
|
|||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "No expense IDs provided")
|
return nil, fiber.NewError(fiber.StatusBadRequest, "No expense IDs provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
actorID := uint(1) // TODO: replace with authenticated user id
|
actorID, err := middleware.ActorIDFromContext(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context")
|
||||||
|
}
|
||||||
|
|
||||||
var results []expenseDto.ExpenseDetailDTO
|
var results []expenseDto.ExpenseDetailDTO
|
||||||
|
|
||||||
err := s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
||||||
|
|
||||||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(tx))
|
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(tx))
|
||||||
expenseRepoTx := repository.NewExpenseRepository(tx)
|
expenseRepoTx := repository.NewExpenseRepository(tx)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package adjustments
|
package adjustments
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||||
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/controllers"
|
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/controllers"
|
||||||
adjustment "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/services"
|
adjustment "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/services"
|
||||||
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||||
@@ -13,7 +13,7 @@ func AdjustmentRoutes(v1 fiber.Router, u user.UserService, s adjustment.Adjustme
|
|||||||
ctrl := controller.NewAdjustmentController(s)
|
ctrl := controller.NewAdjustmentController(s)
|
||||||
|
|
||||||
route := v1.Group("/adjustments")
|
route := v1.Group("/adjustments")
|
||||||
|
route.Use(m.Auth(u))
|
||||||
// Standard CRUD routes following master data pattern
|
// Standard CRUD routes following master data pattern
|
||||||
route.Get("/", ctrl.AdjustmentHistory) // Get all with pagination and filters
|
route.Get("/", ctrl.AdjustmentHistory) // Get all with pagination and filters
|
||||||
route.Post("/", ctrl.Adjustment) // Create adjustment
|
route.Post("/", ctrl.Adjustment) // Create adjustment
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
type ProjectChickinRepository interface {
|
type ProjectChickinRepository interface {
|
||||||
repository.BaseRepository[entity.ProjectChickin]
|
repository.BaseRepository[entity.ProjectChickin]
|
||||||
GetFirstByProjectFlockID(ctx context.Context, projectFlockID uint) (*entity.ProjectChickin, error)
|
GetFirstByProjectFlockID(ctx context.Context, projectFlockID uint) (*entity.ProjectChickin, error)
|
||||||
|
GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectChickin, error)
|
||||||
GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error)
|
GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error)
|
||||||
GetPendingByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error)
|
GetPendingByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error)
|
||||||
GetTotalPendingUsageQtyByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (float64, error)
|
GetTotalPendingUsageQtyByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (float64, error)
|
||||||
@@ -40,6 +41,16 @@ func (r *ChickinRepositoryImpl) GetFirstByProjectFlockID(ctx context.Context, pr
|
|||||||
return &chickin, nil
|
return &chickin, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ChickinRepositoryImpl) GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectChickin, error) {
|
||||||
|
var chickins []entity.ProjectChickin
|
||||||
|
err := r.db.WithContext(ctx).
|
||||||
|
Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = project_chickins.project_flock_kandang_id").
|
||||||
|
Where("project_flock_kandangs.project_flock_id = ?", projectFlockID).
|
||||||
|
Order("project_chickins.created_at DESC").
|
||||||
|
Find(&chickins).Error
|
||||||
|
return chickins, err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ChickinRepositoryImpl) GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) {
|
func (r *ChickinRepositoryImpl) GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) {
|
||||||
var chickins []entity.ProjectChickin
|
var chickins []entity.ProjectChickin
|
||||||
err := r.db.WithContext(ctx).
|
err := r.db.WithContext(ctx).
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
|
|||||||
|
|
||||||
if category == string(utils.ProjectFlockCategoryLaying) {
|
if category == string(utils.ProjectFlockCategoryLaying) {
|
||||||
for _, chickin := range newChikins {
|
for _, chickin := range newChikins {
|
||||||
updates := map[string]any{"quantity": gorm.Expr("quantity - ?", chickin.PendingUsageQty)}
|
updates := map[string]any{"qty": gorm.Expr("qty - ?", chickin.PendingUsageQty)}
|
||||||
|
|
||||||
if err := productWarehouseTx.PatchOne(c.Context(), chickin.ProductWarehouseId, updates, nil); err != nil {
|
if err := productWarehouseTx.PatchOne(c.Context(), chickin.ProductWarehouseId, updates, nil); err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -498,7 +498,7 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
|
|||||||
for _, chickin := range chickins {
|
for _, chickin := range chickins {
|
||||||
|
|
||||||
if categoryForRejection == string(utils.ProjectFlockCategoryGrowing) {
|
if categoryForRejection == string(utils.ProjectFlockCategoryGrowing) {
|
||||||
updates := map[string]any{"quantity": gorm.Expr("quantity + ?", chickin.PendingUsageQty)}
|
updates := map[string]any{"qty": gorm.Expr("qty + ?", chickin.PendingUsageQty)}
|
||||||
|
|
||||||
if err := productWarehouseTx.PatchOne(c.Context(), chickin.ProductWarehouseId, updates, nil); err != nil {
|
if err := productWarehouseTx.PatchOne(c.Context(), chickin.ProductWarehouseId, updates, nil); err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -600,7 +600,7 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti
|
|||||||
|
|
||||||
if chickin.ProductWarehouseId != targetPW.Id {
|
if chickin.ProductWarehouseId != targetPW.Id {
|
||||||
if err := productWarehouseTx.PatchOne(ctx.Context(), chickin.ProductWarehouseId, map[string]any{
|
if err := productWarehouseTx.PatchOne(ctx.Context(), chickin.ProductWarehouseId, map[string]any{
|
||||||
"quantity": gorm.Expr("quantity - ?", quantityToConvert),
|
"qty": gorm.Expr("qty - ?", quantityToConvert),
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Source product warehouse %d not found", chickin.ProductWarehouseId))
|
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Source product warehouse %d not found", chickin.ProductWarehouseId))
|
||||||
@@ -610,7 +610,7 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := productWarehouseTx.PatchOne(ctx.Context(), targetPW.Id, map[string]any{
|
if err := productWarehouseTx.PatchOne(ctx.Context(), targetPW.Id, map[string]any{
|
||||||
"quantity": gorm.Expr("quantity + ?", quantityToConvert),
|
"qty": gorm.Expr("qty + ?", quantityToConvert),
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Target product warehouse %d not found", targetPW.Id))
|
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Target product warehouse %d not found", targetPW.Id))
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -8,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type ProjectBudgetRepository interface {
|
type ProjectBudgetRepository interface {
|
||||||
repository.BaseRepository[entity.ProjectBudget]
|
repository.BaseRepository[entity.ProjectBudget]
|
||||||
|
GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectBudget, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectBudgetRepositoryImpl struct {
|
type ProjectBudgetRepositoryImpl struct {
|
||||||
@@ -21,3 +24,13 @@ func NewProjectBudgetRepository(db *gorm.DB) ProjectBudgetRepository {
|
|||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ProjectBudgetRepositoryImpl) GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectBudget, error) {
|
||||||
|
var budgets []entity.ProjectBudget
|
||||||
|
err := r.db.WithContext(ctx).
|
||||||
|
Where("project_flock_id = ?", projectFlockID).
|
||||||
|
Preload("Nonstock").
|
||||||
|
Preload("Nonstock.Uom").
|
||||||
|
Find(&budgets).Error
|
||||||
|
return budgets, err
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user