Add Phase B: Inventory COGS auto-posting to GL on JobUsage transactions

When powder is consumed via a job (JobsController) or scan (InventoryController.LogUsage),
debit the item's CogsAccountId and credit its InventoryAccountId for the cost of the
quantity consumed (using AverageCost if available, else UnitCost). No-op when either
GL account is not configured on the InventoryItem.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 23:39:23 -04:00
parent 7e1676cfd7
commit 0afb474c3e
3 changed files with 26 additions and 3 deletions
@@ -37,6 +37,7 @@ public class JobsController : Controller
private readonly IJobItemAssemblyService _jobItemAssemblyService;
private readonly IHubContext<NotificationHub> _hub;
private readonly IHubContext<ShopHub> _shopHub;
private readonly IAccountBalanceService _accountBalanceService;
public JobsController(
IUnitOfWork unitOfWork,
@@ -52,7 +53,8 @@ public class JobsController : Controller
IPricingCalculationService pricingService,
IJobItemAssemblyService jobItemAssemblyService,
IHubContext<NotificationHub> hub,
IHubContext<ShopHub> shopHub)
IHubContext<ShopHub> shopHub,
IAccountBalanceService accountBalanceService)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
@@ -68,6 +70,7 @@ public class JobsController : Controller
_jobItemAssemblyService = jobItemAssemblyService;
_hub = hub;
_shopHub = shopHub;
_accountBalanceService = accountBalanceService;
}
/// <summary>
@@ -2726,6 +2729,14 @@ public class JobsController : Controller
inventoryItem.QuantityOnHand -= deductNow;
await _unitOfWork.InventoryItems.UpdateAsync(inventoryItem);
// GL: DR COGS, CR Inventory Asset (accrual) — no-op if accounts not configured
if (inventoryItem.CogsAccountId.HasValue && inventoryItem.InventoryAccountId.HasValue)
{
var cost = deductNow * (inventoryItem.AverageCost > 0 ? inventoryItem.AverageCost : inventoryItem.UnitCost);
await _accountBalanceService.DebitAsync(inventoryItem.CogsAccountId, cost);
await _accountBalanceService.CreditAsync(inventoryItem.InventoryAccountId, cost);
}
_logger.LogInformation(
"Deducted {Lbs} lbs (net of pre-logged) of {Item} from inventory for Job {JobNumber}. New quantity: {NewQty}",
deductNow, inventoryItem.Name, job.JobNumber, inventoryItem.QuantityOnHand);