feat: единый файл Лист1+СПРАВКА, фильтры, сортировка, живой п/п

- Загрузка одного .xlsx (СПРАВКА + Лист1 в одном файле)
- Рег. номера берутся из СПРАВКА автоматически, группируются по (ТН ВЭД, Страна)
- Отдельный опциональный справочник кодов (CodesImportService)
- Фильтры: Все / Авто / Проверить / Нет кода / Без нетто
- Таблица сразу отсортирована по ТН ВЭД с живым обновлением п/п
- Начальный п/п: поле в UI, автоинкремент после экспорта
- Лист2: рамки, жёлтая строка при >1 рег. номере, итого по кол-ву
- Лист3: ТН ВЭД в колонке B вместо константы 09035
- Красный ErrorMessage под кнопкой загрузки, удалён SpravkaFileEntry
This commit is contained in:
Dianaka123
2026-04-07 11:47:31 +03:00
parent addf55e3b2
commit 697ae44519
13 changed files with 602 additions and 429 deletions
@@ -6,35 +6,36 @@ namespace DeclarationAutomatization.Services;
public class TransformService
{
// Группирует строки СПРАВКИ по ТН ВЭД → одна позиция Листа2.
// Количество, сумма, вес — суммируются.
// Рег. номер / дата — берётся первый непустой в группе.
// п/п — нумерация по порядку с 1.
public List<DeclarationItem> BuildDeclarationItems(IEnumerable<SpravkaItem> allItems)
// Строит позиции Листа2 из ИТОГО-строк Листа1.
// Рег. номера берёт из СПРАВКИ по ТН ВЭД.
public List<DeclarationItem> BuildDeclarationItems(
IEnumerable<Sheet1Group> groups,
IEnumerable<SpravkaItem> spravkaItems)
{
int sequentialNumber = 1;
// Индекс: (ТН ВЭД, Страна) → уникальные (рег. номер, дата) из СПРАВКИ
var regByKey = spravkaItems
.Where(s => !string.IsNullOrWhiteSpace(s.RegNumber))
.GroupBy(s => (s.TnVed, s.CountryId))
.ToDictionary(
g => g.Key,
g => g.Select(s => new RegEntry(s.RegNumber, s.RegDate))
.Distinct()
.ToList()
);
return allItems
.GroupBy(s => s.TnVed)
.Select(g =>
{
var first = g.First();
var regEntry = g.FirstOrDefault(s => !string.IsNullOrWhiteSpace(s.RegNumber));
return new DeclarationItem
{
SequentialNumber = sequentialNumber++,
Description = first.Description,
TnVed = first.TnVed,
CountryId = first.CountryId,
Quantity = g.Sum(s => s.Quantity),
AmountWithVat = g.Sum(s => s.AmountWithVat),
GrossWeight = g.Sum(s => s.GrossWeight),
NetWeight = g.Sum(s => s.NetWeight),
RegNumber = regEntry?.RegNumber ?? "",
RegDate = regEntry?.RegDate ?? "",
};
})
.ToList();
return groups.Select(group => new DeclarationItem
{
SequentialNumber = group.SequentialNumber,
Description = group.Description,
TnVed = group.TnVed,
CountryId = group.CountryId,
Quantity = group.Quantity,
AmountWithVat = group.AmountWithVat,
GrossWeight = group.GrossWeight,
NetWeight = group.NetWeight,
RegEntries = regByKey.TryGetValue((group.TnVed, group.CountryId), out var regs)
? regs
: new List<RegEntry>(),
}).ToList();
}
}