Чистая логика вынесена в Application для тестируемости и используется контроллерами: - MovingAverageCost.Compute (скользящее среднее себестоимости) ← SuppliesController.Post - RetailPaymentValidator.IsSufficient (достаточность оплаты) ← RetailSalesController.Post Тесты: - MovingAverageCost: первая приёмка, средневзвешенное, округление до 4 знаков, totalQty=0. - RetailPaymentValidator: ровно/переплата/недоплата, округление до 2 знаков. - StockService.ApplyMovement (SQLite in-memory): материализация Stock+движение, инкремент, отрицательное списание, throw без tenant. - Мультитенантный query-filter AppDbContext: tenant видит своё; чужой не видит; SuperAdmin без override — всё; с override — только выбранную оргу. Все 23 зелёные. EF8 SQLite поддерживает ToJson (EmployeeRole.Permissions). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
35 lines
1.7 KiB
C#
35 lines
1.7 KiB
C#
using FluentAssertions;
|
|
using foodmarket.Application.Sales;
|
|
using Xunit;
|
|
|
|
namespace foodmarket.UnitTests;
|
|
|
|
/// <summary>Достаточность оплаты розничного чека (логика RetailSalesController.Post).</summary>
|
|
public class RetailPaymentValidatorTests
|
|
{
|
|
[Theory]
|
|
[InlineData(1000, 0, 1000)] // ровно наличными
|
|
[InlineData(0, 1000, 1000)] // ровно картой
|
|
[InlineData(600, 400, 1000)] // смешанная оплата, ровно
|
|
[InlineData(1500, 0, 1000)] // переплата наличными (сдача) — ок
|
|
[InlineData(700, 700, 1000)] // переплата смешанная — ок
|
|
public void Sufficient_payment_passes(decimal cash, decimal card, decimal total)
|
|
=> RetailPaymentValidator.IsSufficient(cash, card, total).Should().BeTrue();
|
|
|
|
[Theory]
|
|
[InlineData(999, 0, 1000)] // недоплата наличными
|
|
[InlineData(0, 0, 1000)] // не оплачено вовсе
|
|
[InlineData(400, 400, 1000)] // смешанная недоплата
|
|
public void Insufficient_payment_fails(decimal cash, decimal card, decimal total)
|
|
=> RetailPaymentValidator.IsSufficient(cash, card, total).Should().BeFalse();
|
|
|
|
[Fact]
|
|
public void Rounds_to_two_decimals_before_comparing()
|
|
{
|
|
// 999.999 округляется до 1000.00 ≥ 1000 → ок (защита от float-дрейфа)
|
|
RetailPaymentValidator.IsSufficient(999.999m, 0m, 1000m).Should().BeTrue();
|
|
// 999.994 → 999.99 < 1000 → недоплата
|
|
RetailPaymentValidator.IsSufficient(999.994m, 0m, 1000m).Should().BeFalse();
|
|
}
|
|
}
|