-
This commit is contained in:
@@ -239,6 +239,7 @@ public class WarehouseArticlesController : ControllerBase
|
||||
public record ArticleDto(
|
||||
int Id,
|
||||
string Code,
|
||||
string? AlternativeCode,
|
||||
string Description,
|
||||
string? ShortDescription,
|
||||
string? Barcode,
|
||||
@@ -273,36 +274,36 @@ public class WarehouseArticlesController : ControllerBase
|
||||
);
|
||||
|
||||
public record CreateArticleDto(
|
||||
string Code,
|
||||
string Description,
|
||||
string? ShortDescription,
|
||||
string? Barcode,
|
||||
string? ManufacturerCode,
|
||||
int? CategoryId,
|
||||
string UnitOfMeasure,
|
||||
string? SecondaryUnitOfMeasure,
|
||||
decimal? UnitConversionFactor,
|
||||
StockManagementType StockManagement,
|
||||
bool IsBatchManaged,
|
||||
bool IsSerialManaged,
|
||||
bool HasExpiry,
|
||||
int? ExpiryWarningDays,
|
||||
decimal? MinimumStock,
|
||||
decimal? MaximumStock,
|
||||
decimal? ReorderPoint,
|
||||
decimal? ReorderQuantity,
|
||||
int? LeadTimeDays,
|
||||
ValuationMethod? ValuationMethod,
|
||||
decimal? StandardCost,
|
||||
decimal? BaseSellingPrice,
|
||||
decimal? Weight,
|
||||
decimal? Volume,
|
||||
string? Notes
|
||||
string? AlternativeCode = null,
|
||||
string? ShortDescription = null,
|
||||
string? Barcode = null,
|
||||
string? ManufacturerCode = null,
|
||||
int? CategoryId = null,
|
||||
string? SecondaryUnitOfMeasure = null,
|
||||
decimal? UnitConversionFactor = null,
|
||||
StockManagementType StockManagement = StockManagementType.Standard,
|
||||
bool IsBatchManaged = false,
|
||||
bool IsSerialManaged = false,
|
||||
bool HasExpiry = false,
|
||||
int? ExpiryWarningDays = null,
|
||||
decimal? MinimumStock = null,
|
||||
decimal? MaximumStock = null,
|
||||
decimal? ReorderPoint = null,
|
||||
decimal? ReorderQuantity = null,
|
||||
int? LeadTimeDays = null,
|
||||
ValuationMethod? ValuationMethod = null,
|
||||
decimal? StandardCost = null,
|
||||
decimal? BaseSellingPrice = null,
|
||||
decimal? Weight = null,
|
||||
decimal? Volume = null,
|
||||
string? Notes = null
|
||||
);
|
||||
|
||||
public record UpdateArticleDto(
|
||||
string Code,
|
||||
string Description,
|
||||
string? AlternativeCode,
|
||||
string? ShortDescription,
|
||||
string? Barcode,
|
||||
string? ManufacturerCode,
|
||||
@@ -363,6 +364,7 @@ public class WarehouseArticlesController : ControllerBase
|
||||
private static ArticleDto MapToDto(WarehouseArticle article) => new(
|
||||
article.Id,
|
||||
article.Code,
|
||||
article.AlternativeCode,
|
||||
article.Description,
|
||||
article.ShortDescription,
|
||||
article.Barcode,
|
||||
@@ -398,7 +400,8 @@ public class WarehouseArticlesController : ControllerBase
|
||||
|
||||
private static WarehouseArticle MapFromDto(CreateArticleDto dto) => new()
|
||||
{
|
||||
Code = dto.Code,
|
||||
// Code viene generato automaticamente da WarehouseService.CreateArticleAsync
|
||||
AlternativeCode = dto.AlternativeCode,
|
||||
Description = dto.Description,
|
||||
ShortDescription = dto.ShortDescription,
|
||||
Barcode = dto.Barcode,
|
||||
@@ -428,7 +431,8 @@ public class WarehouseArticlesController : ControllerBase
|
||||
|
||||
private static void UpdateFromDto(WarehouseArticle article, UpdateArticleDto dto)
|
||||
{
|
||||
article.Code = dto.Code;
|
||||
// Code non viene aggiornato - è generato automaticamente e immutabile
|
||||
article.AlternativeCode = dto.AlternativeCode;
|
||||
article.Description = dto.Description;
|
||||
article.ShortDescription = dto.ShortDescription;
|
||||
article.Barcode = dto.Barcode;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Apollinare.API.Services;
|
||||
using Apollinare.Domain.Entities.Warehouse;
|
||||
using Apollinare.Infrastructure.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -13,6 +14,7 @@ public class WarehouseService : IWarehouseService
|
||||
private readonly AppollinareDbContext _context;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly ILogger<WarehouseService> _logger;
|
||||
private readonly AutoCodeService _autoCodeService;
|
||||
|
||||
private const string WAREHOUSES_CACHE_KEY = "warehouse_locations";
|
||||
private const string CATEGORIES_CACHE_KEY = "warehouse_categories";
|
||||
@@ -22,11 +24,13 @@ public class WarehouseService : IWarehouseService
|
||||
public WarehouseService(
|
||||
AppollinareDbContext context,
|
||||
IMemoryCache cache,
|
||||
ILogger<WarehouseService> logger)
|
||||
ILogger<WarehouseService> logger,
|
||||
AutoCodeService autoCodeService)
|
||||
{
|
||||
_context = context;
|
||||
_cache = cache;
|
||||
_logger = logger;
|
||||
_autoCodeService = autoCodeService;
|
||||
}
|
||||
|
||||
#region Articoli
|
||||
@@ -118,6 +122,16 @@ public class WarehouseService : IWarehouseService
|
||||
|
||||
public async Task<WarehouseArticle> CreateArticleAsync(WarehouseArticle article)
|
||||
{
|
||||
// Genera codice automaticamente se non specificato
|
||||
if (string.IsNullOrWhiteSpace(article.Code))
|
||||
{
|
||||
var generatedCode = await _autoCodeService.GenerateNextCodeAsync("warehouse_article");
|
||||
if (generatedCode != null)
|
||||
article.Code = generatedCode;
|
||||
else
|
||||
throw new InvalidOperationException("Impossibile generare codice automatico per l'articolo");
|
||||
}
|
||||
|
||||
// Verifica unicità codice
|
||||
if (await _context.WarehouseArticles.AnyAsync(a => a.Code == article.Code))
|
||||
throw new InvalidOperationException($"Esiste già un articolo con codice '{article.Code}'");
|
||||
@@ -230,6 +244,16 @@ public class WarehouseService : IWarehouseService
|
||||
|
||||
public async Task<WarehouseArticleCategory> CreateCategoryAsync(WarehouseArticleCategory category)
|
||||
{
|
||||
// Genera codice automaticamente se non specificato
|
||||
if (string.IsNullOrWhiteSpace(category.Code))
|
||||
{
|
||||
var generatedCode = await _autoCodeService.GenerateNextCodeAsync("warehouse_category");
|
||||
if (generatedCode != null)
|
||||
category.Code = generatedCode;
|
||||
else
|
||||
throw new InvalidOperationException("Impossibile generare codice automatico per la categoria");
|
||||
}
|
||||
|
||||
if (await _context.WarehouseArticleCategories.AnyAsync(c => c.Code == category.Code))
|
||||
throw new InvalidOperationException($"Esiste già una categoria con codice '{category.Code}'");
|
||||
|
||||
@@ -336,6 +360,16 @@ public class WarehouseService : IWarehouseService
|
||||
|
||||
public async Task<WarehouseLocation> CreateWarehouseAsync(WarehouseLocation warehouse)
|
||||
{
|
||||
// Genera codice automaticamente se non specificato
|
||||
if (string.IsNullOrWhiteSpace(warehouse.Code))
|
||||
{
|
||||
var generatedCode = await _autoCodeService.GenerateNextCodeAsync("warehouse_location");
|
||||
if (generatedCode != null)
|
||||
warehouse.Code = generatedCode;
|
||||
else
|
||||
throw new InvalidOperationException("Impossibile generare codice automatico per il magazzino");
|
||||
}
|
||||
|
||||
if (await _context.WarehouseLocations.AnyAsync(w => w.Code == warehouse.Code))
|
||||
throw new InvalidOperationException($"Esiste già un magazzino con codice '{warehouse.Code}'");
|
||||
|
||||
@@ -464,6 +498,16 @@ public class WarehouseService : IWarehouseService
|
||||
if (!article.IsBatchManaged)
|
||||
throw new InvalidOperationException("L'articolo non è gestito a lotti");
|
||||
|
||||
// Genera numero lotto automaticamente se non specificato
|
||||
if (string.IsNullOrWhiteSpace(batch.BatchNumber))
|
||||
{
|
||||
var generatedCode = await _autoCodeService.GenerateNextCodeAsync("article_batch");
|
||||
if (generatedCode != null)
|
||||
batch.BatchNumber = generatedCode;
|
||||
else
|
||||
throw new InvalidOperationException("Impossibile generare numero lotto automatico");
|
||||
}
|
||||
|
||||
// Verifica unicità batch number per articolo
|
||||
if (await _context.ArticleBatches.AnyAsync(b => b.ArticleId == batch.ArticleId && b.BatchNumber == batch.BatchNumber))
|
||||
throw new InvalidOperationException($"Esiste già un lotto '{batch.BatchNumber}' per questo articolo");
|
||||
@@ -809,9 +853,15 @@ public class WarehouseService : IWarehouseService
|
||||
|
||||
public async Task<StockMovement> CreateMovementAsync(StockMovement movement)
|
||||
{
|
||||
// Genera numero documento se non specificato
|
||||
// Genera numero documento automaticamente se non specificato
|
||||
if (string.IsNullOrEmpty(movement.DocumentNumber))
|
||||
movement.DocumentNumber = await GenerateDocumentNumberAsync(movement.Type);
|
||||
{
|
||||
var generatedCode = await _autoCodeService.GenerateNextCodeAsync("stock_movement");
|
||||
if (generatedCode != null)
|
||||
movement.DocumentNumber = generatedCode;
|
||||
else
|
||||
movement.DocumentNumber = await GenerateDocumentNumberAsync(movement.Type); // Fallback
|
||||
}
|
||||
|
||||
// Verifica unicità documento
|
||||
if (await _context.StockMovements.AnyAsync(m => m.DocumentNumber == movement.DocumentNumber))
|
||||
@@ -1428,8 +1478,15 @@ public class WarehouseService : IWarehouseService
|
||||
|
||||
public async Task<InventoryCount> CreateInventoryCountAsync(InventoryCount inventory)
|
||||
{
|
||||
// Genera codice automaticamente se non specificato
|
||||
if (string.IsNullOrEmpty(inventory.Code))
|
||||
inventory.Code = $"INV/{DateTime.UtcNow:yyyyMMdd}/{await GenerateInventorySequenceAsync()}";
|
||||
{
|
||||
var generatedCode = await _autoCodeService.GenerateNextCodeAsync("inventory_count");
|
||||
if (generatedCode != null)
|
||||
inventory.Code = generatedCode;
|
||||
else
|
||||
inventory.Code = $"INV/{DateTime.UtcNow:yyyyMMdd}/{await GenerateInventorySequenceAsync()}"; // Fallback
|
||||
}
|
||||
|
||||
inventory.CreatedAt = DateTime.UtcNow;
|
||||
_context.InventoryCounts.Add(inventory);
|
||||
|
||||
Reference in New Issue
Block a user