Раньше продажи/возвраты/внесения/выплаты/расхождение смены не влияли на остаток кассы (касса уходила в −, эквайринг оставался 0). Теперь при закрытии смены MoneyService.MaterializeShiftMovementsAsync создаёт Posted-движения money_transactions по типам (Category): продажи нал/карта, возвраты нал/карта, внесение, выплата, излишек/недостача — привязанные к смене, идемпотентно. Остаток кассы/эквайринга и отчёт «Деньги» теперь верны автоматически (всё читает money_transactions). Отрицательный остаток: расход (CashOut/PaymentOut/TransferOut) больше остатка счёта и выплата из смены больше наличных смены → 409 insufficient-funds; настройка Organization.AllowNegativeBalance (по умолч. выкл., меняет только Admin). Миграция Phase34 (idempotent): money_transactions.Category/.CashShiftId, organizations.AllowNegativeBalance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
2.8 KiB
C#
56 lines
2.8 KiB
C#
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
using Microsoft.EntityFrameworkCore.Migrations;
|
|
using foodmarket.Infrastructure.Persistence;
|
|
|
|
#nullable disable
|
|
|
|
namespace foodmarket.Infrastructure.Persistence.Migrations
|
|
{
|
|
/// <summary>Phase34 — движения кассовой смены попадают в деньги.
|
|
///
|
|
/// Добавляет:
|
|
/// <list type="bullet">
|
|
/// <item>money_transactions.<c>Category</c> (integer, DEFAULT 0 = Manual) —
|
|
/// тип движения: розничные продажи/возвраты нал/карта, внесения/выплаты,
|
|
/// излишек/недостача смены.</item>
|
|
/// <item>money_transactions.<c>CashShiftId</c> (uuid, nullable) —
|
|
/// смена, породившая движение (материализуется при закрытии).</item>
|
|
/// <item>organizations.<c>AllowNegativeBalance</c> (boolean, DEFAULT false) —
|
|
/// разрешить ли уход счетов в минус.</item>
|
|
/// </list>
|
|
///
|
|
/// Идемпотентно (IF NOT EXISTS). Данные не пересчитываем: остаток счёта
|
|
/// вычисляемый (Opening + Σ Posted money_transactions); движения прошлых
|
|
/// закрытых смен материализуются ретроспективно отдельным backfill-методом
|
|
/// в DevDataSeeder (idempotent, по CashShiftId).</summary>
|
|
[DbContext(typeof(AppDbContext))]
|
|
[Migration("20261008030000_Phase34_ShiftMoneyMovements")]
|
|
public partial class Phase34_ShiftMoneyMovements : Migration
|
|
{
|
|
protected override void Up(MigrationBuilder b)
|
|
{
|
|
b.Sql(@"
|
|
ALTER TABLE public.money_transactions
|
|
ADD COLUMN IF NOT EXISTS ""Category"" integer NOT NULL DEFAULT 0;
|
|
ALTER TABLE public.money_transactions
|
|
ADD COLUMN IF NOT EXISTS ""CashShiftId"" uuid;
|
|
CREATE INDEX IF NOT EXISTS ""IX_money_transactions_CashShiftId""
|
|
ON public.money_transactions (""CashShiftId"")
|
|
WHERE ""CashShiftId"" IS NOT NULL;
|
|
ALTER TABLE public.organizations
|
|
ADD COLUMN IF NOT EXISTS ""AllowNegativeBalance"" boolean NOT NULL DEFAULT false;
|
|
");
|
|
}
|
|
|
|
protected override void Down(MigrationBuilder b)
|
|
{
|
|
b.Sql(@"
|
|
DROP INDEX IF EXISTS public.""IX_money_transactions_CashShiftId"";
|
|
ALTER TABLE public.money_transactions DROP COLUMN IF EXISTS ""CashShiftId"";
|
|
ALTER TABLE public.money_transactions DROP COLUMN IF EXISTS ""Category"";
|
|
ALTER TABLE public.organizations DROP COLUMN IF EXISTS ""AllowNegativeBalance"";
|
|
");
|
|
}
|
|
}
|
|
}
|