mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 21:41:55 +00:00
FEAT[BE[: add avg weight and avg amount on get penjualan harian
This commit is contained in:
@@ -40,99 +40,24 @@ type RepportMarketingItemDTO struct {
|
||||
type Summary struct {
|
||||
TotalQty int `json:"total_qty"`
|
||||
TotalWeightKg float64 `json:"total_weight_kg"`
|
||||
AverageWeightKg float64 `json:"average_weight_kg"`
|
||||
AverageSalesAmount float64 `json:"average_sales_amount"`
|
||||
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"`
|
||||
}
|
||||
|
||||
type ProductRelationDTOFixed struct {
|
||||
productDTO.ProductRelationDTO
|
||||
ProductPrice float64 `json:"product_price"`
|
||||
SellingPrice *float64 `json:"selling_price,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 = newProductRelationDTOFixedPtr(&mapped)
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
func ToRepportMarketingItemDTOs(mdps []entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) []RepportMarketingItemDTO {
|
||||
func ToMarketingReportItems(mdps []entity.MarketingDeliveryProduct, hppMap map[uint]float64) []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 {
|
||||
// Get HPP and category from map
|
||||
hppPerKg := float64(0)
|
||||
category := ""
|
||||
if projectFlockKandang := mdp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil {
|
||||
@@ -142,101 +67,111 @@ func ToRepportMarketingItemDTOsWithHppMap(mdps []entity.MarketingDeliveryProduct
|
||||
category = projectFlockKandang.ProjectFlock.Category
|
||||
}
|
||||
|
||||
item := ToRepportMarketingItemDTO(mdp, hppPerKg, category)
|
||||
// Calculate dates
|
||||
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
|
||||
}
|
||||
|
||||
totalWeightKg := mdp.UsageQty * mdp.AvgWeight
|
||||
salesAmount := totalWeightKg * mdp.UnitPrice
|
||||
|
||||
var hpp float64
|
||||
var hppAmount float64
|
||||
|
||||
var hasAyam, hasTelur, hasTrading bool
|
||||
for _, flag := range mdp.MarketingProduct.ProductWarehouse.Product.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
|
||||
}
|
||||
|
||||
if ft == utils.FlagOVK || ft == utils.FlagObat || ft == utils.FlagVitamin || ft == utils.FlagKimia ||
|
||||
ft == utils.FlagPakan || ft == utils.FlagPreStarter || ft == utils.FlagStarter || ft == utils.FlagFinisher {
|
||||
hasTrading = true
|
||||
}
|
||||
}
|
||||
|
||||
// Determine marketing type
|
||||
marketingType := "trading"
|
||||
if hasTrading {
|
||||
marketingType = "trading"
|
||||
} else if hasTelur {
|
||||
marketingType = "telur"
|
||||
} else if hasAyam {
|
||||
marketingType = "ayam"
|
||||
}
|
||||
|
||||
eligibleForHpp := false
|
||||
|
||||
if utils.ProjectFlockCategory(category) == utils.ProjectFlockCategoryGrowing {
|
||||
eligibleForHpp = hasAyam
|
||||
} else {
|
||||
eligibleForHpp = hasAyam || hasTelur
|
||||
}
|
||||
|
||||
if eligibleForHpp {
|
||||
hpp = hppPerKg
|
||||
hppAmount = totalWeightKg * hppPerKg
|
||||
}
|
||||
|
||||
item := RepportMarketingItemDTO{
|
||||
ID: int(mdp.Id),
|
||||
SoDate: soDate,
|
||||
RealizationDate: realizationDate,
|
||||
AgingDays: agingDays,
|
||||
DoNumber: marketingDTO.GenerateDeliveryOrderNumber(mdp.MarketingProduct.Marketing.SoNumber, mdp.DeliveryDate, mdp.MarketingProduct.ProductWarehouse.WarehouseId),
|
||||
MarketingType: marketingType,
|
||||
Qty: mdp.UsageQty,
|
||||
AverageWeightKg: mdp.AvgWeight,
|
||||
TotalWeightKg: totalWeightKg,
|
||||
SalesPricePerKg: mdp.UnitPrice,
|
||||
HppPricePerKg: hpp,
|
||||
SalesAmount: salesAmount,
|
||||
HppAmount: hppAmount,
|
||||
VehicleNumber: mdp.VehicleNumber,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if mdp.MarketingProduct.ProductWarehouse.ProductId != 0 {
|
||||
mapped := productDTO.ToProductRelationDTO(mdp.MarketingProduct.ProductWarehouse.Product)
|
||||
item.Product = newProductRelationDTOFixedPtr(&mapped)
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
func getMarketingType(mdp entity.MarketingDeliveryProduct) string {
|
||||
hasAyam, hasTelur, hasTrading := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags)
|
||||
|
||||
if hasAyam {
|
||||
return "ayam"
|
||||
}
|
||||
if hasTelur {
|
||||
return "telur"
|
||||
}
|
||||
if hasTrading {
|
||||
return "trading"
|
||||
}
|
||||
return "trading" // default to trading if no flags found
|
||||
}
|
||||
|
||||
func checkProductFlags(flags []entity.Flag) (hasAyam, hasTelur, hasTrading bool) {
|
||||
if len(flags) == 0 {
|
||||
return false, 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
|
||||
}
|
||||
|
||||
if ft == utils.FlagOVK || ft == utils.FlagObat || ft == utils.FlagVitamin || ft == utils.FlagKimia ||
|
||||
ft == utils.FlagPakan || ft == utils.FlagPreStarter || ft == utils.FlagStarter || ft == utils.FlagFinisher {
|
||||
hasTrading = true
|
||||
}
|
||||
}
|
||||
|
||||
return hasAyam, hasTelur, hasTrading
|
||||
}
|
||||
|
||||
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
|
||||
@@ -244,6 +179,8 @@ func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary {
|
||||
|
||||
totalQty := 0
|
||||
totalWeightKg := 0.0
|
||||
avgSalesAmount := 0.0
|
||||
avgWeightKg := 0.0
|
||||
totalSalesAmount := int64(0)
|
||||
totalHppAmount := int64(0)
|
||||
|
||||
@@ -259,25 +196,26 @@ func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary {
|
||||
totalHppPricePerKg = float64(totalHppAmount) / totalWeightKg
|
||||
}
|
||||
|
||||
if len(items) > 0 {
|
||||
avgSalesAmount = float64(totalSalesAmount) / float64(len(items))
|
||||
}
|
||||
|
||||
if totalQty > 0 {
|
||||
avgWeightKg = totalWeightKg / float64(totalQty)
|
||||
avgSalesAmount = float64(totalSalesAmount) / float64(totalQty) // ← TAMBAHAN INI
|
||||
}
|
||||
|
||||
return &Summary{
|
||||
TotalQty: totalQty,
|
||||
TotalWeightKg: totalWeightKg,
|
||||
AverageWeightKg: avgWeightKg,
|
||||
AverageSalesAmount: avgSalesAmount,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
func newProductRelationDTOFixedPtr(original *productDTO.ProductRelationDTO) *ProductRelationDTOFixed {
|
||||
if original == nil {
|
||||
return nil
|
||||
|
||||
@@ -181,7 +181,7 @@ func (s *repportService) GetMarketing(c *fiber.Ctx, params *validation.Marketing
|
||||
}
|
||||
}
|
||||
|
||||
items := dto.ToRepportMarketingItemDTOsWithHppMap(deliveryProducts, hppMap)
|
||||
items := dto.ToMarketingReportItems(deliveryProducts, hppMap)
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user