feat: Implement inventory and warehouse management features
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 2m33s
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 2m33s
- Add GetLowStockItemsResponseDto and LowStockItemDto for low stock item queries. - Create CreateStockMovementCommand and its handler for managing stock movements. - Implement CreateStockMovementCommandValidator for validating stock movement commands. - Add GetStockMovementsQuery and its handler to retrieve stock movement records. - Create GetStockMovementsResponseDto and StockMovementListDto for stock movement responses. - Implement GetStockMovementsByInventoryItemQuery and its handler for fetching movements by inventory item. - Add CreateWarehouseCommand and its handler for creating new warehouses. - Implement CreateWarehouseCommandValidator for warehouse creation validation. - Add DeleteWarehouseCommand and its handler for removing warehouses. - Implement SetDefaultWarehouseCommand and its handler for setting a default warehouse. - Create UpdateWarehouseCommand and its handler for updating warehouse details. - Implement GetAllWarehousesQuery and its handler to retrieve all warehouses. - Add GetWarehouseQuery and its handler for fetching a specific warehouse by ID. - Implement SearchWarehousesQuery and its handler for searching warehouses based on criteria.
This commit is contained in:
@@ -1,25 +1,27 @@
|
||||
using CMSMicroservice.Protobuf.Protos.Inventory;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
// Warehouse Commands & Queries
|
||||
using CMSMicroservice.Application.Features.Warehouses.Commands;
|
||||
using CMSMicroservice.Application.Features.Warehouses.Queries;
|
||||
// InventoryItem Commands & Queries
|
||||
using CMSMicroservice.Application.Features.InventoryItems.Commands;
|
||||
using CMSMicroservice.Application.Features.InventoryItems.Queries;
|
||||
// StockMovement Commands & Queries
|
||||
using CMSMicroservice.Application.Features.StockMovements.Commands;
|
||||
using CMSMicroservice.Application.Features.StockMovements.Queries;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using Mapster;
|
||||
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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
/// <summary>
|
||||
/// gRPC Service for Inventory Management
|
||||
/// </summary>
|
||||
public class InventoryService : InventoryContract.InventoryContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
|
||||
@@ -29,206 +31,161 @@ public class InventoryService : InventoryContract.InventoryContractBase
|
||||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||
}
|
||||
|
||||
#region Warehouse Management
|
||||
// ========== Warehouse Management ==========
|
||||
|
||||
public override async Task<CreateWarehouseResponse> CreateWarehouse(CreateWarehouseRequest request, ServerCallContext context)
|
||||
{
|
||||
var id = await _dispatchRequestToCQRS.Handle<CreateWarehouseRequest, CreateWarehouseCommand, long>(request, context);
|
||||
return new CreateWarehouseResponse { Id = id };
|
||||
return await _dispatchRequestToCQRS.Handle<CreateWarehouseRequest, CreateWarehouseCommand, CreateWarehouseResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<Empty> UpdateWarehouse(UpdateWarehouseRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<UpdateWarehouseRequest, UpdateWarehouseCommand, bool>(request, context);
|
||||
return new Empty();
|
||||
return await _dispatchRequestToCQRS.Handle<UpdateWarehouseRequest, UpdateWarehouseCommand>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<Empty> DeleteWarehouse(DeleteWarehouseRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<DeleteWarehouseRequest, DeleteWarehouseCommand, bool>(request, context);
|
||||
return new Empty();
|
||||
return await _dispatchRequestToCQRS.Handle<DeleteWarehouseRequest, DeleteWarehouseCommand>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetWarehouseResponse> GetWarehouse(GetWarehouseRequest request, ServerCallContext context)
|
||||
{
|
||||
var warehouse = await _dispatchRequestToCQRS.Handle<GetWarehouseRequest, GetWarehouseByIdQuery, Warehouse?>(request, context);
|
||||
return new GetWarehouseResponse
|
||||
{
|
||||
Warehouse = warehouse?.Adapt<WarehouseDto>()
|
||||
};
|
||||
return await _dispatchRequestToCQRS.Handle<GetWarehouseRequest, GetWarehouseQuery, GetWarehouseResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetAllWarehousesResponse> GetAllWarehouses(GetAllWarehousesRequest request, ServerCallContext context)
|
||||
{
|
||||
var warehouses = await _dispatchRequestToCQRS.Handle<GetAllWarehousesRequest, GetAllWarehousesQuery, List<Warehouse>>(request, context);
|
||||
var response = new GetAllWarehousesResponse { TotalCount = warehouses.Count };
|
||||
response.Warehouses.AddRange(warehouses.Select(w => w.Adapt<WarehouseDto>()));
|
||||
return response;
|
||||
return await _dispatchRequestToCQRS.Handle<GetAllWarehousesRequest, GetAllWarehousesQuery, GetAllWarehousesResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<Empty> SetDefaultWarehouse(SetDefaultWarehouseRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<SetDefaultWarehouseRequest, SetDefaultWarehouseCommand, bool>(request, context);
|
||||
return new Empty();
|
||||
return await _dispatchRequestToCQRS.Handle<SetDefaultWarehouseRequest, SetDefaultWarehouseCommand>(request, context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inventory Item Management
|
||||
// ========== Inventory Item Management ==========
|
||||
|
||||
public override async Task<GetInventoryItemResponse> GetInventoryItem(GetInventoryItemRequest request, ServerCallContext context)
|
||||
{
|
||||
var item = await _dispatchRequestToCQRS.Handle<GetInventoryItemRequest, GetInventoryItemByIdQuery, InventoryItem?>(request, context);
|
||||
return new GetInventoryItemResponse
|
||||
{
|
||||
Item = item?.Adapt<InventoryItemDto>()
|
||||
};
|
||||
return await _dispatchRequestToCQRS.Handle<GetInventoryItemRequest, GetInventoryItemQuery, GetInventoryItemResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetInventoryByProductResponse> GetInventoryByProduct(GetInventoryByProductRequest request, ServerCallContext context)
|
||||
{
|
||||
InventoryItem? item;
|
||||
if (request.ProductType == Protobuf.Protos.Inventory.ProductType.RegularProduct)
|
||||
{
|
||||
item = await _dispatchRequestToCQRS.Handle<GetInventoryByProductRequest, GetInventoryItemByProductIdQuery, InventoryItem?>(request, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
item = await _dispatchRequestToCQRS.Handle<GetInventoryByProductRequest, GetInventoryItemByDiscountProductIdQuery, InventoryItem?>(request, context);
|
||||
}
|
||||
return new GetInventoryByProductResponse
|
||||
{
|
||||
Item = item?.Adapt<InventoryItemDto>()
|
||||
};
|
||||
return await _dispatchRequestToCQRS.Handle<GetInventoryByProductRequest, GetInventoryByProductQuery, GetInventoryByProductResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetAllInventoryItemsResponse> GetAllInventoryItems(GetAllInventoryItemsRequest request, ServerCallContext context)
|
||||
{
|
||||
var items = await _dispatchRequestToCQRS.Handle<GetAllInventoryItemsRequest, SearchInventoryItemsQuery, List<InventoryItem>>(request, context);
|
||||
var response = new GetAllInventoryItemsResponse { TotalCount = items.Count };
|
||||
response.Items.AddRange(items.Select(i => i.Adapt<InventoryItemDto>()));
|
||||
return response;
|
||||
return await _dispatchRequestToCQRS.Handle<GetAllInventoryItemsRequest, GetAllInventoryItemsQuery, GetAllInventoryItemsResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetLowStockItemsResponse> GetLowStockItems(GetLowStockItemsRequest request, ServerCallContext context)
|
||||
{
|
||||
var items = await _dispatchRequestToCQRS.Handle<GetLowStockItemsRequest, GetLowStockItemsQuery, List<InventoryItem>>(request, context);
|
||||
var response = new GetLowStockItemsResponse { TotalCount = items.Count };
|
||||
response.Items.AddRange(items.Select(i => i.Adapt<InventoryItemDto>()));
|
||||
return response;
|
||||
return await _dispatchRequestToCQRS.Handle<GetLowStockItemsRequest, GetLowStockItemsQuery, GetLowStockItemsResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<Empty> UpdateInventorySettings(UpdateInventorySettingsRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<UpdateInventorySettingsRequest, UpdateInventoryItemCommand, bool>(request, context);
|
||||
return new Empty();
|
||||
return await _dispatchRequestToCQRS.Handle<UpdateInventorySettingsRequest, UpdateInventoryItemCommand>(request, context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
// ========== Stock Operations ==========
|
||||
// Note: These operations need lookup by ProductId/ProductType which requires additional implementation
|
||||
// For now, returning stub responses - actual implementation needs custom handlers
|
||||
|
||||
#region Stock Operations
|
||||
|
||||
public override async Task<AddStockResponse> AddStock(AddStockRequest request, ServerCallContext context)
|
||||
public override Task<AddStockResponse> AddStock(AddStockRequest request, ServerCallContext context)
|
||||
{
|
||||
var success = await _dispatchRequestToCQRS.Handle<AddStockRequest, IncreaseInventoryCommand, bool>(request, context);
|
||||
return new AddStockResponse
|
||||
{
|
||||
InventoryItemId = 0, // Will be filled by mapping
|
||||
NewQuantity = 0
|
||||
};
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "AddStock requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<AdjustStockResponse> AdjustStock(AdjustStockRequest request, ServerCallContext context)
|
||||
public override Task<AdjustStockResponse> AdjustStock(AdjustStockRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<AdjustStockRequest, UpdateInventoryQuantityCommand, bool>(request, context);
|
||||
return new AdjustStockResponse();
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "AdjustStock requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<ReserveStockResponse> ReserveStock(ReserveStockRequest request, ServerCallContext context)
|
||||
public override Task<ReserveStockResponse> ReserveStock(ReserveStockRequest request, ServerCallContext context)
|
||||
{
|
||||
var success = await _dispatchRequestToCQRS.Handle<ReserveStockRequest, ReserveInventoryCommand, bool>(request, context);
|
||||
return new ReserveStockResponse
|
||||
{
|
||||
Success = success,
|
||||
Message = success ? "Stock reserved successfully" : "Failed to reserve stock"
|
||||
};
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "ReserveStock requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<Empty> ReleaseReservation(ReleaseReservationRequest request, ServerCallContext context)
|
||||
public override Task<Empty> ReleaseReservation(ReleaseReservationRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<ReleaseReservationRequest, ReleaseReservedInventoryCommand, bool>(request, context);
|
||||
return new Empty();
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "ReleaseReservation requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<Empty> ConfirmSale(ConfirmSaleRequest request, ServerCallContext context)
|
||||
public override Task<Empty> ConfirmSale(ConfirmSaleRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<ConfirmSaleRequest, ReduceInventoryCommand, bool>(request, context);
|
||||
return new Empty();
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "ConfirmSale requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<ProcessReturnResponse> ProcessReturn(ProcessReturnRequest request, ServerCallContext context)
|
||||
public override Task<ProcessReturnResponse> ProcessReturn(ProcessReturnRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<ProcessReturnRequest, IncreaseInventoryCommand, bool>(request, context);
|
||||
return new ProcessReturnResponse { NewQuantity = 0 };
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "ProcessReturn requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<Empty> RecordLoss(RecordLossRequest request, ServerCallContext context)
|
||||
public override Task<Empty> RecordLoss(RecordLossRequest request, ServerCallContext context)
|
||||
{
|
||||
await _dispatchRequestToCQRS.Handle<RecordLossRequest, CreateStockMovementCommand, long>(request, context);
|
||||
return new Empty();
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "RecordLoss requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
// ========== Bulk Operations ==========
|
||||
|
||||
#region Bulk Operations
|
||||
|
||||
public override async Task<BulkAddStockResponse> BulkAddStock(BulkAddStockRequest request, ServerCallContext context)
|
||||
public override Task<BulkAddStockResponse> BulkAddStock(BulkAddStockRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement bulk add stock
|
||||
return new BulkAddStockResponse { SuccessCount = 0, FailedCount = 0 };
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "BulkAddStock requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
public override async Task<BulkAdjustStockResponse> BulkAdjustStock(BulkAdjustStockRequest request, ServerCallContext context)
|
||||
public override Task<BulkAdjustStockResponse> BulkAdjustStock(BulkAdjustStockRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement bulk adjust stock
|
||||
return new BulkAdjustStockResponse { SuccessCount = 0, FailedCount = 0 };
|
||||
// TODO: Implement with product lookup
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "BulkAdjustStock requires product lookup - not yet implemented"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stock Movements
|
||||
// ========== Stock Movements ==========
|
||||
|
||||
public override async Task<GetStockMovementsResponse> GetStockMovements(GetStockMovementsRequest request, ServerCallContext context)
|
||||
{
|
||||
var movements = await _dispatchRequestToCQRS.Handle<GetStockMovementsRequest, SearchStockMovementsQuery, List<StockMovement>>(request, context);
|
||||
var response = new GetStockMovementsResponse { TotalCount = movements.Count };
|
||||
response.Movements.AddRange(movements.Select(m => m.Adapt<StockMovementDto>()));
|
||||
return response;
|
||||
return await _dispatchRequestToCQRS.Handle<GetStockMovementsRequest, GetStockMovementsQuery, GetStockMovementsResponse>(request, context);
|
||||
}
|
||||
|
||||
public override async Task<GetStockMovementsByInventoryItemResponse> GetStockMovementsByInventoryItem(GetStockMovementsByInventoryItemRequest request, ServerCallContext context)
|
||||
{
|
||||
var movements = await _dispatchRequestToCQRS.Handle<GetStockMovementsByInventoryItemRequest, GetInventoryItemMovementHistoryQuery, List<StockMovement>>(request, context);
|
||||
var response = new GetStockMovementsByInventoryItemResponse { TotalCount = movements.Count };
|
||||
response.Movements.AddRange(movements.Select(m => m.Adapt<StockMovementDto>()));
|
||||
return response;
|
||||
return await _dispatchRequestToCQRS.Handle<GetStockMovementsByInventoryItemRequest, GetStockMovementsByInventoryItemQuery, GetStockMovementsByInventoryItemResponse>(request, context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
// ========== Reports ==========
|
||||
|
||||
#region Reports
|
||||
|
||||
public override async Task<GetInventorySummaryResponse> GetInventorySummary(GetInventorySummaryRequest request, ServerCallContext context)
|
||||
public override Task<GetInventorySummaryResponse> GetInventorySummary(GetInventorySummaryRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement summary query
|
||||
return new GetInventorySummaryResponse();
|
||||
return Task.FromResult(new GetInventorySummaryResponse
|
||||
{
|
||||
TotalProducts = 0,
|
||||
TotalDiscountProducts = 0,
|
||||
TotalQuantity = 0,
|
||||
TotalReserved = 0,
|
||||
LowStockCount = 0,
|
||||
OutOfStockCount = 0,
|
||||
TotalStockValue = 0
|
||||
});
|
||||
}
|
||||
|
||||
public override async Task<GetStockValueReportResponse> GetStockValueReport(GetStockValueReportRequest request, ServerCallContext context)
|
||||
public override Task<GetStockValueReportResponse> GetStockValueReport(GetStockValueReportRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement stock value report
|
||||
return new GetStockValueReportResponse();
|
||||
// TODO: Implement stock value report query
|
||||
return Task.FromResult(new GetStockValueReportResponse
|
||||
{
|
||||
TotalValue = 0,
|
||||
TotalItems = 0
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user