mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Merge branch 'feat/BE/US-334-Report-closing-hpp-expedisi' into 'feat/BE/Sprint-7'
[FEAT/BE][US#334] report closing hpp expedisi See merge request mbugroup/lti-api!100
This commit is contained in:
@@ -246,6 +246,68 @@ func (u *ClosingController) GetSapronakByKandang(c *fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ClosingController) GetExpeditionHPP(c *fiber.Ctx) error {
|
||||||
|
param := c.Params("project_flock_id")
|
||||||
|
|
||||||
|
projectFlockID, err := strconv.Atoi(param)
|
||||||
|
if err != nil || projectFlockID <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectFlockKandangID *uint
|
||||||
|
if raw := c.Query("project_flock_kandang_id"); raw != "" {
|
||||||
|
idInt, convErr := strconv.Atoi(raw)
|
||||||
|
if convErr != nil || idInt <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_kandang_id")
|
||||||
|
}
|
||||||
|
idUint := uint(idInt)
|
||||||
|
projectFlockKandangID = &idUint
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := u.ClosingService.GetExpeditionHPP(c, uint(projectFlockID), projectFlockKandangID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).
|
||||||
|
JSON(response.Success{
|
||||||
|
Code: fiber.StatusOK,
|
||||||
|
Status: "success",
|
||||||
|
Message: "Get expedition HPP successfully",
|
||||||
|
Data: result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ClosingController) GetExpeditionHPPByKandang(c *fiber.Ctx) error {
|
||||||
|
projectParam := c.Params("project_flock_id")
|
||||||
|
kandangParam := c.Params("project_flock_kandang_id")
|
||||||
|
|
||||||
|
projectFlockID, err := strconv.Atoi(projectParam)
|
||||||
|
if err != nil || projectFlockID <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
pfkID, err := strconv.Atoi(kandangParam)
|
||||||
|
if err != nil || pfkID <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_kandang_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
kandangID := uint(pfkID)
|
||||||
|
|
||||||
|
result, err := u.ClosingService.GetExpeditionHPP(c, uint(projectFlockID), &kandangID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).
|
||||||
|
JSON(response.Success{
|
||||||
|
Code: fiber.StatusOK,
|
||||||
|
Status: "success",
|
||||||
|
Message: "Get expedition HPP successfully",
|
||||||
|
Data: result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ClosingController) GetClosingDataProduksi(c *fiber.Ctx) error {
|
func (u *ClosingController) GetClosingDataProduksi(c *fiber.Ctx) error {
|
||||||
param := c.Params("projectFlockId")
|
param := c.Params("projectFlockId")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
// ExpeditionCostItemDTO merepresentasikan biaya ekspedisi per vendor.
|
||||||
|
type ExpeditionCostItemDTO struct {
|
||||||
|
Id uint64 `json:"id"`
|
||||||
|
ExpeditionVendorName string `json:"expedition_vendor_name"`
|
||||||
|
HPPAmount float64 `json:"hpp_amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpeditionHPPDTO adalah struktur response utama untuk HPP Ekspedisi.
|
||||||
|
type ExpeditionHPPDTO struct {
|
||||||
|
ExpeditionCosts []ExpeditionCostItemDTO `json:"expedition_costs"`
|
||||||
|
TotalHPPAmount float64 `json:"total_hpp_amount"`
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ type ClosingRepository interface {
|
|||||||
SumMarketingWeightAndQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, float64, float64, error)
|
SumMarketingWeightAndQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, float64, float64, error)
|
||||||
SumRecordingEggQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, error)
|
SumRecordingEggQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, error)
|
||||||
GetFcrStandardsByFcrID(ctx context.Context, fcrID uint) ([]entity.FcrStandard, error)
|
GetFcrStandardsByFcrID(ctx context.Context, fcrID uint) ([]entity.FcrStandard, error)
|
||||||
|
GetExpeditionHPP(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]ExpeditionHPPRow, error)
|
||||||
FetchSapronakIncoming(ctx context.Context, kandangID uint) ([]SapronakIncomingRow, error)
|
FetchSapronakIncoming(ctx context.Context, kandangID uint) ([]SapronakIncomingRow, error)
|
||||||
FetchSapronakIncomingDetails(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, error)
|
FetchSapronakIncomingDetails(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, error)
|
||||||
FetchSapronakUsage(ctx context.Context, pfkID uint) ([]SapronakUsageRow, error)
|
FetchSapronakUsage(ctx context.Context, pfkID uint) ([]SapronakUsageRow, error)
|
||||||
@@ -59,6 +60,11 @@ type SapronakRow struct {
|
|||||||
Notes string `gorm:"column:notes"`
|
Notes string `gorm:"column:notes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExpeditionHPPRow struct {
|
||||||
|
SupplierName string `gorm:"column:supplier_name"`
|
||||||
|
TotalAmount float64 `gorm:"column:total_amount"`
|
||||||
|
}
|
||||||
|
|
||||||
type SapronakQueryParams struct {
|
type SapronakQueryParams struct {
|
||||||
Type string
|
Type string
|
||||||
WarehouseIDs []uint
|
WarehouseIDs []uint
|
||||||
@@ -274,6 +280,45 @@ func (r *ClosingRepositoryImpl) GetFcrStandardsByFcrID(ctx context.Context, fcrI
|
|||||||
return standards, nil
|
return standards, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ClosingRepositoryImpl) GetExpeditionHPP(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]ExpeditionHPPRow, error) {
|
||||||
|
db := r.DB().WithContext(ctx)
|
||||||
|
|
||||||
|
if projectFlockID == 0 {
|
||||||
|
return nil, fmt.Errorf("invalid project flock id")
|
||||||
|
}
|
||||||
|
|
||||||
|
query := db.
|
||||||
|
Table("expense_realizations AS er").
|
||||||
|
Joins("JOIN expense_nonstocks ens ON ens.id = er.expense_nonstock_id").
|
||||||
|
Joins("JOIN expenses e ON e.id = ens.expense_id").
|
||||||
|
Joins("JOIN project_flock_kandangs pfk ON pfk.id = ens.project_flock_kandang_id").
|
||||||
|
Joins("JOIN nonstocks n ON n.id = ens.nonstock_id").
|
||||||
|
Joins("JOIN flags f ON f.flagable_id = n.id AND f.flagable_type = ?", entity.FlagableTypeNonstock).
|
||||||
|
Joins("JOIN suppliers s ON s.id = e.supplier_id").
|
||||||
|
Where("pfk.project_flock_id = ?", projectFlockID).
|
||||||
|
Where("e.category = ?", "BOP").
|
||||||
|
Where("UPPER(f.name) = ?", strings.ToUpper(string(utils.FlagEkspedisi)))
|
||||||
|
|
||||||
|
if projectFlockKandangID != nil && *projectFlockKandangID != 0 {
|
||||||
|
query = query.Where("pfk.id = ?", *projectFlockKandangID)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rows []ExpeditionHPPRow
|
||||||
|
err := query.
|
||||||
|
Select(
|
||||||
|
"e.supplier_id AS supplier_id, " +
|
||||||
|
"s.name AS supplier_name, " +
|
||||||
|
"SUM(er.qty * er.price) AS total_amount",
|
||||||
|
).
|
||||||
|
Group("e.supplier_id, s.name").
|
||||||
|
Scan(&rows).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows, nil
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
sapronakIncomingPurchasesSQL = `
|
sapronakIncomingPurchasesSQL = `
|
||||||
SELECT
|
SELECT
|
||||||
|
|||||||
@@ -27,5 +27,7 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService
|
|||||||
route.Get("/:project_flock_id/perhitungan_sapronak", ctrl.GetSapronakByProject)
|
route.Get("/:project_flock_id/perhitungan_sapronak", ctrl.GetSapronakByProject)
|
||||||
route.Get("/:projectFlockId", ctrl.GetClosingSummary)
|
route.Get("/:projectFlockId", ctrl.GetClosingSummary)
|
||||||
route.Get("/:projectFlockId/sapronak", ctrl.GetClosingSapronak)
|
route.Get("/:projectFlockId/sapronak", ctrl.GetClosingSapronak)
|
||||||
|
route.Get("/:project_flock_id/expedition-hpp", ctrl.GetExpeditionHPP)
|
||||||
|
route.Get("/:project_flock_id/:project_flock_kandang_id/expedition-hpp", ctrl.GetExpeditionHPPByKandang)
|
||||||
route.Get("/:projectFlockId/data-produksi", ctrl.GetClosingDataProduksi)
|
route.Get("/:projectFlockId/data-produksi", ctrl.GetClosingDataProduksi)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type ClosingService interface {
|
|||||||
GetOverhead(ctx *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error)
|
GetOverhead(ctx *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error)
|
||||||
GetClosingDataProduksi(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingProductionReportDTO, error)
|
GetClosingDataProduksi(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingProductionReportDTO, error)
|
||||||
GetClosingSapronak(ctx *fiber.Ctx, projectFlockID uint, params *validation.ClosingSapronakQuery) ([]dto.ClosingSapronakItemDTO, int64, error)
|
GetClosingSapronak(ctx *fiber.Ctx, projectFlockID uint, params *validation.ClosingSapronakQuery) ([]dto.ClosingSapronakItemDTO, int64, error)
|
||||||
|
GetExpeditionHPP(ctx *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) (*dto.ExpeditionHPPDTO, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type closingService struct {
|
type closingService struct {
|
||||||
@@ -383,6 +384,40 @@ func (s closingService) GetOverhead(c *fiber.Ctx, projectFlockID uint) (*dto.Ove
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetExpeditionHPP menghitung HPP ekspedisi per vendor untuk sebuah project flock.
|
||||||
|
// Jika projectFlockKandangID tidak nil, maka hanya data untuk kandang tersebut yang dihitung.
|
||||||
|
func (s closingService) GetExpeditionHPP(c *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) (*dto.ExpeditionHPPDTO, error) {
|
||||||
|
if projectFlockID == 0 {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id")
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := s.Repository.GetExpeditionHPP(c.Context(), projectFlockID, projectFlockKandangID)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Failed to get expedition HPP for project flock %d: %+v", projectFlockID, err)
|
||||||
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch expedition HPP")
|
||||||
|
}
|
||||||
|
|
||||||
|
expeditionCosts := make([]dto.ExpeditionCostItemDTO, 0, len(rows))
|
||||||
|
var totalHPP float64
|
||||||
|
|
||||||
|
for idx, row := range rows {
|
||||||
|
expeditionCosts = append(expeditionCosts, dto.ExpeditionCostItemDTO{
|
||||||
|
Id: uint64(idx + 1),
|
||||||
|
ExpeditionVendorName: row.SupplierName,
|
||||||
|
HPPAmount: row.TotalAmount,
|
||||||
|
})
|
||||||
|
|
||||||
|
totalHPP += row.TotalAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &dto.ExpeditionHPPDTO{
|
||||||
|
ExpeditionCosts: expeditionCosts,
|
||||||
|
TotalHPPAmount: totalHPP,
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint) (*dto.ClosingProductionReportDTO, error) {
|
func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint) (*dto.ClosingProductionReportDTO, error) {
|
||||||
if projectFlockID == 0 {
|
if projectFlockID == 0 {
|
||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id")
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id")
|
||||||
|
|||||||
Reference in New Issue
Block a user