mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 21:41:55 +00:00
344 lines
10 KiB
Go
344 lines
10 KiB
Go
package controller
|
|
|
|
import (
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
|
|
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/modules/repports/dto"
|
|
service "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/services"
|
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/validations"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/response"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
// === Marketing Report Response ===
|
|
|
|
type MarketingReportResponse struct {
|
|
Code int `json:"code"`
|
|
Status string `json:"status"`
|
|
Message string `json:"message"`
|
|
Meta response.Meta `json:"meta"`
|
|
Data []dto.RepportMarketingItemDTO `json:"data"`
|
|
Total *dto.Summary `json:"total,omitempty"`
|
|
}
|
|
|
|
type RepportController struct {
|
|
RepportService service.RepportService
|
|
}
|
|
|
|
func NewRepportController(repportService service.RepportService) *RepportController {
|
|
return &RepportController{
|
|
RepportService: repportService,
|
|
}
|
|
}
|
|
|
|
func (c *RepportController) GetExpense(ctx *fiber.Ctx) error {
|
|
query := &validation.ExpenseQuery{
|
|
Page: ctx.QueryInt("page", 1),
|
|
Limit: ctx.QueryInt("limit", 10),
|
|
Search: ctx.Query("search", ""),
|
|
Category: ctx.Query("category", ""),
|
|
SupplierId: int64(ctx.QueryInt("supplier_id", 0)),
|
|
KandangId: int64(ctx.QueryInt("kandang_id", 0)),
|
|
ProjectFlockKandangId: int64(ctx.QueryInt("project_flock_kandang_id", 0)),
|
|
NonstockId: int64(ctx.QueryInt("nonstock_id", 0)),
|
|
AreaId: int64(ctx.QueryInt("area_id", 0)),
|
|
LocationId: int64(ctx.QueryInt("location_id", 0)),
|
|
RealizationDate: ctx.Query("realization_date", ""),
|
|
}
|
|
|
|
locationScope, err := m.ResolveLocationScope(ctx, c.RepportService.DB())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
areaScope, err := m.ResolveAreaScope(ctx, c.RepportService.DB())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if locationScope.Restrict {
|
|
query.AllowedLocationIDs = toInt64Slice(locationScope.IDs)
|
|
}
|
|
if areaScope.Restrict {
|
|
query.AllowedAreaIDs = toInt64Slice(areaScope.IDs)
|
|
}
|
|
|
|
if query.Page < 1 || query.Limit < 1 {
|
|
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
|
}
|
|
|
|
result, totalResults, err := c.RepportService.GetExpense(ctx, query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusOK).
|
|
JSON(response.SuccessWithPaginate[dto.RepportExpenseListDTO]{
|
|
Code: fiber.StatusOK,
|
|
Status: "success",
|
|
Message: "Get expense report successfully",
|
|
Meta: response.Meta{
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
|
|
TotalResults: totalResults,
|
|
},
|
|
Data: result,
|
|
})
|
|
}
|
|
|
|
func (c *RepportController) GetMarketing(ctx *fiber.Ctx) error {
|
|
query := &validation.MarketingQuery{
|
|
Page: ctx.QueryInt("page", 1),
|
|
Limit: ctx.QueryInt("limit", 10),
|
|
Search: ctx.Query("search", ""),
|
|
CustomerId: int64(ctx.QueryInt("customer_id", 0)),
|
|
ProductId: int64(ctx.QueryInt("product_id", 0)),
|
|
WarehouseId: int64(ctx.QueryInt("warehouse_id", 0)),
|
|
SalesPersonId: int64(ctx.QueryInt("sales_person_id", 0)),
|
|
MarketingType: ctx.Query("marketing_type", ""),
|
|
FilterBy: ctx.Query("filter_by", ""),
|
|
StartDate: ctx.Query("start_date", ""),
|
|
EndDate: ctx.Query("end_date", ""),
|
|
SortBy: ctx.Query("sort_by", ""),
|
|
SortOrder: ctx.Query("sort_order", ""),
|
|
}
|
|
|
|
if query.Page < 1 || query.Limit < 1 {
|
|
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
|
}
|
|
|
|
result, totalResults, err := c.RepportService.GetMarketing(ctx, query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
total := dto.ToSummaryFromDTOItems(result)
|
|
|
|
return ctx.Status(fiber.StatusOK).
|
|
JSON(MarketingReportResponse{
|
|
Code: fiber.StatusOK,
|
|
Status: "success",
|
|
Message: "Get marketing report successfully",
|
|
Meta: response.Meta{
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
|
|
TotalResults: totalResults,
|
|
},
|
|
Data: result,
|
|
Total: total,
|
|
})
|
|
}
|
|
|
|
func (c *RepportController) GetPurchaseSupplier(ctx *fiber.Ctx) error {
|
|
query := &validation.PurchaseSupplierQuery{
|
|
Page: ctx.QueryInt("page", 1),
|
|
Limit: ctx.QueryInt("limit", 10),
|
|
AreaId: int64(ctx.QueryInt("area_id", 0)),
|
|
SupplierId: int64(ctx.QueryInt("supplier_id", 0)),
|
|
ProductId: int64(ctx.QueryInt("product_id", 0)),
|
|
ProductCategoryId: int64(ctx.QueryInt("product_category_id", 0)),
|
|
StartDate: ctx.Query("start_date", ""),
|
|
EndDate: ctx.Query("end_date", ""),
|
|
SortBy: ctx.Query("sort_by", ""),
|
|
FilterBy: ctx.Query("filter_by", ""),
|
|
}
|
|
|
|
areaScope, err := m.ResolveAreaScope(ctx, c.RepportService.DB())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if areaScope.Restrict {
|
|
query.AllowedAreaIDs = toInt64Slice(areaScope.IDs)
|
|
}
|
|
|
|
if query.Page < 1 || query.Limit < 1 {
|
|
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
|
}
|
|
|
|
result, totalResults, err := c.RepportService.GetPurchaseSupplier(ctx, query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
filters := map[string]interface{}{
|
|
"area_id": query.AreaId,
|
|
"supplier_id": query.SupplierId,
|
|
"product_id": query.ProductId,
|
|
"product_category_id": query.ProductCategoryId,
|
|
"start_date": query.StartDate,
|
|
"end_date": query.EndDate,
|
|
"sort_by": query.SortBy,
|
|
"filter_by": query.FilterBy,
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusOK).
|
|
JSON(response.SuccessWithPaginate[dto.PurchaseSupplierDTO]{
|
|
Code: fiber.StatusOK,
|
|
Status: "success",
|
|
Message: "Get supplier purchase recap successfully",
|
|
Meta: response.Meta{
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
|
|
TotalResults: totalResults,
|
|
Filters: filters,
|
|
},
|
|
Data: result,
|
|
})
|
|
}
|
|
|
|
func (c *RepportController) GetDebtSupplier(ctx *fiber.Ctx) error {
|
|
supplierIDs, err := parseCommaSeparatedInt64s(ctx.Query("supplier_ids", ""))
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
}
|
|
|
|
query := &validation.DebtSupplierQuery{
|
|
Page: ctx.QueryInt("page", 1),
|
|
Limit: ctx.QueryInt("limit", 10),
|
|
SupplierIDs: supplierIDs,
|
|
StartDate: ctx.Query("start_date", ""),
|
|
EndDate: ctx.Query("end_date", ""),
|
|
FilterBy: ctx.Query("filter_by", ""),
|
|
SortOrder: ctx.Query("sort_order", ""),
|
|
}
|
|
|
|
if query.Page < 1 || query.Limit < 1 {
|
|
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
|
}
|
|
|
|
result, totalResults, err := c.RepportService.GetDebtSupplier(ctx, query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
supplierIDs = query.SupplierIDs
|
|
if supplierIDs == nil {
|
|
supplierIDs = []int64{}
|
|
}
|
|
|
|
filters := map[string]interface{}{
|
|
"start_date": query.StartDate,
|
|
"end_date": query.EndDate,
|
|
"supplier_ids": supplierIDs,
|
|
"filter_by": query.FilterBy,
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusOK).
|
|
JSON(response.SuccessWithPaginate[dto.DebtSupplierDTO]{
|
|
Code: fiber.StatusOK,
|
|
Status: "success",
|
|
Message: "Get supplier debt recap successfully",
|
|
Meta: response.Meta{
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
|
|
TotalResults: totalResults,
|
|
Filters: filters,
|
|
},
|
|
Data: result,
|
|
})
|
|
}
|
|
|
|
func (c *RepportController) GetHppPerKandang(ctx *fiber.Ctx) error {
|
|
data, meta, err := c.RepportService.GetHppPerKandang(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
resp := struct {
|
|
Code int `json:"code"`
|
|
Status string `json:"status"`
|
|
Message string `json:"message"`
|
|
Meta dto.HppPerKandangMetaDTO `json:"meta"`
|
|
Data dto.HppPerKandangResponseData `json:"data"`
|
|
}{
|
|
Code: fiber.StatusOK,
|
|
Status: "success",
|
|
Message: "Get HPP harian kandang layer successfully",
|
|
Meta: *meta,
|
|
Data: *data,
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusOK).JSON(resp)
|
|
}
|
|
|
|
func (c *RepportController) GetProductionResult(ctx *fiber.Ctx) error {
|
|
idParam := ctx.Params("idProjectFlockKandang")
|
|
if idParam == "" {
|
|
return fiber.NewError(fiber.StatusBadRequest, "idProjectFlockKandang is required")
|
|
}
|
|
|
|
projectFlockKandangID, err := strconv.ParseUint(idParam, 10, 64)
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusBadRequest, "invalid idProjectFlockKandang")
|
|
}
|
|
|
|
query := &validation.ProductionResultQuery{
|
|
Page: ctx.QueryInt("page", 1),
|
|
Limit: ctx.QueryInt("limit", 10),
|
|
ProjectFlockKandangID: uint(projectFlockKandangID),
|
|
}
|
|
|
|
if query.Page < 1 || query.Limit < 1 {
|
|
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
|
}
|
|
|
|
data, totalResults, err := c.RepportService.GetProductionResult(ctx, query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusOK).
|
|
JSON(response.SuccessWithPaginate[dto.ProductionResultDTO]{
|
|
Code: fiber.StatusOK,
|
|
Status: "success",
|
|
Message: "Get Laporan Hasil Produksi successfully",
|
|
Meta: response.Meta{
|
|
Page: query.Page,
|
|
Limit: query.Limit,
|
|
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
|
|
TotalResults: totalResults,
|
|
},
|
|
Data: data,
|
|
})
|
|
}
|
|
|
|
func parseCommaSeparatedInt64s(raw string) ([]int64, error) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return []int64{}, nil
|
|
}
|
|
|
|
parts := strings.Split(raw, ",")
|
|
result := make([]int64, 0, len(parts))
|
|
for _, part := range parts {
|
|
part = strings.TrimSpace(part)
|
|
if part == "" {
|
|
continue
|
|
}
|
|
|
|
id, err := strconv.ParseInt(part, 10, 64)
|
|
if err != nil {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest, "supplier_ids must be comma separated integers")
|
|
}
|
|
result = append(result, id)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func toInt64Slice(ids []uint) []int64 {
|
|
if len(ids) == 0 {
|
|
return nil
|
|
}
|
|
out := make([]int64, 0, len(ids))
|
|
for _, id := range ids {
|
|
out = append(out, int64(id))
|
|
}
|
|
return out
|
|
}
|