GET /api/reports/sales — агрегаты по period:day/week/month, product, cashier, register, payment. Фильтры: from/to (по умолчанию last 30 days), storeId, productGroupId. Возвраты включаются с минусом (netto-выручка для фискальной отчётности). GET /api/reports/sales/export?format=csv|xlsx — выгрузка через CsvHelper (BOM UTF-8 + ; разделитель для Excel-RU) и ClosedXML. Реализация: плоский набор строк проектируется на сервере БД (Join+Where, EF переводит), агрегация в C#. Сознательный компромисс — EF8 не переводит «distinct count» внутри group-проекции с join'ами по nullable-ключам; объёмы отчётов (~десятки тысяч строк/месяц) держатся в RAM спокойно. Web: /reports/sales — выбор периода, табы группировки, фильтры, экспорт. Sidebar: «Отчёты → Продажи» для Admin/Storekeeper. Bonus: попутно вылечен баг RetailSalesController.Update — DbUpdateConcurrency «0 affected» воспроизводился при PUT на свеже-созданный возврат (create-return + immediate edit). Исправлено двумя изменениями: • Update не делает Include(Lines) — старые строки удаляются ExecuteDelete'ом; • ApplyLines добавляет новые строки напрямую в DbSet (а не через nav-collection sale.Lines.Add) — иначе EF8 путается со state'ом из-за client-side Id (Guid). Тесты: 5 интеграционных (group by product, group by payment, returns reduce revenue signed, tenant isolation, CSV export). 37 интеграционных всего зелёные. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
68 lines
3.6 KiB
XML
68 lines
3.6 KiB
XML
<Project>
|
|
<PropertyGroup>
|
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
|
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<!-- ASP.NET Core 8 -->
|
|
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
|
|
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.9.0" />
|
|
|
|
<!-- EF Core 8 + PostgreSQL -->
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.11" />
|
|
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
|
|
|
|
<!-- OpenIddict 5 (aligned to .NET 8 LTS) -->
|
|
<PackageVersion Include="OpenIddict.AspNetCore" Version="5.8.0" />
|
|
<PackageVersion Include="OpenIddict.EntityFrameworkCore" Version="5.8.0" />
|
|
|
|
<!-- Identity -->
|
|
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="2.3.1" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.11" />
|
|
|
|
<!-- App services -->
|
|
<PackageVersion Include="CsvHelper" Version="33.0.1" />
|
|
<PackageVersion Include="ClosedXML" Version="0.104.2" />
|
|
<PackageVersion Include="MailKit" Version="4.10.0" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="8.0.11" />
|
|
<PackageVersion Include="MediatR" Version="12.4.1" />
|
|
<PackageVersion Include="FluentValidation" Version="11.11.0" />
|
|
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
|
|
<PackageVersion Include="Mapster" Version="7.4.0" />
|
|
<PackageVersion Include="Mapster.DependencyInjection" Version="1.0.1" />
|
|
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
|
|
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
|
|
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
|
|
<!-- Background jobs -->
|
|
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.17" />
|
|
<PackageVersion Include="Hangfire.PostgreSql" Version="1.20.10" />
|
|
|
|
<!-- POS: local storage + API client -->
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
|
|
<PackageVersion Include="Refit" Version="7.2.22" />
|
|
<PackageVersion Include="Refit.HttpClientFactory" Version="7.2.22" />
|
|
<PackageVersion Include="Polly" Version="8.5.0" />
|
|
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
|
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
|
<PackageVersion Include="System.IO.Ports" Version="8.0.0" />
|
|
|
|
<!-- Testing -->
|
|
<PackageVersion Include="xunit" Version="2.9.3" />
|
|
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.1" />
|
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
|
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
|
|
<PackageVersion Include="NSubstitute" Version="5.3.0" />
|
|
<PackageVersion Include="coverlet.collector" Version="6.0.3" />
|
|
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11" />
|
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.11" />
|
|
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.1.0" />
|
|
</ItemGroup>
|
|
</Project>
|