adjust response api get all closing, response api get closing tab sapronak

This commit is contained in:
giovanni-ce
2025-12-09 16:23:05 +07:00
parent 536e76d481
commit 4a2a80916f
6 changed files with 98 additions and 66 deletions
@@ -40,7 +40,7 @@ func (u *ClosingController) GetAll(c *fiber.Ctx) error {
} }
return c.Status(fiber.StatusOK). return c.Status(fiber.StatusOK).
JSON(response.SuccessWithPaginate[dto.ClosingSummaryDTO]{ JSON(response.SuccessWithPaginate[dto.ClosingListItemDTO]{
Code: fiber.StatusOK, Code: fiber.StatusOK,
Status: "success", Status: "success",
Message: "Retrieved closing projects list successfully", Message: "Retrieved closing projects list successfully",
@@ -152,13 +152,8 @@ func (u *ClosingController) GetClosingSapronak(c *fiber.Ctx) error {
return err return err
} }
resp := struct { return c.Status(fiber.StatusOK).
Code int `json:"code"` JSON(response.SuccessWithPaginate[dto.ClosingSapronakItemDTO]{
Status string `json:"status"`
Message string `json:"message"`
Meta response.Meta `json:"meta"`
Data interface{} `json:"data"`
}{
Code: fiber.StatusOK, Code: fiber.StatusOK,
Status: "success", Status: "success",
Message: "Retrieved closing report (sapronak) successfully", Message: "Retrieved closing report (sapronak) successfully",
@@ -169,8 +164,5 @@ func (u *ClosingController) GetClosingSapronak(c *fiber.Ctx) error {
TotalResults: totalResults, TotalResults: totalResults,
}, },
Data: result, Data: result,
} })
return c.Status(fiber.StatusOK).
JSON(resp)
} }
@@ -27,6 +27,21 @@ type ClosingDetailDTO struct {
ClosingListDTO ClosingListDTO
} }
type ClosingListItemDTO struct {
Id uint `json:"id"`
LocationID uint `json:"location_id"`
LocationName string `json:"location_name"`
ProjectCategory string `json:"project_category"`
Period int `json:"period"`
ClosingDate string `json:"closing_date"`
ShedLabel string `json:"shed_label"`
ShedCount int `json:"shed_count"`
SalesPaidAmount int64 `json:"sales_paid_amount"`
SalesRemainingAmount int64 `json:"sales_remaining_amount"`
SalesPaymentStatus string `json:"sales_payment_status"`
ProjectStatus string `json:"project_status"`
}
type ClosingSummaryDTO struct { type ClosingSummaryDTO struct {
FlockID uint `json:"flock_id"` FlockID uint `json:"flock_id"`
Period int `json:"period"` Period int `json:"period"`
@@ -68,6 +83,25 @@ func ToClosingSummaryDTO(project entity.ProjectFlock, statusProject, statusClosi
} }
} }
func ToClosingListItemDTO(project entity.ProjectFlock, projectStatus string) ClosingListItemDTO {
shedCount := len(project.KandangHistory)
return ClosingListItemDTO{
Id: project.Id,
LocationID: project.LocationId,
LocationName: project.Location.Name,
ProjectCategory: project.Category,
Period: maxPeriod(project.KandangHistory),
ClosingDate: "17-Nov-2025",
ShedLabel: fmt.Sprintf("%d Kandang", shedCount),
ShedCount: shedCount,
SalesPaidAmount: 21993726,
SalesRemainingAmount: 11075919,
SalesPaymentStatus: "Lunas",
ProjectStatus: projectStatus,
}
}
func maxPeriod(history []entity.ProjectFlockKandang) int { func maxPeriod(history []entity.ProjectFlockKandang) int {
max := 0 max := 0
for _, h := range history { for _, h := range history {
@@ -12,7 +12,7 @@ type ClosingSapronakItemDTO struct {
ProductSubCategory string `json:"product_sub_category"` ProductSubCategory string `json:"product_sub_category"`
SourceWarehouse string `json:"source_warehouse"` SourceWarehouse string `json:"source_warehouse"`
DestinationWarehouse string `json:"destination_warehouse,omitempty"` DestinationWarehouse string `json:"destination_warehouse,omitempty"`
Destination string `json:"destination,omitempty"` // Destination string `json:"destination,omitempty"`
Quantity float64 `json:"quantity"` Quantity float64 `json:"quantity"`
Unit string `json:"unit"` Unit string `json:"unit"`
FormattedQuantity string `json:"formatted_quantity"` FormattedQuantity string `json:"formatted_quantity"`
@@ -112,7 +112,11 @@ SELECT
'Purchase' AS transaction_type, 'Purchase' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category, pc.name AS product_category,
pc.name AS product_sub_category, COALESCE((
SELECT string_agg(f.name, ' ')
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category,
'External Supplier' AS source_warehouse, 'External Supplier' AS source_warehouse,
w.name AS destination_warehouse, w.name AS destination_warehouse,
'' AS destination, '' AS destination,
@@ -137,7 +141,11 @@ SELECT
'Internal Transfer In' AS transaction_type, 'Internal Transfer In' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category, pc.name AS product_category,
pc.name AS product_sub_category, COALESCE((
SELECT string_agg(f.name, ' ')
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category,
COALESCE(fw.name, '') AS source_warehouse, COALESCE(fw.name, '') AS source_warehouse,
COALESCE(tw.name, '') AS destination_warehouse, COALESCE(tw.name, '') AS destination_warehouse,
'' AS destination, '' AS destination,
@@ -163,7 +171,11 @@ SELECT
'Internal Transfer Out' AS transaction_type, 'Internal Transfer Out' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category, pc.name AS product_category,
pc.name AS product_sub_category, COALESCE((
SELECT string_agg(f.name, ' ')
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category,
COALESCE(fw.name, '') AS source_warehouse, COALESCE(fw.name, '') AS source_warehouse,
'' AS destination_warehouse, '' AS destination_warehouse,
COALESCE(tw.name, '') AS destination, COALESCE(tw.name, '') AS destination,
@@ -189,7 +201,11 @@ SELECT
'Trading Sales' AS transaction_type, 'Trading Sales' AS transaction_type,
prod.name AS product_name, prod.name AS product_name,
pc.name AS product_category, pc.name AS product_category,
pc.name AS product_sub_category, COALESCE((
SELECT string_agg(f.name, ' ')
FROM flags f
WHERE f.flagable_type = 'products' AND f.flagable_id = prod.id
), '') AS product_sub_category,
w.name AS source_warehouse, w.name AS source_warehouse,
'' AS destination_warehouse, '' AS destination_warehouse,
'RETAIL CUSTOMER' AS destination, 'RETAIL CUSTOMER' AS destination,
+1 -1
View File
@@ -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("/closing") route := v1.Group("/closings")
// 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)
@@ -23,11 +23,11 @@ import (
) )
type ClosingService interface { type ClosingService interface {
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]dto.ClosingSummaryDTO, int64, error) GetAll(ctx *fiber.Ctx, params *validation.Query) ([]dto.ClosingListItemDTO, int64, error)
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)
GetClosingSapronak(ctx *fiber.Ctx, projectFlockID uint, params *validation.SapronakQuery) (*dto.ClosingSapronakDTO, int64, error) GetClosingSapronak(ctx *fiber.Ctx, projectFlockID uint, params *validation.SapronakQuery) ([]dto.ClosingSapronakItemDTO, int64, error)
} }
type closingService struct { type closingService struct {
@@ -58,11 +58,12 @@ func (s closingService) withRelations(db *gorm.DB) *gorm.DB {
func (s closingService) withClosingRelations(db *gorm.DB) *gorm.DB { func (s closingService) withClosingRelations(db *gorm.DB) *gorm.DB {
return s.withRelations(db). return s.withRelations(db).
Preload("Location").
Preload("KandangHistory"). Preload("KandangHistory").
Preload("KandangHistory.Chickins") Preload("KandangHistory.Chickins")
} }
func (s closingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]dto.ClosingSummaryDTO, int64, error) { func (s closingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]dto.ClosingListItemDTO, 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
} }
@@ -82,15 +83,15 @@ func (s closingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]dto.Cl
return nil, 0, err return nil, 0, err
} }
result := make([]dto.ClosingSummaryDTO, 0, len(closings)) result := make([]dto.ClosingListItemDTO, 0, len(closings))
for _, closing := range closings { for _, closing := range closings {
statusProject, statusClosing, err := s.getApprovalStatuses(c.Context(), closing.Id) statusProject, _, err := s.getApprovalStatuses(c.Context(), closing.Id)
if err != nil { if err != nil {
s.Log.Errorf("Failed to retrieve approval statuses for project flock %d: %+v", closing.Id, err) s.Log.Errorf("Failed to retrieve approval statuses for project flock %d: %+v", closing.Id, err)
return nil, 0, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch approval status") return nil, 0, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch approval status")
} }
result = append(result, dto.ToClosingSummaryDTO(closing, statusProject, statusClosing)) result = append(result, dto.ToClosingListItemDTO(closing, statusProject))
} }
return result, total, nil return result, total, nil
@@ -158,7 +159,7 @@ func (s closingService) GetClosingSummary(c *fiber.Ctx, projectFlockID uint) (*d
return &summary, nil return &summary, nil
} }
func (s closingService) GetClosingSapronak(c *fiber.Ctx, projectFlockID uint, params *validation.SapronakQuery) (*dto.ClosingSapronakDTO, int64, error) { func (s closingService) GetClosingSapronak(c *fiber.Ctx, projectFlockID uint, params *validation.SapronakQuery) ([]dto.ClosingSapronakItemDTO, int64, error) {
if projectFlockID == 0 { if projectFlockID == 0 {
return nil, 0, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id") return nil, 0, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id")
} }
@@ -234,7 +235,7 @@ func (s closingService) GetClosingSapronak(c *fiber.Ctx, projectFlockID uint, pa
ProductSubCategory: row.ProductSubCategory, ProductSubCategory: row.ProductSubCategory,
SourceWarehouse: row.SourceWarehouse, SourceWarehouse: row.SourceWarehouse,
DestinationWarehouse: row.DestinationWarehouse, DestinationWarehouse: row.DestinationWarehouse,
Destination: row.Destination, // Destination: row.Destination,
Quantity: row.Quantity, Quantity: row.Quantity,
Unit: row.Unit, Unit: row.Unit,
FormattedQuantity: formatQuantity(row.Quantity, row.Unit), FormattedQuantity: formatQuantity(row.Quantity, row.Unit),
@@ -243,18 +244,7 @@ func (s closingService) GetClosingSapronak(c *fiber.Ctx, projectFlockID uint, pa
}) })
} }
result := dto.ClosingSapronakDTO{ return items, totalResults, nil
IncomingSapronak: []dto.ClosingSapronakItemDTO{},
OutgoingSapronak: []dto.ClosingSapronakItemDTO{},
}
if params.Type == validation.SapronakTypeIncoming {
result.IncomingSapronak = items
} else {
result.OutgoingSapronak = items
}
return &result, totalResults, nil
} }
func (s closingService) getWarehouseIDsByProjectFlock(ctx context.Context, projectFlockID uint) ([]uint, error) { func (s closingService) getWarehouseIDsByProjectFlock(ctx context.Context, projectFlockID uint) ([]uint, error) {