mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
529 lines
19 KiB
Go
529 lines
19 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
|
||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||
productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||
"gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/dto"
|
||
marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/repositories"
|
||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/validations"
|
||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
||
|
||
"github.com/go-playground/validator/v10"
|
||
"github.com/gofiber/fiber/v2"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
type DeliveryOrdersService interface {
|
||
GetAll(ctx *fiber.Ctx, params *validation.DeliveryOrderQuery) ([]dto.MarketingListDTO, int64, error)
|
||
GetOne(ctx *fiber.Ctx, id uint) (*dto.MarketingDetailDTO, error)
|
||
CreateOne(ctx *fiber.Ctx, req *validation.DeliveryOrderCreate) (*dto.MarketingDetailDTO, error)
|
||
UpdateOne(ctx *fiber.Ctx, req *validation.DeliveryOrderUpdate, id uint) (*dto.MarketingDetailDTO, error)
|
||
}
|
||
|
||
type deliveryOrdersService struct {
|
||
Validate *validator.Validate
|
||
MarketingRepo marketingRepo.MarketingRepository
|
||
MarketingProductRepo marketingRepo.MarketingProductRepository
|
||
MarketingDeliveryProductRepo marketingRepo.MarketingDeliveryProductRepository
|
||
ApprovalSvc commonSvc.ApprovalService
|
||
FifoSvc commonSvc.FifoService
|
||
}
|
||
|
||
func NewDeliveryOrdersService(
|
||
marketingRepo marketingRepo.MarketingRepository,
|
||
marketingProductRepo marketingRepo.MarketingProductRepository,
|
||
marketingDeliveryProductRepo marketingRepo.MarketingDeliveryProductRepository,
|
||
approvalSvc commonSvc.ApprovalService,
|
||
fifoSvc commonSvc.FifoService,
|
||
validate *validator.Validate,
|
||
) DeliveryOrdersService {
|
||
return &deliveryOrdersService{
|
||
Validate: validate,
|
||
MarketingRepo: marketingRepo,
|
||
MarketingProductRepo: marketingProductRepo,
|
||
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
||
ApprovalSvc: approvalSvc,
|
||
FifoSvc: fifoSvc,
|
||
}
|
||
}
|
||
|
||
func (s deliveryOrdersService) withRelations(db *gorm.DB) *gorm.DB {
|
||
return db.
|
||
Preload("CreatedUser").
|
||
Preload("Customer").
|
||
Preload("SalesPerson").
|
||
Preload("Products.ProductWarehouse.Product").
|
||
Preload("Products.ProductWarehouse.Warehouse").
|
||
Preload("Products.DeliveryProduct")
|
||
}
|
||
|
||
func (s deliveryOrdersService) getMarketingWithDeliveries(c *fiber.Ctx, marketingId uint) (*dto.MarketingDetailDTO, error) {
|
||
marketing, err := s.MarketingRepo.GetByID(c.Context(), marketingId, s.withRelations)
|
||
if err != nil {
|
||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch marketing")
|
||
}
|
||
|
||
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowMarketing, marketingId, nil)
|
||
if err != nil {
|
||
}
|
||
marketing.LatestApproval = latestApproval
|
||
|
||
allDeliveryProducts, err := s.MarketingDeliveryProductRepo.GetByMarketingId(c.Context(), marketingId)
|
||
if err != nil {
|
||
allDeliveryProducts = []entity.MarketingDeliveryProduct{}
|
||
}
|
||
|
||
responseDTO := dto.ToMarketingDetailDTO(marketing, allDeliveryProducts)
|
||
return &responseDTO, nil
|
||
}
|
||
|
||
func (s deliveryOrdersService) GetAll(c *fiber.Ctx, params *validation.DeliveryOrderQuery) ([]dto.MarketingListDTO, int64, error) {
|
||
if err := s.Validate.Struct(params); err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
offset := (params.Page - 1) * params.Limit
|
||
|
||
marketings, total, err := s.MarketingRepo.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
|
||
db = db.
|
||
Preload("CreatedUser").
|
||
Preload("Customer").
|
||
Preload("SalesPerson").
|
||
Preload("Products.ProductWarehouse.Product").
|
||
Preload("Products.ProductWarehouse.Warehouse").
|
||
Preload("Products.DeliveryProduct")
|
||
|
||
if params.MarketingId != 0 {
|
||
return db.Where("id = ?", params.MarketingId)
|
||
}
|
||
return db.Order("created_at DESC").Order("updated_at DESC")
|
||
})
|
||
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
for i := range marketings {
|
||
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowMarketing, marketings[i].Id, func(db *gorm.DB) *gorm.DB {
|
||
return db.Preload("ActionUser")
|
||
})
|
||
if err != nil {
|
||
continue
|
||
}
|
||
marketings[i].LatestApproval = latestApproval
|
||
}
|
||
|
||
result := make([]dto.MarketingListDTO, len(marketings))
|
||
for i, marketing := range marketings {
|
||
result[i] = dto.ToMarketingListDTO(&marketing, []entity.MarketingDeliveryProduct{})
|
||
}
|
||
|
||
return result, total, nil
|
||
}
|
||
|
||
func (s deliveryOrdersService) GetOne(c *fiber.Ctx, id uint) (*dto.MarketingDetailDTO, error) {
|
||
|
||
marketing, err := s.MarketingRepo.GetByID(c.Context(), id, s.withRelations)
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, fiber.NewError(fiber.StatusNotFound, "Marketing not found")
|
||
}
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
allDeliveryProducts, err := s.MarketingDeliveryProductRepo.GetByMarketingId(c.Context(), id)
|
||
if err != nil {
|
||
allDeliveryProducts = []entity.MarketingDeliveryProduct{}
|
||
}
|
||
|
||
if s.ApprovalSvc != nil {
|
||
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), utils.ApprovalWorkflowMarketing, marketing.Id, func(db *gorm.DB) *gorm.DB {
|
||
return db.Preload("ActionUser")
|
||
})
|
||
if err != nil {
|
||
|
||
} else if len(approvals) > 0 {
|
||
if marketing.LatestApproval == nil {
|
||
latest := approvals[len(approvals)-1]
|
||
marketing.LatestApproval = &latest
|
||
}
|
||
} else {
|
||
marketing.LatestApproval = nil
|
||
}
|
||
}
|
||
|
||
responseDTO := dto.ToMarketingDetailDTO(marketing, allDeliveryProducts)
|
||
return &responseDTO, nil
|
||
}
|
||
|
||
func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.DeliveryOrderCreate) (*dto.MarketingDetailDTO, error) {
|
||
if err := s.Validate.Struct(req); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
if err := commonSvc.EnsureRelations(c.Context(),
|
||
commonSvc.RelationCheck{Name: "Marketing", ID: &req.MarketingId, Exists: s.MarketingRepo.IdExists},
|
||
); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
actorID, err := m.ActorIDFromContext(c)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(s.MarketingRepo.DB()))
|
||
|
||
latestApproval, err := approvalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowMarketing, req.MarketingId, nil)
|
||
if err != nil {
|
||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to check approval status")
|
||
}
|
||
if latestApproval == nil {
|
||
return nil, fiber.NewError(fiber.StatusBadRequest, "Marketing has not been submitted for approval")
|
||
}
|
||
if latestApproval.StepNumber < uint16(utils.MarketingStepSalesOrder) {
|
||
return nil, fiber.NewError(fiber.StatusBadRequest, "Marketing must be approved to Sales Order step before creating delivery order")
|
||
}
|
||
if latestApproval.StepNumber >= uint16(utils.MarketingDeliveryOrder) {
|
||
return nil, fiber.NewError(fiber.StatusBadRequest, "Delivery order already exists for this marketing")
|
||
}
|
||
|
||
err = s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||
|
||
marketingProductRepositoryTx := marketingRepo.NewMarketingProductRepository(dbTransaction)
|
||
marketingDeliveryProductRepositoryTx := marketingRepo.NewMarketingDeliveryProductRepository(dbTransaction)
|
||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||
|
||
allMarketingProducts, err := marketingProductRepositoryTx.GetByMarketingID(c.Context(), req.MarketingId)
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("No marketing products found for marketing %d", req.MarketingId))
|
||
}
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch marketing products")
|
||
}
|
||
|
||
for _, requestedProduct := range req.DeliveryProducts {
|
||
var foundMarketingProduct *entity.MarketingProduct
|
||
for i := range allMarketingProducts {
|
||
if allMarketingProducts[i].Id == requestedProduct.MarketingProductId {
|
||
foundMarketingProduct = &allMarketingProducts[i]
|
||
break
|
||
}
|
||
}
|
||
if foundMarketingProduct == nil {
|
||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Marketing product %d not found for this marketing", requestedProduct.MarketingProductId))
|
||
}
|
||
|
||
if err := commonSvc.EnsureProjectFlockNotClosedForProductWarehouses(
|
||
c.Context(),
|
||
dbTransaction,
|
||
[]uint{foundMarketingProduct.ProductWarehouseId},
|
||
); err != nil {
|
||
return err
|
||
}
|
||
|
||
deliveryProduct, err := marketingDeliveryProductRepositoryTx.GetByMarketingProductID(c.Context(), foundMarketingProduct.Id)
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Delivery product for marketing product %d not found", requestedProduct.MarketingProductId))
|
||
}
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch delivery product")
|
||
}
|
||
|
||
var itemDeliveryDate *time.Time
|
||
if requestedProduct.DeliveryDate != "" {
|
||
parsedDate, err := utils.ParseDateString(requestedProduct.DeliveryDate)
|
||
if err != nil {
|
||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid delivery date format for product %d: %v", requestedProduct.MarketingProductId, err))
|
||
}
|
||
itemDeliveryDate = &parsedDate
|
||
}
|
||
|
||
// Cek apakah product punya flag PAKAN atau OVK
|
||
isPakanOrOVK := false
|
||
if foundMarketingProduct.ProductWarehouse.Product.Id != 0 && len(foundMarketingProduct.ProductWarehouse.Product.Flags) > 0 {
|
||
for _, flag := range foundMarketingProduct.ProductWarehouse.Product.Flags {
|
||
if flag.Name == string(utils.FlagPakan) || flag.Name == string(utils.FlagOVK) {
|
||
isPakanOrOVK = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// Hitung total_weight dan total_price berdasarkan flag
|
||
totalWeight := requestedProduct.Qty * requestedProduct.AvgWeight
|
||
var totalPrice float64
|
||
if isPakanOrOVK {
|
||
// PAKAN atau OVK: qty × unit_price
|
||
totalPrice = requestedProduct.Qty * requestedProduct.UnitPrice
|
||
} else {
|
||
// Produk lain: total_weight × unit_price
|
||
totalPrice = totalWeight * requestedProduct.UnitPrice
|
||
}
|
||
|
||
deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId
|
||
deliveryProduct.UnitPrice = requestedProduct.UnitPrice
|
||
deliveryProduct.AvgWeight = requestedProduct.AvgWeight
|
||
deliveryProduct.TotalWeight = totalWeight
|
||
deliveryProduct.TotalPrice = totalPrice
|
||
deliveryProduct.DeliveryDate = itemDeliveryDate
|
||
deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber
|
||
|
||
if requestedProduct.Qty > 0 {
|
||
|
||
if err := s.consumeDeliveryStock(c.Context(), dbTransaction, deliveryProduct, foundMarketingProduct, requestedProduct.Qty); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
if err := marketingDeliveryProductRepositoryTx.UpdateOne(c.Context(), deliveryProduct.Id, deliveryProduct, nil); err != nil {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery product")
|
||
}
|
||
|
||
}
|
||
|
||
approvalAction := entity.ApprovalActionApproved
|
||
if _, err := approvalSvcTx.CreateApproval(
|
||
c.Context(),
|
||
utils.ApprovalWorkflowMarketing,
|
||
req.MarketingId,
|
||
utils.MarketingDeliveryOrder,
|
||
&approvalAction,
|
||
actorID,
|
||
nil); err != nil {
|
||
if !errors.Is(err, gorm.ErrDuplicatedKey) {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create delivery order approval")
|
||
}
|
||
}
|
||
|
||
return nil
|
||
})
|
||
|
||
if err != nil {
|
||
if fiberErr, ok := err.(*fiber.Error); ok {
|
||
return nil, fiberErr
|
||
}
|
||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to create delivery order")
|
||
}
|
||
|
||
return s.getMarketingWithDeliveries(c, req.MarketingId)
|
||
}
|
||
|
||
func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryOrderUpdate, id uint) (*dto.MarketingDetailDTO, error) {
|
||
if err := s.Validate.Struct(req); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
if err := commonSvc.EnsureRelations(c.Context(),
|
||
commonSvc.RelationCheck{Name: "Marketing", ID: &id, Exists: s.MarketingRepo.IdExists},
|
||
); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
err := s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||
|
||
marketingProductRepositoryTx := marketingRepo.NewMarketingProductRepository(dbTransaction)
|
||
marketingDeliveryProductRepositoryTx := marketingRepo.NewMarketingDeliveryProductRepository(dbTransaction)
|
||
|
||
allMarketingProducts, err := marketingProductRepositoryTx.GetByMarketingID(c.Context(), id)
|
||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch marketing products")
|
||
}
|
||
|
||
if len(req.DeliveryProducts) > 0 {
|
||
for _, requestedProduct := range req.DeliveryProducts {
|
||
|
||
var foundMarketingProduct *entity.MarketingProduct
|
||
for i := range allMarketingProducts {
|
||
if allMarketingProducts[i].Id == requestedProduct.MarketingProductId {
|
||
foundMarketingProduct = &allMarketingProducts[i]
|
||
break
|
||
}
|
||
}
|
||
if foundMarketingProduct == nil {
|
||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Marketing product %d not found for this marketing", requestedProduct.MarketingProductId))
|
||
}
|
||
if err := commonSvc.EnsureProjectFlockNotClosedForProductWarehouses(
|
||
c.Context(),
|
||
dbTransaction,
|
||
[]uint{foundMarketingProduct.ProductWarehouseId},
|
||
); err != nil {
|
||
return err
|
||
}
|
||
|
||
deliveryProduct, err := marketingDeliveryProductRepositoryTx.GetByMarketingProductID(c.Context(), foundMarketingProduct.Id)
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Delivery product for marketing product %d not found", requestedProduct.MarketingProductId))
|
||
}
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch delivery product")
|
||
}
|
||
|
||
var itemDeliveryDate *time.Time
|
||
if requestedProduct.DeliveryDate != "" {
|
||
parsedDate, err := utils.ParseDateString(requestedProduct.DeliveryDate)
|
||
if err != nil {
|
||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid delivery date format for product %d: %v", requestedProduct.MarketingProductId, err))
|
||
}
|
||
itemDeliveryDate = &parsedDate
|
||
} else if deliveryProduct.DeliveryDate != nil {
|
||
itemDeliveryDate = deliveryProduct.DeliveryDate
|
||
}
|
||
|
||
oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty
|
||
|
||
// Cek apakah product punya flag PAKAN atau OVK
|
||
isPakanOrOVK := false
|
||
if foundMarketingProduct.ProductWarehouse.Product.Id != 0 && len(foundMarketingProduct.ProductWarehouse.Product.Flags) > 0 {
|
||
for _, flag := range foundMarketingProduct.ProductWarehouse.Product.Flags {
|
||
if flag.Name == string(utils.FlagPakan) || flag.Name == string(utils.FlagOVK) {
|
||
isPakanOrOVK = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// Hitung total_weight dan total_price berdasarkan flag
|
||
totalWeight := requestedProduct.Qty * requestedProduct.AvgWeight
|
||
var totalPrice float64
|
||
if isPakanOrOVK {
|
||
// PAKAN atau OVK: qty × unit_price
|
||
totalPrice = requestedProduct.Qty * requestedProduct.UnitPrice
|
||
} else {
|
||
// Produk lain: total_weight × unit_price
|
||
totalPrice = totalWeight * requestedProduct.UnitPrice
|
||
}
|
||
|
||
deliveryProduct.ProductWarehouseId = foundMarketingProduct.ProductWarehouseId
|
||
deliveryProduct.UnitPrice = requestedProduct.UnitPrice
|
||
deliveryProduct.AvgWeight = requestedProduct.AvgWeight
|
||
deliveryProduct.TotalWeight = totalWeight
|
||
deliveryProduct.TotalPrice = totalPrice
|
||
deliveryProduct.DeliveryDate = itemDeliveryDate
|
||
deliveryProduct.VehicleNumber = requestedProduct.VehicleNumber
|
||
|
||
if requestedProduct.Qty != oldRequestedQty {
|
||
|
||
if oldRequestedQty > 0 {
|
||
if err := s.releaseDeliveryStock(c.Context(), dbTransaction, deliveryProduct, foundMarketingProduct); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
if requestedProduct.Qty > 0 {
|
||
if err := s.consumeDeliveryStock(c.Context(), dbTransaction, deliveryProduct, foundMarketingProduct, requestedProduct.Qty); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
if err := marketingDeliveryProductRepositoryTx.UpdateOne(c.Context(), deliveryProduct.Id, deliveryProduct, nil); err != nil {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery product")
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
})
|
||
|
||
if err != nil {
|
||
if fiberErr, ok := err.(*fiber.Error); ok {
|
||
return nil, fiberErr
|
||
}
|
||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery order")
|
||
}
|
||
|
||
return s.getMarketingWithDeliveries(c, id)
|
||
}
|
||
|
||
func (s deliveryOrdersService) consumeDeliveryStock(ctx context.Context, tx *gorm.DB, deliveryProduct *entity.MarketingDeliveryProduct, marketingProduct *entity.MarketingProduct, requestedQty float64) error {
|
||
if marketingProduct == nil || marketingProduct.ProductWarehouseId == 0 {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Product warehouse not found")
|
||
}
|
||
|
||
if deliveryProduct == nil || deliveryProduct.Id == 0 {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Delivery product not found")
|
||
}
|
||
|
||
result, err := s.FifoSvc.Consume(ctx, commonSvc.StockConsumeRequest{
|
||
UsableKey: fifo.UsableKeyMarketingDelivery,
|
||
UsableID: deliveryProduct.Id,
|
||
ProductWarehouseID: marketingProduct.ProductWarehouseId,
|
||
Quantity: requestedQty,
|
||
AllowPending: false,
|
||
Tx: tx,
|
||
})
|
||
|
||
deliveryProductRepo := marketingRepo.NewMarketingDeliveryProductRepository(tx)
|
||
|
||
if err != nil {
|
||
pwRepo := productWarehouseRepo.NewProductWarehouseRepository(tx)
|
||
pw, err2 := pwRepo.GetByID(ctx, marketingProduct.ProductWarehouseId, nil)
|
||
if err2 != nil {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check product warehouse stock")
|
||
}
|
||
|
||
if pw == nil || pw.Quantity < requestedQty {
|
||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Insufficient stock. Available: %.2f, Requested: %.2f", func() float64 {
|
||
if pw != nil {
|
||
return pw.Quantity
|
||
} else {
|
||
return 0
|
||
}
|
||
}(), requestedQty))
|
||
}
|
||
|
||
if err := deliveryProductRepo.UpdateFifoFields(ctx, deliveryProduct.Id, requestedQty, 0); err != nil {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery product")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
if err := deliveryProductRepo.UpdateFifoFields(ctx, deliveryProduct.Id, result.UsageQuantity, result.PendingQuantity); err != nil {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery product")
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func (s deliveryOrdersService) releaseDeliveryStock(ctx context.Context, tx *gorm.DB, deliveryProduct *entity.MarketingDeliveryProduct, marketingProduct *entity.MarketingProduct) error {
|
||
if deliveryProduct == nil || deliveryProduct.Id == 0 {
|
||
return nil
|
||
}
|
||
|
||
if marketingProduct == nil || marketingProduct.ProductWarehouseId == 0 {
|
||
return fiber.NewError(fiber.StatusInternalServerError, "Product warehouse not found")
|
||
}
|
||
|
||
deliveryProductRepo := marketingRepo.NewMarketingDeliveryProductRepository(tx)
|
||
currentUsage, err := deliveryProductRepo.GetUsageQty(ctx, deliveryProduct.Id)
|
||
if err != nil {
|
||
currentUsage = 0
|
||
}
|
||
|
||
if currentUsage == 0 {
|
||
return nil
|
||
}
|
||
|
||
if err := s.FifoSvc.ReleaseUsage(ctx, commonSvc.StockReleaseRequest{
|
||
UsableKey: fifo.UsableKeyMarketingDelivery,
|
||
UsableID: deliveryProduct.Id,
|
||
Tx: tx,
|
||
}); err != nil {
|
||
return err
|
||
}
|
||
|
||
if err := deliveryProductRepo.ResetFifoFields(ctx, deliveryProduct.Id); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|