mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
494 lines
19 KiB
Go
494 lines
19 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"mime/multipart"
|
|
"strings"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sirupsen/logrus"
|
|
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"
|
|
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
|
rStockTransfer "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/repositories"
|
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/validations"
|
|
rSupplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories"
|
|
warehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
|
|
projectFlockKandangRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
|
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
|
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type TransferService interface {
|
|
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.StockTransfer, int64, error)
|
|
GetOne(ctx *fiber.Ctx, id uint) (*entity.StockTransfer, error)
|
|
CreateOne(ctx *fiber.Ctx, req *validation.TransferRequest, files []*multipart.FileHeader) (*entity.StockTransfer, error)
|
|
}
|
|
|
|
type transferService struct {
|
|
Log *logrus.Logger
|
|
Validate *validator.Validate
|
|
StockTransferRepo rStockTransfer.StockTransferRepository
|
|
StockTransferDetailRepo rStockTransfer.StockTransferDetailRepository
|
|
StockTransferDeliveryRepo rStockTransfer.StockTransferDeliveryRepository
|
|
StockTransferDeliveryItemRepo rStockTransfer.StockTransferDeliveryItemRepository
|
|
StockLogsRepository rStockLogs.StockLogRepository
|
|
ProductWarehouseRepo rProductWarehouse.ProductWarehouseRepository
|
|
SupplierRepo rSupplier.SupplierRepository
|
|
WarehouseRepo warehouseRepo.WarehouseRepository
|
|
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
|
DocumentSvc commonSvc.DocumentService
|
|
FifoSvc commonSvc.FifoService
|
|
ExpenseBridge TransferExpenseBridge
|
|
}
|
|
|
|
func NewTransferService(validate *validator.Validate, stockTransferRepo rStockTransfer.StockTransferRepository, stockTransferDetailRepo rStockTransfer.StockTransferDetailRepository, stockTransferDeliveryRepo rStockTransfer.StockTransferDeliveryRepository, stockTransferDeliveryItemRepo rStockTransfer.StockTransferDeliveryItemRepository, stockLogsRepo rStockLogs.StockLogRepository, productWarehouseRepo rProductWarehouse.ProductWarehouseRepository, supplierRepo rSupplier.SupplierRepository, warehouseRepo warehouseRepo.WarehouseRepository, projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository, documentSvc commonSvc.DocumentService, fifoSvc commonSvc.FifoService, expenseBridge TransferExpenseBridge) TransferService {
|
|
return &transferService{
|
|
Log: utils.Log,
|
|
Validate: validate,
|
|
StockTransferRepo: stockTransferRepo,
|
|
StockTransferDetailRepo: stockTransferDetailRepo,
|
|
StockTransferDeliveryRepo: stockTransferDeliveryRepo,
|
|
StockTransferDeliveryItemRepo: stockTransferDeliveryItemRepo,
|
|
StockLogsRepository: stockLogsRepo,
|
|
ProductWarehouseRepo: productWarehouseRepo,
|
|
SupplierRepo: supplierRepo,
|
|
WarehouseRepo: warehouseRepo,
|
|
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
|
DocumentSvc: documentSvc,
|
|
FifoSvc: fifoSvc,
|
|
ExpenseBridge: expenseBridge,
|
|
}
|
|
}
|
|
|
|
func (s transferService) withRelations(db *gorm.DB) *gorm.DB {
|
|
return db.
|
|
Preload("CreatedUser").
|
|
Preload("FromWarehouse").
|
|
Preload("FromWarehouse.Location").
|
|
Preload("FromWarehouse.Area").
|
|
Preload("ToWarehouse").
|
|
Preload("ToWarehouse.Location").
|
|
Preload("ToWarehouse.Area").
|
|
Preload("Details").
|
|
Preload("Details.Product").
|
|
Preload("Details.ExpenseNonstock").
|
|
Preload("Details.ExpenseNonstock.Expense").
|
|
Preload("Details.ExpenseNonstock.Expense.Supplier").
|
|
Preload("Deliveries.Items").
|
|
Preload("Deliveries.Supplier").
|
|
Preload("Deliveries.Documents", func(db *gorm.DB) *gorm.DB {
|
|
return db.Where("documentable_type = ?", string(utils.DocumentableTypeTransfer))
|
|
})
|
|
}
|
|
|
|
func (s transferService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.StockTransfer, int64, error) {
|
|
if err := s.Validate.Struct(params); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
offset := (params.Page - 1) * params.Limit
|
|
|
|
transfers, total, err := s.StockTransferRepo.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
|
|
db = s.withRelations(db)
|
|
if params.Search != "" {
|
|
db = db.Where("LOWER(movement_number) LIKE LOWER(?)", "%"+strings.TrimSpace(params.Search)+"%")
|
|
}
|
|
return db.Order("created_at DESC").Order("updated_at DESC")
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return transfers, total, nil
|
|
}
|
|
|
|
func (s transferService) GetOne(c *fiber.Ctx, id uint) (*entity.StockTransfer, error) {
|
|
|
|
transferPtr, err := s.StockTransferRepo.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB {
|
|
return s.withRelations(db)
|
|
})
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fiber.NewError(fiber.StatusNotFound, "Transfer not found")
|
|
}
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to get transfer")
|
|
}
|
|
|
|
return transferPtr, nil
|
|
}
|
|
|
|
func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferRequest, files []*multipart.FileHeader) (*entity.StockTransfer, error) {
|
|
|
|
pwIDs := make([]uint, 0, len(req.Products))
|
|
|
|
for _, product := range req.Products {
|
|
sourcePW, err := s.ProductWarehouseRepo.GetProductWarehouseByProductAndWarehouseID(
|
|
c.Context(), uint(product.ProductID), uint(req.SourceWarehouseID),
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok produk %d tidak tersedia di gudang asal", product.ProductID))
|
|
}
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal cek stok produk di gudang asal")
|
|
}
|
|
if sourcePW.Quantity < product.ProductQty {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok produk %d di gudang asal tidak cukup", product.ProductID))
|
|
}
|
|
pwIDs = append(pwIDs, sourcePW.Id)
|
|
}
|
|
|
|
if err := commonSvc.EnsureProjectFlockNotClosedForProductWarehouses(
|
|
c.Context(),
|
|
s.StockTransferRepo.DB(),
|
|
pwIDs,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
destPfkID, err := s.getActiveProjectFlockKandangID(c.Context(), uint(req.DestinationWarehouseID))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
projectFlockKandang, err := s.ProjectFlockKandangRepo.GetByID(c.Context(), destPfkID)
|
|
if err != nil {
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data project flock")
|
|
}
|
|
if projectFlockKandang.ClosedAt != nil {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Project flock tujuan sudah closing")
|
|
}
|
|
|
|
actorID, err := m.ActorIDFromContext(c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
deliveryQtyMap := make(map[uint]float64)
|
|
for _, delivery := range req.Deliveries {
|
|
for _, prod := range delivery.Products {
|
|
deliveryQtyMap[prod.ProductID] += prod.ProductQty
|
|
}
|
|
}
|
|
|
|
for _, product := range req.Products {
|
|
if deliveryQtyMap[product.ProductID] > product.ProductQty {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest,
|
|
fmt.Sprintf("Total qty delivery untuk produk %d (%v) melebihi qty transfer (%v)", product.ProductID, deliveryQtyMap[product.ProductID], product.ProductQty))
|
|
}
|
|
}
|
|
|
|
for _, delivery := range req.Deliveries {
|
|
supplier, err := s.SupplierRepo.GetByID(c.Context(), uint(delivery.SupplierID), nil)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Supplier dengan ID %d tidak ditemukan", delivery.SupplierID))
|
|
}
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal cek data supplier")
|
|
}
|
|
if supplier.Category != string(utils.SupplierCategoryBOP) {
|
|
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Supplier dengan ID %d bukan kategori BOP", delivery.SupplierID))
|
|
}
|
|
}
|
|
|
|
movementNumber, err := s.StockTransferRepo.GenerateMovementNumber(c.Context())
|
|
if err != nil {
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to generate movement number")
|
|
}
|
|
|
|
transferDate, _ := utils.ParseDateString(req.TransferDate)
|
|
|
|
entityTransfer := &entity.StockTransfer{
|
|
FromWarehouseId: uint64(req.SourceWarehouseID),
|
|
ToWarehouseId: uint64(req.DestinationWarehouseID),
|
|
Reason: req.TransferReason,
|
|
TransferDate: transferDate,
|
|
MovementNumber: movementNumber,
|
|
CreatedBy: uint64(actorID),
|
|
}
|
|
|
|
expensePayloads := make([]TransferExpenseReceivingPayload, 0)
|
|
|
|
err = s.StockTransferRepo.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
|
|
|
stockTransferRepoTX := s.StockTransferRepo.WithTx(tx)
|
|
stockTransferDetailRepoTX := s.StockTransferDetailRepo.WithTx(tx)
|
|
stockTransferDeliveryRepoTX := s.StockTransferDeliveryRepo.WithTx(tx)
|
|
stockTransferDeliveryItemRepoTX := s.StockTransferDeliveryItemRepo.WithTx(tx)
|
|
productWarehouseRepoTX := rProductWarehouse.NewProductWarehouseRepository(tx)
|
|
|
|
if err := stockTransferRepoTX.CreateOne(c.Context(), entityTransfer, nil); err != nil {
|
|
return err
|
|
}
|
|
|
|
details := make([]*entity.StockTransferDetail, 0, len(req.Products))
|
|
detailMap := make(map[uint64]*entity.StockTransferDetail)
|
|
|
|
for _, product := range req.Products {
|
|
|
|
sourcePW, err := productWarehouseRepoTX.GetProductWarehouseByProductAndWarehouseID(
|
|
c.Context(), uint(product.ProductID), uint(req.SourceWarehouseID),
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok produk %d tidak tersedia di gudang asal", product.ProductID))
|
|
}
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data product warehouse source")
|
|
}
|
|
|
|
destPW, err := productWarehouseRepoTX.GetProductWarehouseByProductAndWarehouseID(
|
|
c.Context(), uint(product.ProductID), uint(req.DestinationWarehouseID),
|
|
)
|
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data product warehouse destination")
|
|
}
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
ctx := c.Context()
|
|
projectFlockKandangID, err := s.getActiveProjectFlockKandangID(ctx, uint(req.DestinationWarehouseID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
destPW = &entity.ProductWarehouse{
|
|
ProductId: uint(product.ProductID),
|
|
WarehouseId: uint(req.DestinationWarehouseID),
|
|
Quantity: 0,
|
|
ProjectFlockKandangId: &projectFlockKandangID,
|
|
}
|
|
if err := productWarehouseRepoTX.CreateOne(c.Context(), destPW, nil); err != nil {
|
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal membuat product warehouse destination")
|
|
}
|
|
}
|
|
|
|
detail := &entity.StockTransferDetail{
|
|
StockTransferId: entityTransfer.Id,
|
|
ProductId: uint64(product.ProductID),
|
|
|
|
SourceProductWarehouseID: func() *uint64 { id := uint64(sourcePW.Id); return &id }(),
|
|
UsageQty: 0,
|
|
PendingQty: 0,
|
|
|
|
DestProductWarehouseID: func() *uint64 { id := uint64(destPW.Id); return &id }(),
|
|
TotalQty: 0,
|
|
TotalUsed: 0,
|
|
}
|
|
details = append(details, detail)
|
|
detailMap[uint64(product.ProductID)] = detail
|
|
}
|
|
|
|
if err := stockTransferDetailRepoTX.CreateMany(c.Context(), details, nil); err != nil {
|
|
return err
|
|
}
|
|
|
|
var deliveries []*entity.StockTransferDelivery
|
|
for _, delivery := range req.Deliveries {
|
|
deliveries = append(deliveries, &entity.StockTransferDelivery{
|
|
StockTransferId: entityTransfer.Id,
|
|
SupplierId: uint64(delivery.SupplierID),
|
|
VehiclePlate: delivery.VehiclePlate,
|
|
DriverName: delivery.DriverName,
|
|
ShippingCostItem: delivery.DeliveryCostPerItem,
|
|
ShippingCostTotal: delivery.DeliveryCost,
|
|
})
|
|
}
|
|
if err := stockTransferDeliveryRepoTX.CreateMany(c.Context(), deliveries, nil); err != nil {
|
|
return err
|
|
}
|
|
|
|
var deliveryItems []*entity.StockTransferDeliveryItem
|
|
|
|
for i, delivery := range deliveries {
|
|
item := req.Deliveries[i]
|
|
for _, prod := range item.Products {
|
|
detail, ok := detailMap[uint64(prod.ProductID)]
|
|
if !ok {
|
|
return fmt.Errorf("produk %d tidak ditemukan di detail", prod.ProductID)
|
|
}
|
|
deliveryItems = append(deliveryItems, &entity.StockTransferDeliveryItem{
|
|
StockTransferDeliveryId: delivery.Id,
|
|
StockTransferDetailId: detail.Id,
|
|
Quantity: prod.ProductQty,
|
|
})
|
|
}
|
|
}
|
|
if err := stockTransferDeliveryItemRepoTX.CreateMany(c.Context(), deliveryItems, nil); err != nil {
|
|
return err
|
|
}
|
|
|
|
if s.DocumentSvc != nil && len(files) > 0 {
|
|
|
|
for deliveryIdx, delivery := range deliveries {
|
|
reqDelivery := req.Deliveries[deliveryIdx]
|
|
|
|
if reqDelivery.DocumentIndex < 0 {
|
|
continue
|
|
}
|
|
|
|
if reqDelivery.DocumentIndex >= len(files) {
|
|
return fiber.NewError(fiber.StatusBadRequest,
|
|
fmt.Sprintf("DocumentIndex %d untuk delivery %d melebihi jumlah file yang diupload (%d)",
|
|
reqDelivery.DocumentIndex, deliveryIdx+1, len(files)))
|
|
}
|
|
|
|
file := files[reqDelivery.DocumentIndex]
|
|
|
|
documentFiles := []commonSvc.DocumentFile{
|
|
{
|
|
File: file,
|
|
Type: string(utils.DocumentTypeTransfer),
|
|
Index: &reqDelivery.DocumentIndex,
|
|
},
|
|
}
|
|
_, err := s.DocumentSvc.UploadDocuments(c.Context(), commonSvc.DocumentUploadRequest{
|
|
DocumentableType: string(utils.DocumentableTypeTransfer),
|
|
DocumentableID: delivery.Id,
|
|
CreatedBy: &actorID,
|
|
Files: documentFiles,
|
|
})
|
|
if err != nil {
|
|
s.Log.WithError(err).Errorf("Failed to upload document for delivery %d (delivery_id: %d, filename: %s)",
|
|
deliveryIdx+1, delivery.Id, file.Filename)
|
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to upload document for delivery %d: %v", deliveryIdx+1, err))
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, product := range req.Products {
|
|
detail := detailMap[uint64(product.ProductID)]
|
|
|
|
consumeResult, err := s.FifoSvc.Consume(c.Context(), commonSvc.StockConsumeRequest{
|
|
UsableKey: fifo.UsableKeyStockTransferOut,
|
|
UsableID: uint(detail.Id),
|
|
ProductWarehouseID: uint(*detail.SourceProductWarehouseID),
|
|
Quantity: product.ProductQty,
|
|
AllowPending: false,
|
|
Tx: tx,
|
|
})
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok tidak cukup di gudang asal untuk produk %d: %v", product.ProductID, err))
|
|
}
|
|
|
|
if err := tx.Model(&entity.StockTransferDetail{}).
|
|
Where("id = ?", detail.Id).
|
|
Updates(map[string]interface{}{
|
|
"usage_qty": consumeResult.UsageQuantity,
|
|
"pending_qty": consumeResult.PendingQuantity,
|
|
}).Error; err != nil {
|
|
return fmt.Errorf("gagal update usage tracking: %w", err)
|
|
}
|
|
|
|
note := fmt.Sprintf("Transfer #%s", entityTransfer.MovementNumber)
|
|
replenishResult, err := s.FifoSvc.Replenish(c.Context(), commonSvc.StockReplenishRequest{
|
|
StockableKey: fifo.StockableKeyStockTransferIn,
|
|
StockableID: uint(detail.Id),
|
|
ProductWarehouseID: uint(*detail.DestProductWarehouseID),
|
|
Quantity: product.ProductQty,
|
|
Note: ¬e,
|
|
Tx: tx,
|
|
})
|
|
if err != nil {
|
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Gagal menambah stok di gudang tujuan untuk produk %d: %v", product.ProductID, err))
|
|
}
|
|
|
|
if err := tx.Model(&entity.StockTransferDetail{}).
|
|
Where("id = ?", detail.Id).
|
|
Updates(map[string]interface{}{
|
|
"total_qty": replenishResult.AddedQuantity,
|
|
}).Error; err != nil {
|
|
return fmt.Errorf("gagal update total tracking: %w", err)
|
|
}
|
|
}
|
|
|
|
if len(req.Deliveries) > 0 {
|
|
for _, delivery := range req.Deliveries {
|
|
for _, prod := range delivery.Products {
|
|
detail := detailMap[uint64(prod.ProductID)]
|
|
if detail == nil {
|
|
continue
|
|
}
|
|
|
|
warehouseID := uint(req.DestinationWarehouseID)
|
|
supplierID := uint(delivery.SupplierID)
|
|
deliveredDate := transferDate
|
|
deliveredQty := prod.ProductQty
|
|
|
|
payload := TransferExpenseReceivingPayload{
|
|
TransferDetailID: detail.Id,
|
|
ProductID: uint64(prod.ProductID),
|
|
WarehouseID: uint64(warehouseID),
|
|
SupplierID: uint64(supplierID),
|
|
DeliveredQty: deliveredQty,
|
|
DeliveredDate: &deliveredDate,
|
|
}
|
|
expensePayloads = append(expensePayloads, payload)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to process transfer transaction: %v", err))
|
|
}
|
|
|
|
result, err := s.GetOne(c, uint(entityTransfer.Id))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(expensePayloads) > 0 {
|
|
if err := s.notifyExpenseItemsDelivered(c, entityTransfer.Id, expensePayloads); err != nil {
|
|
s.Log.Errorf("Failed to sync expense for transfer %d: %+v", entityTransfer.Id, err)
|
|
return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to sync expense: %v", err))
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (s *transferService) notifyExpenseItemsDelivered(c *fiber.Ctx, transferID uint64, payloads []TransferExpenseReceivingPayload) error {
|
|
if s.ExpenseBridge == nil || transferID == 0 || len(payloads) == 0 {
|
|
return nil
|
|
}
|
|
return s.ExpenseBridge.OnItemsDelivered(c, transferID, payloads)
|
|
}
|
|
|
|
func (s *transferService) notifyExpenseDetailsDeleted(ctx context.Context, transferID uint64, items []entity.StockTransferDetail) error {
|
|
if s.ExpenseBridge == nil || transferID == 0 || len(items) == 0 {
|
|
return nil
|
|
}
|
|
return s.ExpenseBridge.OnItemsDeleted(ctx, transferID, items)
|
|
}
|
|
|
|
func (s *transferService) getActiveProjectFlockKandangID(ctx context.Context, warehouseID uint) (uint, error) {
|
|
warehouse, err := s.WarehouseRepo.GetByID(ctx, warehouseID, nil)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return 0, fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Gudang dengan ID %d tidak ditemukan", warehouseID))
|
|
}
|
|
return 0, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data gudang")
|
|
}
|
|
|
|
if warehouse.KandangId == nil || *warehouse.KandangId == 0 {
|
|
return 0, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Gudang %d belum terhubung ke kandang", warehouseID))
|
|
}
|
|
|
|
projectFlockKandang, err := s.ProjectFlockKandangRepo.GetActiveByKandangID(ctx, uint(*warehouse.KandangId))
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return 0, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Kandang %d belum memiliki project flock aktif", *warehouse.KandangId))
|
|
}
|
|
return 0, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil project flock kandang")
|
|
}
|
|
|
|
return uint(projectFlockKandang.Id), nil
|
|
}
|