package dto import ( "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" marketingDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/dto" customerDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/dto" productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto" warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto" userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" "gitlab.com/mbugroup/lti-api.git/internal/utils" ) type RepportMarketingItemDTO struct { ID int `json:"id"` SoDate time.Time `json:"so_date"` RealizationDate time.Time `json:"realization_date"` AgingDays int `json:"aging_days"` Warehouse *warehouseDTO.WarehouseRelationDTO `json:"warehouse,omitempty"` Customer *customerDTO.CustomerRelationDTO `json:"customer,omitempty"` DoNumber string `json:"do_number"` Sales *userDTO.UserRelationDTO `json:"sales,omitempty"` VehicleNumber string `json:"vehicle_number"` Product *productDTO.ProductRelationDTO `json:"product,omitempty"` MarketingType string `json:"marketing_type"` Qty float64 `json:"qty"` AverageWeightKg float64 `json:"average_weight_kg"` TotalWeightKg float64 `json:"total_weight_kg"` SalesPricePerKg float64 `json:"sales_price_per_kg"` HppPricePerKg float64 `json:"hpp_price_per_kg"` SalesAmount float64 `json:"sales_amount"` HppAmount float64 `json:"hpp_amount"` } type Summary struct { TotalQty int `json:"total_qty"` TotalWeightKg float64 `json:"total_weight_kg"` TotalSalesAmount int64 `json:"total_sales_amount"` TotalHppAmount int64 `json:"total_hpp_amount"` TotalHppPricePerKg float64 `json:"total_hpp_price_per_kg"` } type RepportMarketingResponseDTO struct { Items []RepportMarketingItemDTO `json:"items"` Total *Summary `json:"total,omitempty"` } func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) RepportMarketingItemDTO { soDate := time.Time{} agingDays := 0 if mdp.MarketingProduct.Marketing.SoDate.Year() > 1 { soDate = mdp.MarketingProduct.Marketing.SoDate agingDays = int(time.Since(soDate).Hours() / 24) } realizationDate := time.Time{} if mdp.DeliveryDate != nil { realizationDate = *mdp.DeliveryDate } doNumber := marketingDTO.GenerateDeliveryOrderNumber(mdp.MarketingProduct.Marketing.SoNumber, mdp.DeliveryDate, mdp.MarketingProduct.ProductWarehouse.WarehouseId) totalWeightKg := mdp.UsageQty * mdp.AvgWeight salesAmount := totalWeightKg * mdp.UnitPrice var hpp float64 var hppAmount float64 if isProductEligibleForHpp(mdp, category) { hpp = hppPricePerKg hppAmount = totalWeightKg * hppPricePerKg } item := RepportMarketingItemDTO{ ID: int(mdp.Id), SoDate: soDate, RealizationDate: realizationDate, AgingDays: agingDays, DoNumber: doNumber, MarketingType: getMarketingType(mdp), Qty: mdp.UsageQty, AverageWeightKg: mdp.AvgWeight, TotalWeightKg: totalWeightKg, SalesPricePerKg: mdp.UnitPrice, HppPricePerKg: hpp, SalesAmount: salesAmount, HppAmount: hppAmount, } if mdp.MarketingProduct.ProductWarehouse.WarehouseId != 0 { mapped := warehouseDTO.ToWarehouseRelationDTO(mdp.MarketingProduct.ProductWarehouse.Warehouse) item.Warehouse = &mapped } if mdp.MarketingProduct.Marketing.CustomerId != 0 { mapped := customerDTO.ToCustomerRelationDTO(mdp.MarketingProduct.Marketing.Customer) item.Customer = &mapped } if mdp.MarketingProduct.Marketing.SalesPersonId != 0 { mapped := userDTO.ToUserRelationDTO(mdp.MarketingProduct.Marketing.SalesPerson) item.Sales = &mapped } item.VehicleNumber = mdp.VehicleNumber if mdp.MarketingProduct.ProductWarehouse.ProductId != 0 { mapped := productDTO.ToProductRelationDTO(mdp.MarketingProduct.ProductWarehouse.Product) item.Product = &mapped } return item } func ToRepportMarketingItemDTOs(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) []RepportMarketingItemDTO { items := make([]RepportMarketingItemDTO, 0, len(mdps)) for _, mdp := range mdps { items = append(items, ToRepportMarketingItemDTO(mdp, hppPricePerKg, category)) } return items } func ToRepportMarketingItemDTOsWithHppMap(mdps []entity.MarketingDeliveryProduct, hppMap map[uint]float64) []RepportMarketingItemDTO { items := make([]RepportMarketingItemDTO, 0, len(mdps)) for _, mdp := range mdps { hppPerKg := float64(0) category := "" if projectFlockKandang := mdp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil { if hpp, exists := hppMap[projectFlockKandang.ProjectFlockId]; exists { hppPerKg = hpp } category = projectFlockKandang.ProjectFlock.Category } item := ToRepportMarketingItemDTO(mdp, hppPerKg, category) items = append(items, item) } return items } func getMarketingType(mdp entity.MarketingDeliveryProduct) string { hasAyam, hasTelur := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags) if hasAyam { return "ayam" } if hasTelur { return "telur" } return "trading" } func checkProductFlags(flags []entity.Flag) (hasAyam, hasTelur bool) { if len(flags) == 0 { return false, false } for _, flag := range flags { ft := utils.FlagType(flag.Name) if ft == utils.FlagAyamAfkir || ft == utils.FlagAyamCulling || ft == utils.FlagAyamMati || ft == utils.FlagDOC || ft == utils.FlagPullet || ft == utils.FlagLayer { hasAyam = true } if ft == utils.FlagTelur || ft == utils.FlagTelurUtuh || ft == utils.FlagTelurPecah || ft == utils.FlagTelurPutih || ft == utils.FlagTelurRetak { hasTelur = true } } return hasAyam, hasTelur } func isProductEligibleForHpp(mdp entity.MarketingDeliveryProduct, category string) bool { hasAyam, hasTelur := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags) if utils.ProjectFlockCategory(category) == utils.ProjectFlockCategoryGrowing { return hasAyam } return hasAyam || hasTelur } func ToSummary(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) *Summary { if len(mdps) == 0 { return nil } totalQty := 0 totalWeightKg := 0.0 totalEligibleWeightKg := 0.0 totalSalesAmount := int64(0) totalHppAmount := int64(0) for _, mdp := range mdps { calculatedTotalWeight := mdp.UsageQty * mdp.AvgWeight totalQty += int(mdp.UsageQty) totalWeightKg += calculatedTotalWeight totalSalesAmount += int64(calculatedTotalWeight * mdp.UnitPrice) if isProductEligibleForHpp(mdp, category) { totalEligibleWeightKg += calculatedTotalWeight totalHppAmount += int64(calculatedTotalWeight * hppPricePerKg) } } totalHppPricePerKg := float64(0) if totalEligibleWeightKg > 0 { totalHppPricePerKg = float64(totalHppAmount) / totalEligibleWeightKg } return &Summary{ TotalQty: totalQty, TotalWeightKg: totalWeightKg, TotalSalesAmount: totalSalesAmount, TotalHppAmount: totalHppAmount, TotalHppPricePerKg: totalHppPricePerKg, } } func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary { if len(items) == 0 { return nil } totalQty := 0 totalWeightKg := 0.0 totalSalesAmount := int64(0) totalHppAmount := int64(0) for _, item := range items { totalQty += int(item.Qty) totalWeightKg += item.TotalWeightKg totalSalesAmount += int64(item.SalesAmount) totalHppAmount += int64(item.HppAmount) } totalHppPricePerKg := float64(0) if totalWeightKg > 0 { totalHppPricePerKg = float64(totalHppAmount) / totalWeightKg } return &Summary{ TotalQty: totalQty, TotalWeightKg: totalWeightKg, TotalSalesAmount: totalSalesAmount, TotalHppAmount: totalHppAmount, TotalHppPricePerKg: totalHppPricePerKg, } } func ToRepportMarketingResponseDTO(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) RepportMarketingResponseDTO { items := ToRepportMarketingItemDTOs(mdps, hppPricePerKg, category) total := ToSummary(mdps, hppPricePerKg, category) return RepportMarketingResponseDTO{ Items: items, Total: total, } }