package dto import ( "errors" "github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/Caknoooo/go-gin-clean-starter/pkg/constants" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/google/uuid" ) const ( MESSAGE_FAILED_CREATE_PRODUCT = "failed create product" MESSAGE_SUCCESS_CREATE_PRODUCT = "success create product" MESSAGE_FAILED_GET_PRODUCT = "failed get product" MESSAGE_SUCCESS_GET_PRODUCT = "success get product" MESSAGE_FAILED_UPDATE_PRODUCT = "failed update product" MESSAGE_SUCCESS_UPDATE_PRODUCT = "success update product" MESSAGE_FAILED_DELETE_PRODUCT = "failed delete product" MESSAGE_SUCCESS_DELETE_PRODUCT = "success delete product" MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body" MESSAGE_FAILED_ASSIGN_CROSS_REF = "failed assign cross reference" MESSAGE_SUCCESS_ASSIGN_CROSS_REF = "success assign cross reference" MESSAGE_FAILED_REMOVE_CROSS_REF = "failed remove cross reference" MESSAGE_SUCCESS_REMOVE_CROSS_REF = "success remove cross reference" ) var ( ErrCreateProduct = errors.New("failed to create product") ErrGetProductById = errors.New("failed to get product by id") ErrUpdateProduct = errors.New("failed to update product") ErrDeleteProduct = errors.New("failed to delete product") ErrAssignCrossRef = errors.New("failed to assign cross reference") ErrRemoveCrossRef = errors.New("failed to remove cross reference") ) type ( ProductCreateRequest struct { Name string `json:"name" binding:"required"` // RefNumber string `json:"ref_number" binding:"required"` SKU string `json:"sku" binding:"required"` Description string `json:"description"` Status string `json:"status" binding:"required"` IsReturnable bool `json:"is_returnable"` // DimLength float64 `json:"dim_length"` // DimWidth float64 `json:"dim_width"` // DimHeight float64 `json:"dim_height"` // Weight float64 `json:"weight"` // Volume float64 `json:"volume"` // MaxStackHeight int `json:"max_stack_height"` // Temperature string `json:"temperature"` // IsHazardous bool `json:"is_hazardous"` // MinStock int `json:"min_stock"` // MaxStock int `json:"max_stock"` // ReplenishType string `json:"replenish_type"` // CycleCount string `json:"cycle_count"` // LotRules string `json:"lot_rules"` // LeadTime int `json:"lead_time"` // MultiplyRate string `json:"multiply_rate"` // DivideRate float64 `json:"divide_rate"` ClientID string `json:"client_id" binding:"required"` CategoryID *string `json:"category_id"` UomID *string `json:"uom_id"` // DimUomID string `json:"dim_uom_id"` // WeightUomID string `json:"weight_uom_id"` // VolumeUomID string `json:"volume_uom_id"` // MinStockUomID string `json:"min_stock_uom_id"` // MaxStockUomID string `json:"max_stock_uom_id"` // LeadTimeUomID string `json:"lead_time_uom_id"` // UomToUomID string `json:"uom_to_uom_id"` } ProductUpdateRequest struct { Name *string `json:"name"` // RefNumber *string `json:"ref_number"` SKU *string `json:"sku"` Description *string `json:"description"` Status *string `json:"status"` IsReturnable *bool `json:"is_returnable"` DimLength *float64 `json:"dim_length"` DimWidth *float64 `json:"dim_width"` DimHeight *float64 `json:"dim_height"` Weight *float64 `json:"weight"` Volume *float64 `json:"volume"` MaxStackHeight *int `json:"max_stack_height"` Temperature *string `json:"temperature"` IsHazardous *bool `json:"is_hazardous"` MinStock *int `json:"min_stock"` MaxStock *int `json:"max_stock"` ReplenishType *string `json:"replenish_type"` CycleCount *string `json:"cycle_count"` LotRules *string `json:"lot_rules"` LeadTime *int `json:"lead_time"` MultiplyRate *string `json:"multiply_rate"` DivideRate *float64 `json:"divide_rate"` ClientID *string `json:"client_id"` CategoryID *string `json:"category_id"` UomID *string `json:"uom_id"` DimUomID *string `json:"dim_uom_id"` WeightUomID *string `json:"weight_uom_id"` VolumeUomID *string `json:"volume_uom_id"` MinStockUomID *string `json:"min_stock_uom_id"` MaxStockUomID *string `json:"max_stock_uom_id"` LeadTimeUomID *string `json:"lead_time_uom_id"` UomToUomID *string `json:"uom_to_uom_id"` } ProductResponse struct { ID string `json:"id"` Name string `json:"name"` RefNumber string `json:"ref_number"` SKU string `json:"sku"` Description string `json:"description"` Status string `json:"status"` IsReturnable bool `json:"is_returnable"` DimLength float64 `json:"dim_length"` DimWidth float64 `json:"dim_width"` DimHeight float64 `json:"dim_height"` Weight float64 `json:"weight"` Volume float64 `json:"volume"` MaxStackHeight int `json:"max_stack_height"` Temperature string `json:"temperature"` IsHazardous bool `json:"is_hazardous"` MinStock int `json:"min_stock"` MaxStock int `json:"max_stock"` ReplenishType string `json:"replenish_type"` CycleCount string `json:"cycle_count"` LotRules string `json:"lot_rules"` LeadTime int `json:"lead_time"` MultiplyRate string `json:"multiply_rate"` DivideRate float64 `json:"divide_rate"` Client pkgdto.IdNameResponse `json:"client"` Category pkgdto.IdNameResponse `json:"category"` Uom pkgdto.IdNameResponse `json:"uom"` DimUom pkgdto.IdNameResponse `json:"dim_uom"` WeightUom pkgdto.IdNameResponse `json:"weight_uom"` VolumeUom pkgdto.IdNameResponse `json:"volume_uom"` MinStockUom pkgdto.IdNameResponse `json:"min_stock_uom"` MaxStockUom pkgdto.IdNameResponse `json:"max_stock_uom"` LeadTimeUom pkgdto.IdNameResponse `json:"lead_time_uom"` UomToUom pkgdto.IdNameResponse `json:"uom_to_uom"` CrossReferences []ProductVendorResponse `json:"cross_references"` InvTransactions []ProductInventoryTransactionResponse `json:"inv_transactions"` } CrossReferenceRequest struct { VendorIDs []string `json:"vendor_ids" binding:"required"` } ProductVendorResponse struct { ID string `json:"id"` Name string `json:"name"` SearchKey string `json:"search_key"` Address string `json:"address"` ContactPerson string `json:"contact_person"` } ProductInventoryTransactionResponse struct { ID string `json:"id"` TransactionDate string `json:"transaction_date"` TransactionType string `json:"transaction_type"` TransactionQuantity float64 `json:"transaction_quantity"` Lot string `json:"lot"` Locater string `json:"locater"` InvReceiptRef string `json:"inv_receipt_ref,omitempty"` InvIssueRef string `json:"inv_issue_ref,omitempty"` InvMoveRef string `json:"inv_move_ref,omitempty"` } ) func MapProductToResponse(product entities.MProductEntity) ProductResponse { crossRefs := make([]ProductVendorResponse, 0, len(product.CrossReferences)) for _, v := range product.CrossReferences { crossRefs = append(crossRefs, ProductVendorResponse{ ID: v.Vendor.ID.String(), Name: v.Vendor.Name, Address: v.Vendor.Address, ContactPerson: v.Vendor.ContactPerson, SearchKey: v.Vendor.SearchKey, }) } invTransactions := make([]ProductInventoryTransactionResponse, 0, len(product.InventoryTransactions)) for _, it := range product.InventoryTransactions { var transactionQuantity float64 var lot, locater, invReceiptRef, invIssueRef, invMoveRef string var transactionDate string valid := false // Receipt if it.InvReceipt.ID != uuid.Nil && it.InvReceipt.Status == constants.COMPLETED { invReceiptRef = it.InvReceipt.ReferenceNumber transactionDate = utils.DateTimeToString(it.TransactionDate) for _, line := range it.InvReceipt.ReceiptLines { if line.ProductID == it.ProductID { transactionQuantity = line.Quantity lot = line.BatchNumber valid = true break } } } // Issue if it.InvIssue.ID != uuid.Nil && it.InvIssue.Status == constants.COMPLETED { invIssueRef = it.InvIssue.DocumentNumber transactionDate = utils.DateTimeToString(it.TransactionDate) for _, line := range it.InvIssue.IssueLines { if line.ProductID == it.ProductID { transactionQuantity = line.IssuedQuantity valid = true break } } } // Move if it.InvMove.ID != uuid.Nil && it.InvMove.Status == constants.COMPLETED { invMoveRef = it.InvMove.MovementNumber transactionDate = utils.DateTimeToString(it.TransactionDate) for _, line := range it.InvMove.MovementLines { if line.ProductID == it.ProductID { transactionQuantity = line.MovedQuantity valid = true break } } } if valid { invTransactions = append(invTransactions, ProductInventoryTransactionResponse{ ID: it.ID.String(), TransactionDate: transactionDate, TransactionType: it.TransactionType, TransactionQuantity: transactionQuantity, Lot: lot, Locater: locater, InvReceiptRef: invReceiptRef, InvIssueRef: invIssueRef, InvMoveRef: invMoveRef, }) } } return ProductResponse{ ID: product.ID.String(), Name: product.Name, RefNumber: product.RefNumber, SKU: product.SKU, Description: product.Description, Status: product.Status, IsReturnable: product.IsReturnable, DimLength: product.DimLength, DimWidth: product.DimWidth, DimHeight: product.DimHeight, Weight: product.Weight, Volume: product.Volume, MaxStackHeight: product.MaxStackHeight, Temperature: product.Temperature, IsHazardous: product.IsHazardous, MinStock: product.MinStock, MaxStock: product.MaxStock, ReplenishType: product.ReplenishType, CycleCount: product.CycleCount, LotRules: product.LotRules, LeadTime: product.LeadTime, MultiplyRate: product.MultiplyRate, DivideRate: product.DivideRate, Client: pkgdto.IdNameResponse{ ID: product.Client.ID.String(), Name: product.Client.Name, }, Category: pkgdto.IdNameResponse{ ID: product.Category.ID.String(), Name: product.Category.Name, }, Uom: pkgdto.IdNameResponse{ ID: product.Uom.ID.String(), Name: product.Uom.Name, }, DimUom: pkgdto.IdNameResponse{ ID: product.DimUom.ID.String(), Name: product.DimUom.Name, }, WeightUom: pkgdto.IdNameResponse{ ID: product.WeightUom.ID.String(), Name: product.WeightUom.Name, }, VolumeUom: pkgdto.IdNameResponse{ ID: product.VolumeUom.ID.String(), Name: product.VolumeUom.Name, }, MinStockUom: pkgdto.IdNameResponse{ ID: product.MinStockUom.ID.String(), Name: product.MinStockUom.Name, }, MaxStockUom: pkgdto.IdNameResponse{ ID: product.MaxStockUom.ID.String(), Name: product.MaxStockUom.Name, }, LeadTimeUom: pkgdto.IdNameResponse{ ID: product.LeadTimeUom.ID.String(), Name: product.LeadTimeUom.Name, }, UomToUom: pkgdto.IdNameResponse{ ID: product.UomToUom.ID.String(), Name: product.UomToUom.Name, }, CrossReferences: crossRefs, InvTransactions: invTransactions, } }