mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +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 {
|
type Summary struct {
|
||||||
TotalQty int `json:"total_qty"`
|
TotalQty int `json:"total_qty"`
|
||||||
TotalWeightKg float64 `json:"total_weight_kg"`
|
TotalWeightKg float64 `json:"total_weight_kg"`
|
||||||
|
AverageWeightKg float64 `json:"average_weight_kg"`
|
||||||
|
AverageSalesAmount float64 `json:"average_sales_amount"`
|
||||||
TotalSalesAmount int64 `json:"total_sales_amount"`
|
TotalSalesAmount int64 `json:"total_sales_amount"`
|
||||||
TotalHppAmount int64 `json:"total_hpp_amount"`
|
TotalHppAmount int64 `json:"total_hpp_amount"`
|
||||||
TotalHppPricePerKg float64 `json:"total_hpp_price_per_kg"`
|
TotalHppPricePerKg float64 `json:"total_hpp_price_per_kg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RepportMarketingResponseDTO struct {
|
|
||||||
Items []RepportMarketingItemDTO `json:"items"`
|
|
||||||
Total *Summary `json:"total,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProductRelationDTOFixed struct {
|
type ProductRelationDTOFixed struct {
|
||||||
productDTO.ProductRelationDTO
|
productDTO.ProductRelationDTO
|
||||||
ProductPrice float64 `json:"product_price"`
|
ProductPrice float64 `json:"product_price"`
|
||||||
SellingPrice *float64 `json:"selling_price,omitempty"`
|
SellingPrice *float64 `json:"selling_price,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) RepportMarketingItemDTO {
|
func ToMarketingReportItems(mdps []entity.MarketingDeliveryProduct, hppMap map[uint]float64) []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 {
|
|
||||||
items := make([]RepportMarketingItemDTO, 0, len(mdps))
|
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 {
|
for _, mdp := range mdps {
|
||||||
|
// Get HPP and category from map
|
||||||
hppPerKg := float64(0)
|
hppPerKg := float64(0)
|
||||||
category := ""
|
category := ""
|
||||||
if projectFlockKandang := mdp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil {
|
if projectFlockKandang := mdp.MarketingProduct.ProductWarehouse.ProjectFlockKandang; projectFlockKandang != nil {
|
||||||
@@ -142,101 +67,111 @@ func ToRepportMarketingItemDTOsWithHppMap(mdps []entity.MarketingDeliveryProduct
|
|||||||
category = projectFlockKandang.ProjectFlock.Category
|
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)
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
return items
|
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 {
|
func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary {
|
||||||
if len(items) == 0 {
|
if len(items) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -244,6 +179,8 @@ func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary {
|
|||||||
|
|
||||||
totalQty := 0
|
totalQty := 0
|
||||||
totalWeightKg := 0.0
|
totalWeightKg := 0.0
|
||||||
|
avgSalesAmount := 0.0
|
||||||
|
avgWeightKg := 0.0
|
||||||
totalSalesAmount := int64(0)
|
totalSalesAmount := int64(0)
|
||||||
totalHppAmount := int64(0)
|
totalHppAmount := int64(0)
|
||||||
|
|
||||||
@@ -259,25 +196,26 @@ func ToSummaryFromDTOItems(items []RepportMarketingItemDTO) *Summary {
|
|||||||
totalHppPricePerKg = float64(totalHppAmount) / totalWeightKg
|
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{
|
return &Summary{
|
||||||
TotalQty: totalQty,
|
TotalQty: totalQty,
|
||||||
TotalWeightKg: totalWeightKg,
|
TotalWeightKg: totalWeightKg,
|
||||||
|
AverageWeightKg: avgWeightKg,
|
||||||
|
AverageSalesAmount: avgSalesAmount,
|
||||||
TotalSalesAmount: totalSalesAmount,
|
TotalSalesAmount: totalSalesAmount,
|
||||||
TotalHppAmount: totalHppAmount,
|
TotalHppAmount: totalHppAmount,
|
||||||
TotalHppPricePerKg: totalHppPricePerKg,
|
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 {
|
func newProductRelationDTOFixedPtr(original *productDTO.ProductRelationDTO) *ProductRelationDTOFixed {
|
||||||
if original == nil {
|
if original == nil {
|
||||||
return 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
|
return items, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user