364 lines
14 KiB
Go
364 lines
14 KiB
Go
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"
|
|
MESSAGE_FAILED_GET_INV_STORAGES = "failed get inventory storages by product and client"
|
|
MESSAGE_SUCCESS_GET_INV_STORAGES = "success get inventory storages by product and client"
|
|
MESSAGE_FAILED_GET_INV_TRANSACTIONS = "failed get inventory transactions by product and client"
|
|
MESSAGE_SUCCESS_GET_INV_TRANSACTIONS = "success get inventory transactions by product and client"
|
|
MESSAGE_SUCCESS_GET_CROSS_REFERENCES = "success get cross references by product and client"
|
|
MESSAGE_FAILED_GET_CROSS_REFERENCES = "failed get cross references by product and client"
|
|
)
|
|
|
|
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"`
|
|
// InvStorages []ProductInventoryStorageResponse `json:"inv_storages"`
|
|
}
|
|
|
|
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"`
|
|
}
|
|
|
|
ProductInventoryStorageResponse struct {
|
|
ID string `json:"id"`
|
|
Locater string `json:"locater"`
|
|
Lot string `json:"lot"`
|
|
OnHandQuantity float64 `json:"on_hand_quantity"`
|
|
AvailableQuantity float64 `json:"available_quantity"`
|
|
AisleID pkgdto.IdNameResponse `json:"aisle_id"`
|
|
Uom pkgdto.IdNameResponse `json:"uom"`
|
|
InvReceipt pkgdto.IdNameResponse `json:"inv_receipt"`
|
|
InvRequest pkgdto.IdNameResponse `json:"inv_request"`
|
|
}
|
|
)
|
|
|
|
func MapProductToResponse(product entities.MProductEntity) ProductResponse {
|
|
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,
|
|
},
|
|
}
|
|
}
|
|
|
|
func MapInventoryTransactionsToResponses(transactions []entities.InventoryTransactionEntity) []ProductInventoryTransactionResponse {
|
|
responses := make([]ProductInventoryTransactionResponse, 0, len(transactions))
|
|
for _, t := range transactions {
|
|
resp := MapInventoryTransactionToProductInventoryTransactionResponse(t)
|
|
if resp.ID != "" { // hanya tambahkan jika mapping valid
|
|
responses = append(responses, resp)
|
|
}
|
|
}
|
|
return responses
|
|
}
|
|
|
|
func MapInventoryTransactionToProductInventoryTransactionResponse(transaction entities.InventoryTransactionEntity) ProductInventoryTransactionResponse {
|
|
var transactionQuantity float64
|
|
var lot, locater, invReceiptRef, invIssueRef, invMoveRef string
|
|
var transactionDate string
|
|
valid := false
|
|
|
|
if transaction.InvReceipt.ID != uuid.Nil && transaction.InvReceipt.Status == constants.COMPLETED {
|
|
invReceiptRef = transaction.InvReceipt.ReferenceNumber
|
|
transactionDate = utils.DateTimeToString(transaction.TransactionDate)
|
|
for _, line := range transaction.InvReceipt.ReceiptLines {
|
|
if line.ProductID == transaction.ProductID {
|
|
transactionQuantity = line.Quantity
|
|
lot = line.BatchNumber
|
|
valid = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if transaction.InvIssue.ID != uuid.Nil && transaction.InvIssue.Status == constants.COMPLETED {
|
|
invIssueRef = transaction.InvIssue.DocumentNumber
|
|
transactionDate = utils.DateTimeToString(transaction.TransactionDate)
|
|
for _, line := range transaction.InvIssue.IssueLines {
|
|
if line.ProductID == transaction.ProductID {
|
|
transactionQuantity = line.IssuedQuantity
|
|
valid = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if transaction.InvMove.ID != uuid.Nil && transaction.InvMove.Status == constants.COMPLETED {
|
|
invMoveRef = transaction.InvMove.MovementNumber
|
|
transactionDate = utils.DateTimeToString(transaction.TransactionDate)
|
|
for _, line := range transaction.InvMove.MovementLines {
|
|
if line.ProductID == transaction.ProductID {
|
|
transactionQuantity = line.MovedQuantity
|
|
valid = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if !valid {
|
|
return ProductInventoryTransactionResponse{}
|
|
}
|
|
|
|
return ProductInventoryTransactionResponse{
|
|
ID: transaction.ID.String(),
|
|
TransactionDate: transactionDate,
|
|
TransactionType: transaction.TransactionType,
|
|
TransactionQuantity: transactionQuantity,
|
|
Lot: lot,
|
|
Locater: locater,
|
|
InvReceiptRef: invReceiptRef,
|
|
InvIssueRef: invIssueRef,
|
|
InvMoveRef: invMoveRef,
|
|
}
|
|
}
|
|
|
|
func MapInventoryStorageToProductInventoryStorageResponse(storage entities.InventoryStorageEntity) ProductInventoryStorageResponse {
|
|
return ProductInventoryStorageResponse{
|
|
ID: storage.ID.String(),
|
|
// Locater: storage.Locater,
|
|
// Lot: storage.BatchNumber,
|
|
OnHandQuantity: storage.OnHandQuantity,
|
|
AvailableQuantity: storage.AvailableQuantity,
|
|
AisleID: pkgdto.IdNameResponse{
|
|
ID: storage.Aisle.ID.String(),
|
|
Name: storage.Aisle.Name,
|
|
},
|
|
Uom: pkgdto.IdNameResponse{
|
|
ID: storage.Uom.ID.String(),
|
|
Name: storage.Uom.Name,
|
|
},
|
|
InvReceipt: pkgdto.IdNameResponse{
|
|
ID: storage.InvReceipt.ID.String(),
|
|
Name: storage.InvReceipt.ReferenceNumber,
|
|
},
|
|
InvRequest: pkgdto.IdNameResponse{
|
|
ID: storage.InvRequest.ID.String(),
|
|
Name: storage.InvRequest.ReferenceNumber,
|
|
},
|
|
}
|
|
}
|
|
|
|
func MapCrossReferenceToProductVendorResponse(crossRef entities.MCrossReferenceEntity) ProductVendorResponse {
|
|
return ProductVendorResponse{
|
|
ID: crossRef.Vendor.ID.String(),
|
|
Name: crossRef.Vendor.Name,
|
|
ContactPerson: crossRef.Vendor.ContactPerson,
|
|
SearchKey: crossRef.Vendor.SearchKey,
|
|
Address: crossRef.Vendor.Address}
|
|
}
|