mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
316 lines
11 KiB
Go
316 lines
11 KiB
Go
package dto
|
|
|
|
import (
|
|
"encoding/json"
|
|
"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"
|
|
productCategoryDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/product-categories/dto"
|
|
productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto"
|
|
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
|
|
uomDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/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 *ProductRelationDTOFixed `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"`
|
|
}
|
|
|
|
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 {
|
|
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, 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
|
|
}
|
|
|
|
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,
|
|
}
|
|
}
|
|
|
|
func newProductRelationDTOFixedPtr(original *productDTO.ProductRelationDTO) *ProductRelationDTOFixed {
|
|
if original == nil {
|
|
return nil
|
|
}
|
|
fixed := ProductRelationDTOFixed{
|
|
ProductRelationDTO: *original,
|
|
ProductPrice: original.ProductPrice,
|
|
SellingPrice: original.SellingPrice,
|
|
}
|
|
return &fixed
|
|
}
|
|
|
|
func (p ProductRelationDTOFixed) MarshalJSON() ([]byte, error) {
|
|
type Alias struct {
|
|
Id uint `json:"id"`
|
|
Name string `json:"name"`
|
|
ProductPrice float64 `json:"product_price"`
|
|
SellingPrice *float64 `json:"selling_price"`
|
|
Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"`
|
|
Flags *[]string `json:"flags,omitempty"`
|
|
ProductCategory *productCategoryDTO.ProductCategoryRelationDTO `json:"product_category,omitempty"`
|
|
Suppliers []supplierDTO.SupplierRelationDTO `json:"suppliers"`
|
|
}
|
|
|
|
return json.Marshal(&Alias{
|
|
Id: p.ProductRelationDTO.Id,
|
|
Name: p.ProductRelationDTO.Name,
|
|
ProductPrice: p.ProductPrice,
|
|
SellingPrice: p.SellingPrice,
|
|
Uom: p.ProductRelationDTO.Uom,
|
|
Flags: p.ProductRelationDTO.Flags,
|
|
ProductCategory: p.ProductRelationDTO.ProductCategory,
|
|
Suppliers: p.ProductRelationDTO.Suppliers,
|
|
})
|
|
}
|