Добавлена Organization.ShowMinMaxStock (bool, default false) — флаг видимости полей «Минимальный / Максимальный остаток» на карточке товара. В UI настроек магазина появилась соответствующая галка с подсказкой. По умолчанию выключено — большинству магазинов эти поля не нужны. Миграция Phase5f_ShowMinMaxStock добавляет колонку. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
109 lines
4.1 KiB
C#
109 lines
4.1 KiB
C#
using foodmarket.Application.Common.Tenancy;
|
|
using foodmarket.Infrastructure.Persistence;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace foodmarket.Api.Controllers.Organizations;
|
|
|
|
[ApiController]
|
|
[Authorize]
|
|
[Route("api/organization")]
|
|
public class OrganizationSettingsController : ControllerBase
|
|
{
|
|
private readonly AppDbContext _db;
|
|
private readonly ITenantContext _tenant;
|
|
|
|
public OrganizationSettingsController(AppDbContext db, ITenantContext tenant)
|
|
{
|
|
_db = db;
|
|
_tenant = tenant;
|
|
}
|
|
|
|
public record OrgSettingsDto(
|
|
Guid Id,
|
|
string Name,
|
|
string CountryCode,
|
|
Guid? DefaultCurrencyId,
|
|
string? DefaultCurrencyCode,
|
|
string? DefaultCurrencySymbol,
|
|
bool MultiCurrencyEnabled,
|
|
// VAT read-only: из страны организации (countries.VatRate). Источник правды — справочник стран.
|
|
decimal VatRate,
|
|
bool ShowVatEnabledOnProduct,
|
|
bool ShowServiceOnProduct,
|
|
bool ShowMarkedOnProduct,
|
|
bool ShowMinMaxStock);
|
|
|
|
// DefaultCurrencyId не принимается — он read-only, выводится из страны (Country.DefaultCurrencyId).
|
|
public record OrgSettingsInput(
|
|
string Name,
|
|
string CountryCode,
|
|
bool MultiCurrencyEnabled,
|
|
bool ShowVatEnabledOnProduct,
|
|
bool ShowServiceOnProduct,
|
|
bool ShowMarkedOnProduct,
|
|
bool ShowMinMaxStock);
|
|
|
|
[HttpGet("settings")]
|
|
public async Task<ActionResult<OrgSettingsDto>> Get(CancellationToken ct)
|
|
{
|
|
var orgId = _tenant.OrganizationId ?? throw new InvalidOperationException("No tenant.");
|
|
var o = await _db.Organizations
|
|
.Include(o => o.DefaultCurrency)
|
|
.FirstOrDefaultAsync(o => o.Id == orgId, ct);
|
|
if (o is null) return NotFound();
|
|
var vat = await ReadVatRateAsync(o.CountryCode, ct);
|
|
return Project(o, vat);
|
|
}
|
|
|
|
[HttpPut("settings"), Authorize(Roles = "Admin,Manager")]
|
|
public async Task<ActionResult<OrgSettingsDto>> Update([FromBody] OrgSettingsInput input, CancellationToken ct)
|
|
{
|
|
var orgId = _tenant.OrganizationId ?? throw new InvalidOperationException("No tenant.");
|
|
var o = await _db.Organizations
|
|
.Include(o => o.DefaultCurrency)
|
|
.FirstOrDefaultAsync(o => o.Id == orgId, ct);
|
|
if (o is null) return NotFound();
|
|
|
|
o.Name = input.Name;
|
|
o.CountryCode = input.CountryCode;
|
|
// Валюта организации жёстко следует за страной — не принимается от клиента.
|
|
o.DefaultCurrencyId = await _db.Countries
|
|
.Where(c => c.Code == input.CountryCode)
|
|
.Select(c => c.DefaultCurrencyId)
|
|
.FirstOrDefaultAsync(ct);
|
|
o.MultiCurrencyEnabled = input.MultiCurrencyEnabled;
|
|
o.ShowVatEnabledOnProduct = input.ShowVatEnabledOnProduct;
|
|
o.ShowServiceOnProduct = input.ShowServiceOnProduct;
|
|
o.ShowMarkedOnProduct = input.ShowMarkedOnProduct;
|
|
o.ShowMinMaxStock = input.ShowMinMaxStock;
|
|
await _db.SaveChangesAsync(ct);
|
|
|
|
await _db.Entry(o).Reference(x => x.DefaultCurrency).LoadAsync(ct);
|
|
var vat = await ReadVatRateAsync(o.CountryCode, ct);
|
|
return Project(o, vat);
|
|
}
|
|
|
|
private async Task<decimal> ReadVatRateAsync(string countryCode, CancellationToken ct)
|
|
{
|
|
var rate = await _db.Countries
|
|
.Where(c => c.Code == countryCode)
|
|
.Select(c => (decimal?)c.VatRate)
|
|
.FirstOrDefaultAsync(ct);
|
|
return rate ?? 0m;
|
|
}
|
|
|
|
private static OrgSettingsDto Project(foodmarket.Domain.Organizations.Organization o, decimal vat) => new(
|
|
o.Id, o.Name, o.CountryCode,
|
|
o.DefaultCurrencyId,
|
|
o.DefaultCurrency?.Code,
|
|
o.DefaultCurrency?.Symbol,
|
|
o.MultiCurrencyEnabled,
|
|
vat,
|
|
o.ShowVatEnabledOnProduct,
|
|
o.ShowServiceOnProduct,
|
|
o.ShowMarkedOnProduct,
|
|
o.ShowMinMaxStock);
|
|
}
|