Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
Персистентные уведомления (таблица notifications, Phase41) + REST
/api/notifications (список/счётчик/read/read-all) → центр уведомлений в вебе
(колокольчик, API-backed) и мобильном API.
Фоновый джоб NegativeStockNotificationJob (cron */5): агрегирует новые минусы
в ОДНО уведомление на склад (дебаунс по NotifiedAt + интервал орг., по умолч.
15 мин), уважает тихие часы (Asia/Almaty); эскалация просроченных (>N часов,
по умолч. 24) владельцу/админам. Получатели — админы, владелец, кладовщики
(право InventoryEdit). Каналы: SignalR (живой колокольчик), Telegram (владельцу),
push-заглушка.
Настройки организации: NegStockNotify{Enabled,IntervalMinutes,QuietFrom/ToHour,
EscalateHours} + GET/PUT /api/organization/settings + секция в настройках веба.
Блок «Просроченные минусы» на дашборде.
Тесты: unit тихих часов 3/3; integration — джоб создаёт уведомление админу,
дебаунс, read-all 3/3 (вся группа NegativeStockTests зелёная).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
22 lines
1 KiB
C#
22 lines
1 KiB
C#
using System;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using foodmarket.Application.Inventory;
|
||
|
||
namespace foodmarket.UnitTests;
|
||
|
||
/// <summary>No-op реализация <see cref="INegativeStockAlertService"/> для юнит-тестов
|
||
/// StockService, которым неважны предупреждения об отрицательных остатках (они
|
||
/// проверяют только арифметику остатков). Поведение алертов покрыто отдельными
|
||
/// интеграционными тестами (NegativeStockTests).</summary>
|
||
public sealed class NoopNegativeStockAlertService : INegativeStockAlertService
|
||
{
|
||
public static readonly NoopNegativeStockAlertService Instance = new();
|
||
|
||
public Task OnStockLevelAsync(
|
||
Guid storeId, Guid productId, decimal newQty,
|
||
string? causeDocType, Guid? causeDocId, string? causeDocNumber,
|
||
Guid? causeUserId, DateTime? causeAt,
|
||
CancellationToken ct = default) => Task.CompletedTask;
|
||
}
|