Dev #27
@@ -32,6 +32,9 @@ type PurchaseOrderProcessorImpl struct {
|
||||
categoryRepo CategoryRepository
|
||||
unitRepo UnitRepository
|
||||
fileRepo FileRepository
|
||||
// Kept wired but currently unused: purchase orders are a record of spending
|
||||
// only, so nothing here moves stock or converts units. These stay so that
|
||||
// tying purchases back to inventory is a change in one place.
|
||||
inventoryMovementService InventoryMovementService
|
||||
unitConverterRepo IngredientUnitConverterRepository
|
||||
}
|
||||
@@ -438,73 +441,11 @@ func (p *PurchaseOrderProcessorImpl) UpdatePurchaseOrderStatus(ctx context.Conte
|
||||
|
||||
fmt.Println("status:", po.Status)
|
||||
|
||||
// Check if status is changing to "received" and current status is not "received"
|
||||
if status == "received" && po.Status != "received" {
|
||||
// Get purchase order with items for inventory update
|
||||
poWithItems, err := p.purchaseOrderRepo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get purchase order with items: %w", err)
|
||||
}
|
||||
|
||||
// Update inventory for each item
|
||||
for _, item := range poWithItems.Items {
|
||||
if item.PurchaseCategory != nil && item.PurchaseCategory.Type == entities.PurchaseCategoryTypeExpense {
|
||||
continue
|
||||
}
|
||||
|
||||
if item.IngredientID == nil || item.UnitID == nil || item.Quantity == nil {
|
||||
return nil, fmt.Errorf("purchase order item %s is missing raw material inventory fields", item.ID)
|
||||
}
|
||||
|
||||
// Get ingredient to find its base unit
|
||||
ingredient, err := p.ingredientRepo.GetByID(ctx, *item.IngredientID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get ingredient %s: %w", *item.IngredientID, err)
|
||||
}
|
||||
|
||||
// Convert quantity to ingredient's base unit if needed. An ingredient
|
||||
// without a unit has no base unit to convert into, so the purchased
|
||||
// quantity is taken as-is.
|
||||
quantityToAdd := *item.Quantity
|
||||
if ingredient.UnitID != nil && *item.UnitID != *ingredient.UnitID {
|
||||
// Convert from purchase unit to ingredient's base unit
|
||||
convertedQuantity, err := p.unitConverterRepo.ConvertQuantity(ctx, *item.IngredientID, *item.UnitID, *ingredient.UnitID, organizationID, *item.Quantity)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert quantity for ingredient %s from unit %s to %s: %w", *item.IngredientID, *item.UnitID, *ingredient.UnitID, err)
|
||||
}
|
||||
quantityToAdd = convertedQuantity
|
||||
}
|
||||
|
||||
// Calculate unit cost in ingredient's base unit
|
||||
unitCost := 0.0
|
||||
if quantityToAdd > 0 {
|
||||
unitCost = calculatePurchaseOrderItemTotal(item.Quantity, item.Amount) / quantityToAdd
|
||||
}
|
||||
|
||||
// Create inventory movement for ingredient purchase
|
||||
reason := fmt.Sprintf("Purchase order %s received", po.PONumber)
|
||||
referenceType := entities.InventoryMovementReferenceTypePurchaseOrder
|
||||
referenceID := &id
|
||||
|
||||
err = p.inventoryMovementService.CreateIngredientMovement(
|
||||
ctx,
|
||||
*item.IngredientID,
|
||||
organizationID,
|
||||
outletID,
|
||||
userID,
|
||||
entities.InventoryMovementTypePurchase,
|
||||
quantityToAdd,
|
||||
unitCost,
|
||||
reason,
|
||||
&referenceType,
|
||||
referenceID,
|
||||
&item.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create inventory movement for ingredient %s: %w", *item.IngredientID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// A purchase order is a record of spending only. Receiving one does not move
|
||||
// ingredient stock, does not recalculate ingredient cost, and never converts
|
||||
// units: the quantity and unit on an item are kept exactly as the user
|
||||
// entered them. Raw material items are therefore treated the same way expense
|
||||
// items already were, and the ingredient on an item is just a reference.
|
||||
|
||||
// Update the purchase order status
|
||||
statusOutletID := po.OutletID
|
||||
|
||||
Reference in New Issue
Block a user