using CMSMicroservice.Protobuf.Protos.Inventory; using CMSMicroservice.WebApi.Common.Services; using CMSMicroservice.Application.WarehouseCQ.Commands.CreateWarehouse; using CMSMicroservice.Application.WarehouseCQ.Commands.UpdateWarehouse; using CMSMicroservice.Application.WarehouseCQ.Commands.DeleteWarehouse; using CMSMicroservice.Application.WarehouseCQ.Commands.SetDefaultWarehouse; using CMSMicroservice.Application.WarehouseCQ.Queries.GetWarehouse; using CMSMicroservice.Application.WarehouseCQ.Queries.GetAllWarehouses; using CMSMicroservice.Application.InventoryItemCQ.Commands.UpdateInventoryItem; using CMSMicroservice.Application.InventoryItemCQ.Commands.IncreaseInventory; using CMSMicroservice.Application.InventoryItemCQ.Commands.ReduceInventory; using CMSMicroservice.Application.InventoryItemCQ.Commands.ReserveInventory; using CMSMicroservice.Application.InventoryItemCQ.Commands.ReleaseReservedInventory; using CMSMicroservice.Application.InventoryItemCQ.Queries.GetInventoryItem; using CMSMicroservice.Application.InventoryItemCQ.Queries.GetInventoryByProduct; using CMSMicroservice.Application.InventoryItemCQ.Queries.GetAllInventoryItems; using CMSMicroservice.Application.InventoryItemCQ.Queries.GetLowStockItems; using CMSMicroservice.Application.StockMovementCQ.Commands.CreateStockMovement; using CMSMicroservice.Application.StockMovementCQ.Queries.GetStockMovements; using CMSMicroservice.Application.StockMovementCQ.Queries.GetStockMovementsByInventoryItem; using Google.Protobuf.WellKnownTypes; using Grpc.Core; using MediatR; namespace CMSMicroservice.WebApi.Services; public class InventoryService : InventoryContract.InventoryContractBase { private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS; private readonly IMediator _mediator; public InventoryService(IDispatchRequestToCQRS dispatchRequestToCQRS, IMediator mediator) { _dispatchRequestToCQRS = dispatchRequestToCQRS; _mediator = mediator; } // ========== Warehouse Management ========== public override async Task CreateWarehouse(CreateWarehouseRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task UpdateWarehouse(UpdateWarehouseRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task DeleteWarehouse(DeleteWarehouseRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task GetWarehouse(GetWarehouseRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task GetAllWarehouses(GetAllWarehousesRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task SetDefaultWarehouse(SetDefaultWarehouseRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } // ========== Inventory Item Management ========== public override async Task GetInventoryItem(GetInventoryItemRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task GetInventoryByProduct(GetInventoryByProductRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task GetAllInventoryItems(GetAllInventoryItemsRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task GetLowStockItems(GetLowStockItemsRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task UpdateInventorySettings(UpdateInventorySettingsRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } // ========== Stock Operations ========== public override async Task AddStock(AddStockRequest request, ServerCallContext context) { // Lookup InventoryItem by ProductId + ProductType var inventoryItem = await _mediator.Send( new GetInventoryByProductQuery { ProductId = request.ProductId, ProductType = (Domain.Enums.ProductType)request.ProductType }, context.CancellationToken); if (inventoryItem == null) { throw new RpcException(new Status(StatusCode.NotFound, $"Inventory item not found for ProductId={request.ProductId}, ProductType={request.ProductType}")); } // Execute IncreaseInventoryCommand var response = await _mediator.Send( new IncreaseInventoryCommand { Id = inventoryItem.Id, Quantity = request.Quantity, ReferenceNumber = request.ReferenceNumber }, context.CancellationToken); return new AddStockResponse { InventoryItemId = inventoryItem.Id, NewQuantity = response.NewQuantity }; } public override async Task AdjustStock(AdjustStockRequest request, ServerCallContext context) { // Lookup InventoryItem var inventoryItem = await _mediator.Send( new GetInventoryByProductQuery { ProductId = request.ProductId, ProductType = (Domain.Enums.ProductType)request.ProductType }, context.CancellationToken); if (inventoryItem == null) { throw new RpcException(new Status(StatusCode.NotFound, $"Inventory item not found for ProductId={request.ProductId}, ProductType={request.ProductType}")); } // Determine if increase or decrease var difference = request.NewQuantity - inventoryItem.Quantity; if (difference > 0) { await _mediator.Send( new IncreaseInventoryCommand { Id = inventoryItem.Id, Quantity = difference, ReferenceNumber = request.ReferenceNumber }, context.CancellationToken); return new AdjustStockResponse { PreviousQuantity = inventoryItem.Quantity, NewQuantity = request.NewQuantity, Difference = difference }; } else if (difference < 0) { await _mediator.Send( new ReduceInventoryCommand { Id = inventoryItem.Id, Quantity = Math.Abs(difference), FromReserved = false, ReferenceNumber = request.ReferenceNumber }, context.CancellationToken); return new AdjustStockResponse { PreviousQuantity = inventoryItem.Quantity, NewQuantity = request.NewQuantity, Difference = difference }; } else { return new AdjustStockResponse { PreviousQuantity = inventoryItem.Quantity, NewQuantity = inventoryItem.Quantity, Difference = 0 }; } } public override Task ReserveStock(ReserveStockRequest request, ServerCallContext context) { // TODO: Implement with product lookup throw new RpcException(new Status(StatusCode.Unimplemented, "ReserveStock requires product lookup - not yet implemented")); } public override Task ReleaseReservation(ReleaseReservationRequest request, ServerCallContext context) { // TODO: Implement with product lookup throw new RpcException(new Status(StatusCode.Unimplemented, "ReleaseReservation requires product lookup - not yet implemented")); } public override Task ConfirmSale(ConfirmSaleRequest request, ServerCallContext context) { // TODO: Implement with product lookup throw new RpcException(new Status(StatusCode.Unimplemented, "ConfirmSale requires product lookup - not yet implemented")); } public override Task ProcessReturn(ProcessReturnRequest request, ServerCallContext context) { // TODO: Implement with product lookup throw new RpcException(new Status(StatusCode.Unimplemented, "ProcessReturn requires product lookup - not yet implemented")); } public override Task RecordLoss(RecordLossRequest request, ServerCallContext context) { // TODO: Implement with product lookup throw new RpcException(new Status(StatusCode.Unimplemented, "RecordLoss requires product lookup - not yet implemented")); } // ========== Bulk Operations ========== public override Task BulkAddStock(BulkAddStockRequest request, ServerCallContext context) { // TODO: Implement with product lookup throw new RpcException(new Status(StatusCode.Unimplemented, "BulkAddStock requires product lookup - not yet implemented")); } // ========== Stock Movements ========== public override async Task GetStockMovements(GetStockMovementsRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } public override async Task GetStockMovementsByInventoryItem(GetStockMovementsByInventoryItemRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } // ========== Reports ========== public override Task GetInventorySummary(GetInventorySummaryRequest request, ServerCallContext context) { // TODO: Implement summary query return Task.FromResult(new GetInventorySummaryResponse { TotalProducts = 0, TotalDiscountProducts = 0, TotalQuantity = 0, TotalReserved = 0, LowStockCount = 0, OutOfStockCount = 0, TotalStockValue = 0 }); } public override Task GetStockValueReport(GetStockValueReportRequest request, ServerCallContext context) { // TODO: Implement stock value report query return Task.FromResult(new GetStockValueReportResponse { TotalValue = 0, TotalItems = 0 }); } }