feat(org-settings): валюта read-only, тянется из страны (как НДС)
- Currency в настройках больше не выбирается, показывается disabled как "KZT (₸)", источник правды — Country.DefaultCurrencyId. - Backend: OrgSettingsInput больше не принимает DefaultCurrencyId; Update синхронизирует Organization.DefaultCurrencyId со страной. - UX: страна — единственный редактируемый вход, определяет и НДС, и валюту. - Мульти-валютный режим (Organization.MultiCurrencyEnabled) остаётся галкой; выбор валюты в закупках/продажах/карточке товара по-прежнему скрыт когда флаг выключен. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6979599791
commit
5bea852b94
|
|
@ -32,10 +32,10 @@ public record OrgSettingsDto(
|
|||
decimal VatRate,
|
||||
bool ShowVatEnabledOnProduct);
|
||||
|
||||
// DefaultCurrencyId не принимается — он read-only, выводится из страны (Country.DefaultCurrencyId).
|
||||
public record OrgSettingsInput(
|
||||
string Name,
|
||||
string CountryCode,
|
||||
Guid? DefaultCurrencyId,
|
||||
bool MultiCurrencyEnabled,
|
||||
bool ShowVatEnabledOnProduct);
|
||||
|
||||
|
|
@ -62,7 +62,11 @@ public async Task<ActionResult<OrgSettingsDto>> Update([FromBody] OrgSettingsInp
|
|||
|
||||
o.Name = input.Name;
|
||||
o.CountryCode = input.CountryCode;
|
||||
o.DefaultCurrencyId = input.DefaultCurrencyId;
|
||||
// Валюта организации жёстко следует за страной — не принимается от клиента.
|
||||
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;
|
||||
await _db.SaveChangesAsync(ct);
|
||||
|
|
|
|||
|
|
@ -5,31 +5,27 @@ import { api } from '@/lib/api'
|
|||
import { PageHeader } from '@/components/PageHeader'
|
||||
import { Button } from '@/components/Button'
|
||||
import { Field, TextInput, Select, Checkbox } from '@/components/Field'
|
||||
import { useCurrencies, useCountries } from '@/lib/useLookups'
|
||||
import { useCountries } from '@/lib/useLookups'
|
||||
import { useOrgSettings, type OrgSettings } from '@/lib/useOrgSettings'
|
||||
|
||||
export function OrganizationSettingsPage() {
|
||||
const qc = useQueryClient()
|
||||
const settings = useOrgSettings()
|
||||
const currencies = useCurrencies()
|
||||
const countries = useCountries()
|
||||
|
||||
const [form, setForm] = useState<OrgSettings | null>(null)
|
||||
useEffect(() => { if (settings.data && !form) setForm(settings.data) }, [settings.data, form])
|
||||
|
||||
// При смене страны подтягиваем её валюту и ставку НДС (оба из справочника стран).
|
||||
// При смене страны подтягиваем её валюту и ставку НДС (оба read-only, из справочника стран).
|
||||
const onCountryChange = (countryCode: string) => {
|
||||
if (!form) return
|
||||
const country = countries.data?.find((c) => c.code === countryCode)
|
||||
const currency = country?.defaultCurrencyId
|
||||
? currencies.data?.find((c) => c.id === country.defaultCurrencyId)
|
||||
: undefined
|
||||
setForm({
|
||||
...form,
|
||||
countryCode,
|
||||
defaultCurrencyId: currency?.id ?? country?.defaultCurrencyId ?? null,
|
||||
defaultCurrencyCode: currency?.code ?? country?.defaultCurrencyCode ?? null,
|
||||
defaultCurrencySymbol: currency?.symbol ?? country?.defaultCurrencySymbol ?? null,
|
||||
defaultCurrencyId: country?.defaultCurrencyId ?? null,
|
||||
defaultCurrencyCode: country?.defaultCurrencyCode ?? null,
|
||||
defaultCurrencySymbol: country?.defaultCurrencySymbol ?? null,
|
||||
vatRate: country?.vatRate ?? 0,
|
||||
})
|
||||
}
|
||||
|
|
@ -40,7 +36,6 @@ export function OrganizationSettingsPage() {
|
|||
const payload = {
|
||||
name: form.name,
|
||||
countryCode: form.countryCode,
|
||||
defaultCurrencyId: form.defaultCurrencyId,
|
||||
multiCurrencyEnabled: form.multiCurrencyEnabled,
|
||||
showVatEnabledOnProduct: form.showVatEnabledOnProduct,
|
||||
}
|
||||
|
|
@ -71,17 +66,10 @@ export function OrganizationSettingsPage() {
|
|||
</Select>
|
||||
</Field>
|
||||
<Field label="Валюта по умолчанию">
|
||||
<Select
|
||||
value={form.defaultCurrencyId ?? ''}
|
||||
onChange={(e) => {
|
||||
const id = e.target.value
|
||||
const c = currencies.data?.find((x) => x.id === id)
|
||||
setForm({ ...form, defaultCurrencyId: id || null, defaultCurrencyCode: c?.code ?? null, defaultCurrencySymbol: c?.symbol ?? null })
|
||||
}}
|
||||
>
|
||||
<option value="">—</option>
|
||||
{currencies.data?.map((c) => <option key={c.id} value={c.id}>{c.code} ({c.symbol})</option>)}
|
||||
</Select>
|
||||
<TextInput
|
||||
value={form.defaultCurrencyCode ? `${form.defaultCurrencyCode} (${form.defaultCurrencySymbol ?? ''})` : '—'}
|
||||
disabled
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue