mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 15:25:43 +00:00
Merge branch 'development' of https://gitlab.com/mbugroup/lti-api into fix/BE/Purchase-edit-qty
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
t text;
|
||||||
|
seq_name text;
|
||||||
|
BEGIN
|
||||||
|
FOREACH t IN ARRAY ARRAY[
|
||||||
|
'daily_checklist_activity_task_assignments',
|
||||||
|
'daily_checklist_activity_tasks',
|
||||||
|
'daily_checklist_phases',
|
||||||
|
'daily_checklist_tasks',
|
||||||
|
'daily_checklists',
|
||||||
|
'employee_kandangs',
|
||||||
|
'employees',
|
||||||
|
'phase_activities',
|
||||||
|
'phases'
|
||||||
|
]
|
||||||
|
LOOP
|
||||||
|
-- Sequence name convention
|
||||||
|
seq_name := format('public.%I_id_seq', t);
|
||||||
|
|
||||||
|
-- 1) Drop default nextval (bigserial behavior)
|
||||||
|
EXECUTE format(
|
||||||
|
'ALTER TABLE public.%I ALTER COLUMN id DROP DEFAULT',
|
||||||
|
t
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 2) Add IDENTITY back (BY DEFAULT is safer for rollback)
|
||||||
|
EXECUTE format(
|
||||||
|
'ALTER TABLE public.%I ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY',
|
||||||
|
t
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 3) Detach & optionally drop sequence (safe)
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1 FROM pg_class
|
||||||
|
WHERE relkind = 'S'
|
||||||
|
AND relname = t || '_id_seq'
|
||||||
|
) THEN
|
||||||
|
EXECUTE format(
|
||||||
|
'ALTER SEQUENCE %s OWNED BY NONE',
|
||||||
|
seq_name
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Optional: drop sequence (comment if you want to keep it)
|
||||||
|
EXECUTE format(
|
||||||
|
'DROP SEQUENCE IF EXISTS %s',
|
||||||
|
seq_name
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
t text;
|
||||||
|
seq_name text;
|
||||||
|
max_id bigint;
|
||||||
|
BEGIN
|
||||||
|
FOREACH t IN ARRAY ARRAY[
|
||||||
|
'daily_checklist_activity_task_assignments',
|
||||||
|
'daily_checklist_activity_tasks',
|
||||||
|
'daily_checklist_phases',
|
||||||
|
'daily_checklist_tasks',
|
||||||
|
'daily_checklists',
|
||||||
|
'employee_kandangs',
|
||||||
|
'employees',
|
||||||
|
'phase_activities',
|
||||||
|
'phases'
|
||||||
|
]
|
||||||
|
LOOP
|
||||||
|
-- Sequence name convention: public.<table>_id_seq
|
||||||
|
seq_name := format('public.%I_id_seq', t);
|
||||||
|
|
||||||
|
-- Drop IDENTITY only if the column is identity (safe to re-run)
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'public'
|
||||||
|
AND table_name = t
|
||||||
|
AND column_name = 'id'
|
||||||
|
AND is_identity = 'YES'
|
||||||
|
) THEN
|
||||||
|
EXECUTE format('ALTER TABLE public.%I ALTER COLUMN id DROP IDENTITY', t);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Ensure sequence exists
|
||||||
|
EXECUTE format('CREATE SEQUENCE IF NOT EXISTS %s', seq_name);
|
||||||
|
|
||||||
|
-- Set default like bigserial
|
||||||
|
EXECUTE format(
|
||||||
|
'ALTER TABLE public.%I ALTER COLUMN id SET DEFAULT nextval(''%s'')',
|
||||||
|
t, seq_name
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Own the sequence by the column
|
||||||
|
EXECUTE format(
|
||||||
|
'ALTER SEQUENCE %s OWNED BY public.%I.id',
|
||||||
|
seq_name, t
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Sync sequence to MAX(id) + 1 to avoid duplicate key
|
||||||
|
EXECUTE format('SELECT COALESCE(MAX(id), 0) FROM public.%I', t) INTO max_id;
|
||||||
|
|
||||||
|
EXECUTE format('SELECT setval(''%s'', $1, false)', seq_name)
|
||||||
|
USING (max_id + 1);
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -6,7 +6,7 @@ import "time"
|
|||||||
type StockTransferDelivery struct {
|
type StockTransferDelivery struct {
|
||||||
Id uint64 `gorm:"primaryKey;autoIncrement"`
|
Id uint64 `gorm:"primaryKey;autoIncrement"`
|
||||||
StockTransferId uint64
|
StockTransferId uint64
|
||||||
SupplierId uint64
|
SupplierId *uint64
|
||||||
VehiclePlate string
|
VehiclePlate string
|
||||||
DriverName string
|
DriverName string
|
||||||
DocumentNumber string
|
DocumentNumber string
|
||||||
|
|||||||
@@ -355,9 +355,10 @@ func (r *ClosingRepositoryImpl) SumMarketingWeightAndQtyByProjectFlockKandangIDs
|
|||||||
Joins("JOIN product_warehouses pw ON pw.id = mp.product_warehouse_id").
|
Joins("JOIN product_warehouses pw ON pw.id = mp.product_warehouse_id").
|
||||||
Joins("JOIN products prod ON prod.id = pw.product_id").
|
Joins("JOIN products prod ON prod.id = pw.product_id").
|
||||||
Joins("JOIN flags f ON f.flagable_id = prod.id AND f.flagable_type = ?", "products").
|
Joins("JOIN flags f ON f.flagable_id = prod.id AND f.flagable_type = ?", "products").
|
||||||
|
Joins("JOIN marketing_delivery_products mdp ON mdp.marketing_product_id = mp.id").
|
||||||
Where("pw.project_flock_kandang_id IN ?", projectFlockKandangIDs).
|
Where("pw.project_flock_kandang_id IN ?", projectFlockKandangIDs).
|
||||||
Where("f.name IN ?", flagNames).
|
Where("f.name IN ?", flagNames).
|
||||||
Select("COALESCE(SUM(mp.total_weight), 0) AS total_weight, COALESCE(SUM(mp.qty), 0) AS total_qty, COALESCE(SUM(mp.total_price), 0) AS total_price").
|
Select("COALESCE(SUM(mdp.total_weight), 0) AS total_weight, COALESCE(SUM(mdp.usage_qty), 0) AS total_qty, COALESCE(SUM(mdp.total_price), 0) AS total_price").
|
||||||
Scan(&agg).Error
|
Scan(&agg).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, err
|
return 0, 0, 0, err
|
||||||
@@ -797,7 +798,7 @@ func (r *ClosingRepositoryImpl) detailQuery(
|
|||||||
) *gorm.DB {
|
) *gorm.DB {
|
||||||
db := r.withCtx(ctx).
|
db := r.withCtx(ctx).
|
||||||
Table(table).
|
Table(table).
|
||||||
Joins("JOIN product_warehouses pw ON "+pwJoinCond).
|
Joins("JOIN product_warehouses pw ON " + pwJoinCond).
|
||||||
Joins("JOIN products p ON p.id = pw.product_id")
|
Joins("JOIN products p ON p.id = pw.product_id")
|
||||||
|
|
||||||
db = applyJoins(db, joins...)
|
db = applyJoins(db, joins...)
|
||||||
@@ -1034,7 +1035,7 @@ func (r *ClosingRepositoryImpl) fetchStockLogs(ctx context.Context, kandangID ui
|
|||||||
COALESCE(sl.increase,0) AS increase,
|
COALESCE(sl.increase,0) AS increase,
|
||||||
COALESCE(sl.decrease,0) AS decrease,
|
COALESCE(sl.decrease,0) AS decrease,
|
||||||
COALESCE(p.product_price,0) AS price,
|
COALESCE(p.product_price,0) AS price,
|
||||||
`+movementSelect+`
|
` + movementSelect + `
|
||||||
`).
|
`).
|
||||||
Joins("JOIN product_warehouses pw ON pw.id = sl.product_warehouse_id").
|
Joins("JOIN product_warehouses pw ON pw.id = sl.product_warehouse_id").
|
||||||
Joins("JOIN products p ON p.id = pw.product_id").
|
Joins("JOIN products p ON p.id = pw.product_id").
|
||||||
|
|||||||
@@ -162,12 +162,7 @@ func (s closingService) GetProjectFlockByID(c *fiber.Ctx, id uint) (*entity.Proj
|
|||||||
|
|
||||||
func (s closingService) GetPenjualan(c *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) ([]entity.MarketingDeliveryProduct, error) {
|
func (s closingService) GetPenjualan(c *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) ([]entity.MarketingDeliveryProduct, error) {
|
||||||
|
|
||||||
projectFlock, err := s.ProjectFlockRepo.GetByID(c.Context(), projectFlockID, nil)
|
realisasi, err := s.MarketingDeliveryProductRepo.GetClosingPenjualan(c.Context(), projectFlockID, projectFlockKandangID)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
realisasi, err := s.MarketingDeliveryProductRepo.GetClosingPenjualan(c.Context(), projectFlockID, projectFlockKandangID, projectFlock.Category)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,9 +270,9 @@ func (s closingKeuanganService) calculateProductionData(c *fiber.Ctx, projectFlo
|
|||||||
|
|
||||||
var deliveryProducts []entity.MarketingDeliveryProduct
|
var deliveryProducts []entity.MarketingDeliveryProduct
|
||||||
if projectFlockKandangID != nil {
|
if projectFlockKandangID != nil {
|
||||||
deliveryProducts, err = s.MarketingDeliveryProductRepo.GetClosingPenjualan(c.Context(), projectFlock.Id, projectFlockKandangID, projectFlock.Category)
|
deliveryProducts, err = s.MarketingDeliveryProductRepo.GetClosingPenjualanByCategory(c.Context(), projectFlock.Id, projectFlockKandangID, projectFlock.Category)
|
||||||
} else {
|
} else {
|
||||||
deliveryProducts, err = s.MarketingDeliveryProductRepo.GetClosingPenjualan(c.Context(), projectFlock.Id, nil, projectFlock.Category)
|
deliveryProducts, err = s.MarketingDeliveryProductRepo.GetClosingPenjualanByCategory(c.Context(), projectFlock.Id, nil, projectFlock.Category)
|
||||||
}
|
}
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data penjualan")
|
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data penjualan")
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type Query struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AssignPhases struct {
|
type AssignPhases struct {
|
||||||
PhaseIDs string `json:"phase_ids" validate:"required"`
|
PhaseIDs string `json:"phase_ids" validate:"omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssignTask struct {
|
type AssignTask struct {
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TransferRelationDTO struct {
|
type TransferRelationDTO struct {
|
||||||
Id uint64 `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
MovementNumber string `json:"movement_number"`
|
MovementNumber string `json:"movement_number"`
|
||||||
TransferReason string `json:"transfer_reason"`
|
TransferReason string `json:"transfer_reason"`
|
||||||
TransferDate string `json:"transfer_date"`
|
TransferDate string `json:"transfer_date"`
|
||||||
SourceWarehouse *warehouseDTO.WarehouseRelationDTO `json:"source_warehouse,omitempty"`
|
SourceWarehouse *warehouseDTO.WarehouseRelationDTO `json:"source_warehouse,omitempty"`
|
||||||
DestinationWarehouse *warehouseDTO.WarehouseRelationDTO `json:"destination_warehouse,omitempty"`
|
DestinationWarehouse *warehouseDTO.WarehouseRelationDTO `json:"destination_warehouse,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductSimpleDTO struct {
|
type ProductSimpleDTO struct {
|
||||||
@@ -51,16 +51,16 @@ type TransferDetailDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TransferDetailItemDTO struct {
|
type TransferDetailItemDTO struct {
|
||||||
Id uint64 `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
Product ProductSimpleDTO `json:"product"`
|
Product ProductSimpleDTO `json:"product"`
|
||||||
Quantity float64 `json:"quantity"`
|
Quantity float64 `json:"quantity"`
|
||||||
TransportPerItem *float64 `json:"transport_per_item,omitempty"` // Biaya ekspedisi per item
|
TransportPerItem *float64 `json:"transport_per_item,omitempty"` // Biaya ekspedisi per item
|
||||||
ExpeditionVendor *SupplierSimpleDTO `json:"expedition_vendor,omitempty"` // Vendor ekspedisi
|
ExpeditionVendor *SupplierSimpleDTO `json:"expedition_vendor,omitempty"` // Vendor ekspedisi
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransferDeliveryDTO struct {
|
type TransferDeliveryDTO struct {
|
||||||
Id uint64 `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
Supplier SupplierSimpleDTO `json:"supplier"`
|
Supplier *SupplierSimpleDTO `json:"supplier,omitempty"`
|
||||||
VehiclePlate string `json:"vehicle_plate"`
|
VehiclePlate string `json:"vehicle_plate"`
|
||||||
DriverName string `json:"driver_name"`
|
DriverName string `json:"driver_name"`
|
||||||
DocumentNumber string `json:"document_number"`
|
DocumentNumber string `json:"document_number"`
|
||||||
@@ -115,7 +115,6 @@ func ToTransferListDTO(e entity.StockTransfer) TransferListDTO {
|
|||||||
Quantity: d.UsageQty + d.PendingQty, // Total actual quantity allocated
|
Quantity: d.UsageQty + d.PendingQty, // Total actual quantity allocated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if d.ExpenseNonstock != nil {
|
if d.ExpenseNonstock != nil {
|
||||||
priceCopy := d.ExpenseNonstock.Price
|
priceCopy := d.ExpenseNonstock.Price
|
||||||
detailDTO.TransportPerItem = &priceCopy
|
detailDTO.TransportPerItem = &priceCopy
|
||||||
@@ -155,12 +154,17 @@ func ToTransferListDTO(e entity.StockTransfer) TransferListDTO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deliveries = append(deliveries, TransferDeliveryDTO{
|
var supplier *SupplierSimpleDTO
|
||||||
Id: del.Id,
|
if del.Supplier != nil {
|
||||||
Supplier: SupplierSimpleDTO{
|
supplier = &SupplierSimpleDTO{
|
||||||
Id: del.Supplier.Id,
|
Id: del.Supplier.Id,
|
||||||
Name: del.Supplier.Name,
|
Name: del.Supplier.Name,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deliveries = append(deliveries, TransferDeliveryDTO{
|
||||||
|
Id: del.Id,
|
||||||
|
Supplier: supplier,
|
||||||
VehiclePlate: del.VehiclePlate,
|
VehiclePlate: del.VehiclePlate,
|
||||||
DriverName: del.DriverName,
|
DriverName: del.DriverName,
|
||||||
DocumentNumber: del.DocumentNumber,
|
DocumentNumber: del.DocumentNumber,
|
||||||
@@ -201,7 +205,6 @@ func ToTransferDetailDTO(e entity.StockTransfer) TransferDetailDTO {
|
|||||||
Quantity: d.UsageQty + d.PendingQty, // Total actual quantity allocated
|
Quantity: d.UsageQty + d.PendingQty, // Total actual quantity allocated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if d.ExpenseNonstock != nil {
|
if d.ExpenseNonstock != nil {
|
||||||
priceCopy := d.ExpenseNonstock.Price
|
priceCopy := d.ExpenseNonstock.Price
|
||||||
detailDTO.TransportPerItem = &priceCopy
|
detailDTO.TransportPerItem = &priceCopy
|
||||||
@@ -241,12 +244,17 @@ func ToTransferDetailDTO(e entity.StockTransfer) TransferDetailDTO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deliveries = append(deliveries, TransferDeliveryDTO{
|
var supplier *SupplierSimpleDTO
|
||||||
Id: del.Id,
|
if del.Supplier != nil {
|
||||||
Supplier: SupplierSimpleDTO{
|
supplier = &SupplierSimpleDTO{
|
||||||
Id: del.Supplier.Id,
|
Id: del.Supplier.Id,
|
||||||
Name: del.Supplier.Name,
|
Name: del.Supplier.Name,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deliveries = append(deliveries, TransferDeliveryDTO{
|
||||||
|
Id: del.Id,
|
||||||
|
Supplier: supplier,
|
||||||
VehiclePlate: del.VehiclePlate,
|
VehiclePlate: del.VehiclePlate,
|
||||||
DriverName: del.DriverName,
|
DriverName: del.DriverName,
|
||||||
DocumentNumber: del.DocumentNumber,
|
DocumentNumber: del.DocumentNumber,
|
||||||
|
|||||||
@@ -196,6 +196,11 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, delivery := range req.Deliveries {
|
for _, delivery := range req.Deliveries {
|
||||||
|
// Skip supplier validation if SupplierID is 0 (optional)
|
||||||
|
if delivery.SupplierID == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
supplier, err := s.SupplierRepo.GetByID(c.Context(), uint(delivery.SupplierID), nil)
|
supplier, err := s.SupplierRepo.GetByID(c.Context(), uint(delivery.SupplierID), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -310,9 +315,16 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
|
|
||||||
var deliveries []*entity.StockTransferDelivery
|
var deliveries []*entity.StockTransferDelivery
|
||||||
for _, delivery := range req.Deliveries {
|
for _, delivery := range req.Deliveries {
|
||||||
|
supplierId := func() *uint64 {
|
||||||
|
if delivery.SupplierID > 0 {
|
||||||
|
id := uint64(delivery.SupplierID)
|
||||||
|
return &id
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}()
|
||||||
deliveries = append(deliveries, &entity.StockTransferDelivery{
|
deliveries = append(deliveries, &entity.StockTransferDelivery{
|
||||||
StockTransferId: entityTransfer.Id,
|
StockTransferId: entityTransfer.Id,
|
||||||
SupplierId: uint64(delivery.SupplierID),
|
SupplierId: supplierId,
|
||||||
VehiclePlate: delivery.VehiclePlate,
|
VehiclePlate: delivery.VehiclePlate,
|
||||||
DriverName: delivery.DriverName,
|
DriverName: delivery.DriverName,
|
||||||
ShippingCostItem: delivery.DeliveryCostPerItem,
|
ShippingCostItem: delivery.DeliveryCostPerItem,
|
||||||
@@ -458,6 +470,11 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
|
|
||||||
if len(req.Deliveries) > 0 {
|
if len(req.Deliveries) > 0 {
|
||||||
for _, delivery := range req.Deliveries {
|
for _, delivery := range req.Deliveries {
|
||||||
|
// Skip adding to expensePayloads if SupplierID is 0 (optional)
|
||||||
|
if delivery.SupplierID == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, prod := range delivery.Products {
|
for _, prod := range delivery.Products {
|
||||||
detail := detailMap[uint64(prod.ProductID)]
|
detail := detailMap[uint64(prod.ProductID)]
|
||||||
if detail == nil {
|
if detail == nil {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type TransferDelivery struct {
|
|||||||
DocumentIndex int `json:"document_index" validate:"omitempty,min=-1" default:"-1"`
|
DocumentIndex int `json:"document_index" validate:"omitempty,min=-1" default:"-1"`
|
||||||
DriverName string `json:"driver_name" validate:"required"`
|
DriverName string `json:"driver_name" validate:"required"`
|
||||||
VehiclePlate string `json:"vehicle_plate" validate:"required"`
|
VehiclePlate string `json:"vehicle_plate" validate:"required"`
|
||||||
SupplierID uint `json:"supplier_id" validate:"required"`
|
SupplierID uint `json:"supplier_id" `
|
||||||
Products []TransferDeliveryProduct `json:"products" validate:"required,dive"`
|
Products []TransferDeliveryProduct `json:"products" validate:"required,dive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import (
|
|||||||
type MarketingDeliveryProductRepository interface {
|
type MarketingDeliveryProductRepository interface {
|
||||||
repository.BaseRepository[entity.MarketingDeliveryProduct]
|
repository.BaseRepository[entity.MarketingDeliveryProduct]
|
||||||
GetDeliveryProductsByProjectFlockID(ctx context.Context, projectFlockID uint, callback func(*gorm.DB) *gorm.DB) ([]entity.MarketingDeliveryProduct, error)
|
GetDeliveryProductsByProjectFlockID(ctx context.Context, projectFlockID uint, callback func(*gorm.DB) *gorm.DB) ([]entity.MarketingDeliveryProduct, error)
|
||||||
GetClosingPenjualan(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint, category string) ([]entity.MarketingDeliveryProduct, error)
|
GetClosingPenjualan(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]entity.MarketingDeliveryProduct, error)
|
||||||
|
GetClosingPenjualanByCategory(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint, category string) ([]entity.MarketingDeliveryProduct, error)
|
||||||
GetByMarketingId(ctx context.Context, marketingId uint) ([]entity.MarketingDeliveryProduct, error)
|
GetByMarketingId(ctx context.Context, marketingId uint) ([]entity.MarketingDeliveryProduct, error)
|
||||||
GetByMarketingProductID(ctx context.Context, marketingProductID uint) (*entity.MarketingDeliveryProduct, error)
|
GetByMarketingProductID(ctx context.Context, marketingProductID uint) (*entity.MarketingDeliveryProduct, error)
|
||||||
GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.MarketingQuery) ([]entity.MarketingDeliveryProduct, int64, error)
|
GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.MarketingQuery) ([]entity.MarketingDeliveryProduct, int64, error)
|
||||||
@@ -54,7 +55,45 @@ func (r *MarketingDeliveryProductRepositoryImpl) GetDeliveryProductsByProjectFlo
|
|||||||
return deliveryProducts, nil
|
return deliveryProducts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *MarketingDeliveryProductRepositoryImpl) GetClosingPenjualan(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint, category string) ([]entity.MarketingDeliveryProduct, error) {
|
func (r *MarketingDeliveryProductRepositoryImpl) GetClosingPenjualan(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]entity.MarketingDeliveryProduct, error) {
|
||||||
|
var deliveryProducts []entity.MarketingDeliveryProduct
|
||||||
|
|
||||||
|
db := r.DB().WithContext(ctx).
|
||||||
|
Joins("JOIN marketing_products ON marketing_products.id = marketing_delivery_products.marketing_product_id").
|
||||||
|
Joins("JOIN product_warehouses ON product_warehouses.id = marketing_products.product_warehouse_id").
|
||||||
|
Joins("JOIN products ON products.id = product_warehouses.product_id").
|
||||||
|
Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = product_warehouses.project_flock_kandang_id").
|
||||||
|
Where("project_flock_kandangs.project_flock_id = ?", projectFlockID).
|
||||||
|
Where("marketing_delivery_products.delivery_date IS NOT NULL").
|
||||||
|
Distinct("marketing_delivery_products.*")
|
||||||
|
|
||||||
|
if projectFlockKandangID != nil {
|
||||||
|
db = db.Where("product_warehouses.project_flock_kandang_id = ?", *projectFlockKandangID)
|
||||||
|
}
|
||||||
|
|
||||||
|
db = db.
|
||||||
|
Preload("MarketingProduct").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.Product").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.Product.ProductCategory").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.Product.Uom").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.Product.Flags").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.Warehouse").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang.Kandang").
|
||||||
|
Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang.Chickins").
|
||||||
|
Preload("MarketingProduct.Marketing").
|
||||||
|
Preload("MarketingProduct.Marketing.Customer").
|
||||||
|
Order("marketing_delivery_products.delivery_date DESC")
|
||||||
|
|
||||||
|
if err := db.Find(&deliveryProducts).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return deliveryProducts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MarketingDeliveryProductRepositoryImpl) GetClosingPenjualanByCategory(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint, category string) ([]entity.MarketingDeliveryProduct, error) {
|
||||||
var deliveryProducts []entity.MarketingDeliveryProduct
|
var deliveryProducts []entity.MarketingDeliveryProduct
|
||||||
|
|
||||||
db := r.DB().WithContext(ctx).
|
db := r.DB().WithContext(ctx).
|
||||||
|
|||||||
@@ -650,9 +650,9 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
|
|||||||
repoTx := s.Repository.WithTx(dbTransaction)
|
repoTx := s.Repository.WithTx(dbTransaction)
|
||||||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||||
|
|
||||||
// Gunakan repo baru untuk transaction scope agar bisa akses method custom
|
|
||||||
sourceRepoTx := repository.NewLayingTransferSourceRepository(dbTransaction)
|
sourceRepoTx := repository.NewLayingTransferSourceRepository(dbTransaction)
|
||||||
targetRepoTx := repository.NewLayingTransferTargetRepository(dbTransaction)
|
targetRepoTx := repository.NewLayingTransferTargetRepository(dbTransaction)
|
||||||
|
stockLogRepoTx := rStockLogs.NewStockLogRepository(dbTransaction)
|
||||||
|
|
||||||
for _, approvableID := range approvableIDs {
|
for _, approvableID := range approvableIDs {
|
||||||
transfer, err := repoTx.GetByID(c.Context(), approvableID, nil)
|
transfer, err := repoTx.GetByID(c.Context(), approvableID, nil)
|
||||||
@@ -687,23 +687,28 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
|
|||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil targets transfer")
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil targets transfer")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hitung total quantity dari targets untuk di-consume dari sources
|
|
||||||
totalTargetQty := 0.0
|
totalTargetQty := 0.0
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
totalTargetQty += target.TotalQty
|
totalTargetQty += target.TotalQty
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consume dari laying_transfer_sources (Usable) - akan consume dari ProjectFlockPopulation (Stockable)
|
totalSourceRequested := 0.0
|
||||||
|
for _, source := range sources {
|
||||||
|
totalSourceRequested += source.RequestedQty
|
||||||
|
}
|
||||||
|
|
||||||
for _, source := range sources {
|
for _, source := range sources {
|
||||||
if source.ProductWarehouseId == nil {
|
if source.ProductWarehouseId == nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Source product warehouse tidak ditemukan untuk transfer %d", approvableID))
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Source product warehouse tidak ditemukan untuk transfer %d", approvableID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceShare := (source.RequestedQty / totalSourceRequested) * totalTargetQty
|
||||||
|
|
||||||
consumeResult, err := s.FifoSvc.Consume(c.Context(), commonSvc.StockConsumeRequest{
|
consumeResult, err := s.FifoSvc.Consume(c.Context(), commonSvc.StockConsumeRequest{
|
||||||
UsableKey: fifo.UsableKeyTransferToLayingOut,
|
UsableKey: fifo.UsableKeyTransferToLayingOut,
|
||||||
UsableID: source.Id,
|
UsableID: source.Id,
|
||||||
ProductWarehouseID: *source.ProductWarehouseId,
|
ProductWarehouseID: *source.ProductWarehouseId,
|
||||||
Quantity: totalTargetQty,
|
Quantity: sourceShare,
|
||||||
AllowPending: false,
|
AllowPending: false,
|
||||||
Tx: dbTransaction,
|
Tx: dbTransaction,
|
||||||
})
|
})
|
||||||
@@ -717,6 +722,19 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
|
|||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal update source usage qty")
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal update source usage qty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stockLogDecrease := &entity.StockLog{
|
||||||
|
ProductWarehouseId: *source.ProductWarehouseId,
|
||||||
|
CreatedBy: actorID,
|
||||||
|
Increase: 0,
|
||||||
|
Decrease: sourceShare,
|
||||||
|
LoggableType: string(utils.StockLogTypeTransferLaying),
|
||||||
|
LoggableId: approvableID,
|
||||||
|
Notes: fmt.Sprintf("TL #%s", transfer.TransferNumber),
|
||||||
|
}
|
||||||
|
if err := stockLogRepoTx.CreateOne(c.Context(), stockLogDecrease, nil); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal membuat log stok keluar")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, target := range targets {
|
for _, target := range targets {
|
||||||
@@ -725,7 +743,7 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
note := fmt.Sprintf("Transfer to Laying #%s", transfer.TransferNumber)
|
note := fmt.Sprintf("Transfer to Laying #%s", transfer.TransferNumber)
|
||||||
replenishResult, err := s.FifoSvc.Replenish(c.Context(), commonSvc.StockReplenishRequest{
|
_, err := s.FifoSvc.Replenish(c.Context(), commonSvc.StockReplenishRequest{
|
||||||
StockableKey: fifo.StockableKeyTransferToLayingIn,
|
StockableKey: fifo.StockableKeyTransferToLayingIn,
|
||||||
StockableID: target.Id,
|
StockableID: target.Id,
|
||||||
ProductWarehouseID: *target.ProductWarehouseId,
|
ProductWarehouseID: *target.ProductWarehouseId,
|
||||||
@@ -738,10 +756,23 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := targetRepoTx.PatchOne(c.Context(), target.Id, map[string]interface{}{
|
if err := targetRepoTx.PatchOne(c.Context(), target.Id, map[string]interface{}{
|
||||||
"total_qty": replenishResult.AddedQuantity,
|
"total_qty": target.TotalQty,
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal update target total qty")
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal update target total qty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stockLogIncrease := &entity.StockLog{
|
||||||
|
ProductWarehouseId: *target.ProductWarehouseId,
|
||||||
|
CreatedBy: actorID,
|
||||||
|
Increase: target.TotalQty,
|
||||||
|
Decrease: 0,
|
||||||
|
LoggableType: string(utils.StockLogTypeTransferLaying),
|
||||||
|
LoggableId: approvableID,
|
||||||
|
Notes: fmt.Sprintf("TL #%s", transfer.TransferNumber),
|
||||||
|
}
|
||||||
|
if err := stockLogRepoTx.CreateOne(c.Context(), stockLogIncrease, nil); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal membuat log stok masuk")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ type Update struct {
|
|||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
Page int `query:"page" validate:"omitempty,number,min=1,gt=0"`
|
Page int `query:"page" validate:"omitempty,number,min=1,gt=0"`
|
||||||
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"`
|
Limit int `query:"limit" validate:"omitempty,number,min=1,gt=0"`
|
||||||
Search string `query:"search" validate:"omitempty"`
|
Search string `query:"search" validate:"omitempty"`
|
||||||
StartDate string `query:"start_date" validate:"omitempty"`
|
StartDate string `query:"start_date" validate:"omitempty"`
|
||||||
EndDate string `query:"end_date" validate:"omitempty"`
|
EndDate string `query:"end_date" validate:"omitempty"`
|
||||||
|
|||||||
@@ -109,12 +109,13 @@ const (
|
|||||||
type StockLogType string
|
type StockLogType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StockLogTypeAdjustment StockLogType = "ADJUSTMENT"
|
StockLogTypeAdjustment StockLogType = "ADJUSTMENT"
|
||||||
StockLogTypeTransfer StockLogType = "TRANSFER"
|
StockLogTypeTransfer StockLogType = "TRANSFER"
|
||||||
StockLogTypeMarketing StockLogType = "MARKETING"
|
StockLogTypeTransferLaying StockLogType = "TRANSFER_LAYING"
|
||||||
StockLogTypeChikin StockLogType = "CHICKIN"
|
StockLogTypeMarketing StockLogType = "MARKETING"
|
||||||
StockLogTypePurchase StockLogType = "PURCHASE"
|
StockLogTypeChikin StockLogType = "CHICKIN"
|
||||||
StockLogTypeRecording StockLogType = "RECORDING"
|
StockLogTypePurchase StockLogType = "PURCHASE"
|
||||||
|
StockLogTypeRecording StockLogType = "RECORDING"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user