Fix issue
This commit is contained in:
parent
b2db56f855
commit
6c19876a47
@ -40,12 +40,12 @@ type UpdatePurchaseOrderRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UpdatePurchaseOrderItemRequest struct {
|
type UpdatePurchaseOrderItemRequest struct {
|
||||||
ID *uuid.UUID `json:"id,omitempty"` // For existing items
|
ID *uuid.UUID `json:"id,omitempty"` // Ignored. Supplying items replaces all existing PO items.
|
||||||
IngredientID *uuid.UUID `json:"ingredient_id,omitempty" validate:"omitempty"`
|
IngredientID *uuid.UUID `json:"ingredient_id" validate:"required"`
|
||||||
PurchaseCategoryID *uuid.UUID `json:"purchase_category_id,omitempty" validate:"omitempty"`
|
PurchaseCategoryID *uuid.UUID `json:"purchase_category_id" validate:"required"`
|
||||||
Description *string `json:"description,omitempty" validate:"omitempty"`
|
Description *string `json:"description,omitempty" validate:"omitempty"`
|
||||||
Quantity *float64 `json:"quantity,omitempty" validate:"omitempty,gt=0"`
|
Quantity *float64 `json:"quantity" validate:"required,gt=0"`
|
||||||
UnitID *uuid.UUID `json:"unit_id,omitempty" validate:"omitempty"`
|
UnitID *uuid.UUID `json:"unit_id" validate:"required"`
|
||||||
Amount *float64 `json:"amount,omitempty" validate:"omitempty,gte=0"`
|
Amount *float64 `json:"amount,omitempty" validate:"omitempty,gte=0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -117,7 +117,7 @@ type UpdatePurchaseOrderRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UpdatePurchaseOrderItemRequest struct {
|
type UpdatePurchaseOrderItemRequest struct {
|
||||||
ID *uuid.UUID `json:"id,omitempty"` // For existing items
|
ID *uuid.UUID `json:"id,omitempty"` // Ignored. Supplying items replaces all existing PO items.
|
||||||
IngredientID *uuid.UUID `json:"ingredient_id,omitempty"`
|
IngredientID *uuid.UUID `json:"ingredient_id,omitempty"`
|
||||||
PurchaseCategoryID *uuid.UUID `json:"purchase_category_id,omitempty"`
|
PurchaseCategoryID *uuid.UUID `json:"purchase_category_id,omitempty"`
|
||||||
Description *string `json:"description,omitempty"`
|
Description *string `json:"description,omitempty"`
|
||||||
|
|||||||
@ -842,10 +842,10 @@ func exclusiveSummarySalaryBreakdown(transactions []entities.ExclusiveSummaryDai
|
|||||||
|
|
||||||
classification := strings.ToLower(transaction.CategoryCode + " " + transaction.CategoryName + " " + transaction.Description)
|
classification := strings.ToLower(transaction.CategoryCode + " " + transaction.CategoryName + " " + transaction.Description)
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(classification, "staff") || strings.Contains(classification, "kary") || strings.Contains(classification, "karyawan"):
|
|
||||||
salaryStaff += transaction.Amount
|
|
||||||
case strings.Contains(classification, "dw"):
|
case strings.Contains(classification, "dw"):
|
||||||
salaryDW += transaction.Amount
|
salaryDW += transaction.Amount
|
||||||
|
case strings.Contains(classification, "staff") || strings.Contains(classification, "kary") || strings.Contains(classification, "karyawan"):
|
||||||
|
salaryStaff += transaction.Amount
|
||||||
default:
|
default:
|
||||||
salaryOther += transaction.Amount
|
salaryOther += transaction.Amount
|
||||||
}
|
}
|
||||||
|
|||||||
@ -293,7 +293,7 @@ func TestAnalyticsProcessorGetExclusiveSummaryPeriodCalculatesSummaryAndReimburs
|
|||||||
},
|
},
|
||||||
DailyTransactions: []entities.ExclusiveSummaryDailyTransaction{
|
DailyTransactions: []entities.ExclusiveSummaryDailyTransaction{
|
||||||
{Date: now, CategoryCode: "biaya_gaji", CategoryName: "Gaji", Description: "gaji kary", Amount: 48203333, Source: "expense"},
|
{Date: now, CategoryCode: "biaya_gaji", CategoryName: "Gaji", Description: "gaji kary", Amount: 48203333, Source: "expense"},
|
||||||
{Date: now, CategoryCode: "biaya_gaji", CategoryName: "Gaji", Description: "DW", Amount: 3555000, Source: "expense"},
|
{Date: now, CategoryCode: "biaya_gaji_dw", CategoryName: "Gaji DW", Description: "gaji karyawan", Amount: 3555000, Source: "expense"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, expenseRepositoryStub{})
|
}, expenseRepositoryStub{})
|
||||||
|
|||||||
@ -173,7 +173,7 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
Joins("JOIN units u ON poi.unit_id = u.id").
|
Joins("JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status = ?", "received").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo)
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo)
|
||||||
summaryQuery = r.applyPurchaseOrderItemOutletFilter(summaryQuery, outletID)
|
summaryQuery = r.applyPurchaseOrderItemOutletFilter(summaryQuery, outletID)
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
Joins("JOIN units u ON poi.unit_id = u.id").
|
Joins("JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status = ?", "received").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
Group(dateFormat).
|
Group(dateFormat).
|
||||||
Order(dateFormat)
|
Order(dateFormat)
|
||||||
@ -245,7 +245,7 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
Joins("LEFT JOIN units u ON poi.unit_id = u.id").
|
Joins("LEFT JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status = ?", "received").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
Group("i.id, i.name").
|
Group("i.id, i.name").
|
||||||
Order("total_cost DESC")
|
Order("total_cost DESC")
|
||||||
@ -273,7 +273,7 @@ func (r *AnalyticsRepositoryImpl) getPurchaseOrderPurchasingAnalytics(ctx contex
|
|||||||
Joins("JOIN units u ON poi.unit_id = u.id").
|
Joins("JOIN units u ON poi.unit_id = u.id").
|
||||||
Where("po.organization_id = ?", organizationID).
|
Where("po.organization_id = ?", organizationID).
|
||||||
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
Where("pc.type = ?", entities.PurchaseCategoryTypeRawMaterial).
|
||||||
Where("po.status != ?", "cancelled").
|
Where("po.status = ?", "received").
|
||||||
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
Where("po.transaction_date >= ? AND po.transaction_date <= ?", dateFrom, dateTo).
|
||||||
Group("v.id, v.name").
|
Group("v.id, v.name").
|
||||||
Order("total_cost DESC")
|
Order("total_cost DESC")
|
||||||
@ -296,7 +296,15 @@ func (r *AnalyticsRepositoryImpl) applyPurchaseOrderItemOutletFilter(query *gorm
|
|||||||
if outletID == nil {
|
if outletID == nil {
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
return query.Where("(i.outlet_id = ? OR u.outlet_id = ?)", *outletID, *outletID)
|
return query.Where(`
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM inventory_movements im
|
||||||
|
WHERE im.purchase_order_item_id = poi.id
|
||||||
|
AND im.movement_type = ?
|
||||||
|
AND im.outlet_id = ?
|
||||||
|
)
|
||||||
|
`, entities.InventoryMovementTypePurchase, *outletID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, limit int) ([]*entities.ProductAnalytics, error) {
|
func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, dateFrom, dateTo time.Time, limit int) ([]*entities.ProductAnalytics, error) {
|
||||||
@ -307,6 +315,7 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
|
|||||||
Select(`
|
Select(`
|
||||||
p.id as product_id,
|
p.id as product_id,
|
||||||
p.name as product_name,
|
p.name as product_name,
|
||||||
|
p.price as product_price,
|
||||||
c.id as category_id,
|
c.id as category_id,
|
||||||
c.name as category_name,
|
c.name as category_name,
|
||||||
c.order as category_order,
|
c.order as category_order,
|
||||||
@ -365,7 +374,7 @@ func (r *AnalyticsRepositoryImpl) GetProductAnalytics(ctx context.Context, organ
|
|||||||
query = r.resolveOutletID(query, outletID, "o.outlet_id")
|
query = r.resolveOutletID(query, outletID, "o.outlet_id")
|
||||||
|
|
||||||
err := query.
|
err := query.
|
||||||
Group("p.id, p.name, p.cost, c.id, c.name, c.order, mahpp.hpp_per_unit").
|
Group("p.id, p.name, p.price, p.cost, c.id, c.name, c.order, mahpp.hpp_per_unit").
|
||||||
Order("revenue DESC").
|
Order("revenue DESC").
|
||||||
Limit(limit).
|
Limit(limit).
|
||||||
Scan(&results).Error
|
Scan(&results).Error
|
||||||
@ -854,8 +863,14 @@ func (r *AnalyticsRepositoryImpl) exclusiveSummaryTransactionUnionQuery(organiza
|
|||||||
}
|
}
|
||||||
|
|
||||||
if outletID != nil {
|
if outletID != nil {
|
||||||
poOutletFilter = "AND (i.outlet_id = ? OR u.outlet_id = ?)"
|
poOutletFilter = `AND EXISTS (
|
||||||
args = append(args, *outletID, *outletID)
|
SELECT 1
|
||||||
|
FROM inventory_movements im
|
||||||
|
WHERE im.purchase_order_item_id = poi.id
|
||||||
|
AND im.movement_type = 'purchase'
|
||||||
|
AND im.outlet_id = ?
|
||||||
|
)`
|
||||||
|
args = append(args, *outletID)
|
||||||
}
|
}
|
||||||
|
|
||||||
args = append(args,
|
args = append(args,
|
||||||
|
|||||||
@ -73,3 +73,31 @@ func TestPurchaseOrderValidatorCreateRejectsDueDateBeforeTransactionDate(t *test
|
|||||||
require.Equal(t, constants.MalformedFieldErrorCode, code)
|
require.Equal(t, constants.MalformedFieldErrorCode, code)
|
||||||
require.Contains(t, err.Error(), "due_date must be after transaction_date")
|
require.Contains(t, err.Error(), "due_date must be after transaction_date")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPurchaseOrderValidatorUpdateItemsRequireFullReplacementFields(t *testing.T) {
|
||||||
|
validator := NewPurchaseOrderValidator()
|
||||||
|
req := &contract.UpdatePurchaseOrderRequest{
|
||||||
|
Items: []contract.UpdatePurchaseOrderItemRequest{
|
||||||
|
{
|
||||||
|
PurchaseCategoryID: ptrUUID(uuid.New()),
|
||||||
|
Quantity: ptrFloat64(1),
|
||||||
|
UnitID: ptrUUID(uuid.New()),
|
||||||
|
Amount: ptrFloat64(1000),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err, code := validator.ValidateUpdatePurchaseOrderRequest(req)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, constants.MissingFieldErrorCode, code)
|
||||||
|
require.Contains(t, err.Error(), "ingredient_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ptrUUID(id uuid.UUID) *uuid.UUID {
|
||||||
|
return &id
|
||||||
|
}
|
||||||
|
|
||||||
|
func ptrFloat64(value float64) *float64 {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ DROP TRIGGER IF EXISTS trigger_validate_purchase_order_item_raw_material ON purc
|
|||||||
DROP FUNCTION IF EXISTS validate_purchase_order_item_raw_material();
|
DROP FUNCTION IF EXISTS validate_purchase_order_item_raw_material();
|
||||||
|
|
||||||
ALTER TABLE purchase_order_items
|
ALTER TABLE purchase_order_items
|
||||||
|
ALTER COLUMN purchase_category_id DROP NOT NULL,
|
||||||
ALTER COLUMN ingredient_id DROP NOT NULL,
|
ALTER COLUMN ingredient_id DROP NOT NULL,
|
||||||
ALTER COLUMN quantity DROP NOT NULL,
|
ALTER COLUMN quantity DROP NOT NULL,
|
||||||
ALTER COLUMN unit_id DROP NOT NULL;
|
ALTER COLUMN unit_id DROP NOT NULL;
|
||||||
|
|||||||
@ -1,10 +1,21 @@
|
|||||||
|
UPDATE purchase_order_items poi
|
||||||
|
SET purchase_category_id = pc.id
|
||||||
|
FROM purchase_orders po
|
||||||
|
JOIN purchase_categories pc ON pc.organization_id = po.organization_id
|
||||||
|
AND pc.code = 'bahan_baku'
|
||||||
|
AND pc.type = 'raw_material'
|
||||||
|
WHERE poi.purchase_order_id = po.id
|
||||||
|
AND poi.purchase_category_id IS NULL;
|
||||||
|
|
||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF EXISTS (
|
IF EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM purchase_order_items poi
|
FROM purchase_order_items poi
|
||||||
JOIN purchase_categories pc ON pc.id = poi.purchase_category_id
|
LEFT JOIN purchase_categories pc ON pc.id = poi.purchase_category_id
|
||||||
WHERE pc.type <> 'raw_material'
|
WHERE poi.purchase_category_id IS NULL
|
||||||
|
OR pc.id IS NULL
|
||||||
|
OR pc.type <> 'raw_material'
|
||||||
OR poi.ingredient_id IS NULL
|
OR poi.ingredient_id IS NULL
|
||||||
OR poi.quantity IS NULL
|
OR poi.quantity IS NULL
|
||||||
OR poi.unit_id IS NULL
|
OR poi.unit_id IS NULL
|
||||||
@ -14,6 +25,7 @@ BEGIN
|
|||||||
END $$;
|
END $$;
|
||||||
|
|
||||||
ALTER TABLE purchase_order_items
|
ALTER TABLE purchase_order_items
|
||||||
|
ALTER COLUMN purchase_category_id SET NOT NULL,
|
||||||
ALTER COLUMN ingredient_id SET NOT NULL,
|
ALTER COLUMN ingredient_id SET NOT NULL,
|
||||||
ALTER COLUMN quantity SET NOT NULL,
|
ALTER COLUMN quantity SET NOT NULL,
|
||||||
ALTER COLUMN unit_id SET NOT NULL;
|
ALTER COLUMN unit_id SET NOT NULL;
|
||||||
|
|||||||
@ -1,3 +1,20 @@
|
|||||||
|
UPDATE expense_items ei
|
||||||
|
SET purchase_category_id = pc.id
|
||||||
|
FROM expenses e
|
||||||
|
JOIN purchase_categories pc ON pc.organization_id = e.organization_id
|
||||||
|
AND pc.code = 'biaya_lain_lain'
|
||||||
|
AND pc.type = 'expense'
|
||||||
|
WHERE ei.expense_id = e.id
|
||||||
|
AND (
|
||||||
|
ei.purchase_category_id IS NULL
|
||||||
|
OR NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM purchase_categories current_pc
|
||||||
|
WHERE current_pc.id = ei.purchase_category_id
|
||||||
|
AND current_pc.type = 'expense'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF EXISTS (
|
IF EXISTS (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user