fix(moysklad): не выдумывать Kind=Both для импортированных контрагентов
У MoySklad НЕТ встроенного поля «Поставщик/Покупатель» у контрагентов —
эта классификация целиком пользовательская через теги или группы. Импорт
ставил Kind=Both дефолтом когда тегов не было, что искажало данные:
все 586 контрагентов на stage стали «Оба», хотя в MoySklad ничего такого
не было.
- CounterpartyKind: добавлен Unspecified=0 как дефолт
- ImportCounterpartiesAsync.ResolveKind: возвращает Unspecified когда
тегов нет; Both только если в тегах ОБА маркера ("постав" + "покуп");
иначе один из конкретных
- UI: dropdown получил опцию «Не указано», лейбл «Оба» переименован в
«Поставщик + Покупатель» (точнее)
- Существующие данные: SQL UPDATE Kind=3 → Kind=0 на stage (586 строк)
и dev (0 строк, локально пусто)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7640d6ddcd
commit
2d1a9c8f75
|
|
@ -2,6 +2,10 @@ namespace foodmarket.Domain.Catalog;
|
|||
|
||||
public enum CounterpartyKind
|
||||
{
|
||||
/// <summary>Не указано — дефолт для импортированных без явной классификации.
|
||||
/// MoySklad сам не имеет встроенного поля Supplier/Customer, оно ставится
|
||||
/// через теги или группы, и часто отсутствует. Не выдумываем за пользователя.</summary>
|
||||
Unspecified = 0,
|
||||
Supplier = 1,
|
||||
Customer = 2,
|
||||
Both = 3,
|
||||
|
|
|
|||
|
|
@ -39,16 +39,19 @@ public async Task<MoySkladImportResult> ImportCounterpartiesAsync(string token,
|
|||
{
|
||||
var orgId = _tenant.OrganizationId ?? throw new InvalidOperationException("No tenant organization in context.");
|
||||
|
||||
// Map MoySklad tag set → local CounterpartyKind. If no tags say otherwise, assume Both.
|
||||
// MoySklad сам НЕ имеет встроенного "Supplier/Customer" поля у контрагентов.
|
||||
// Классификация обычно через теги ("Поставщик"/"Покупатель") или группы. Если их нет —
|
||||
// оставляем Unspecified, не выдумываем за пользователя.
|
||||
static foodmarket.Domain.Catalog.CounterpartyKind ResolveKind(IReadOnlyList<string>? tags)
|
||||
{
|
||||
if (tags is null || tags.Count == 0) return foodmarket.Domain.Catalog.CounterpartyKind.Both;
|
||||
if (tags is null || tags.Count == 0) return foodmarket.Domain.Catalog.CounterpartyKind.Unspecified;
|
||||
var lower = tags.Select(t => t.ToLowerInvariant()).ToList();
|
||||
var hasSupplier = lower.Any(t => t.Contains("постав"));
|
||||
var hasCustomer = lower.Any(t => t.Contains("покуп") || t.Contains("клиент"));
|
||||
if (hasSupplier && !hasCustomer) return foodmarket.Domain.Catalog.CounterpartyKind.Supplier;
|
||||
if (hasCustomer && !hasSupplier) return foodmarket.Domain.Catalog.CounterpartyKind.Customer;
|
||||
return foodmarket.Domain.Catalog.CounterpartyKind.Both;
|
||||
if (hasSupplier && hasCustomer) return foodmarket.Domain.Catalog.CounterpartyKind.Both;
|
||||
if (hasSupplier) return foodmarket.Domain.Catalog.CounterpartyKind.Supplier;
|
||||
if (hasCustomer) return foodmarket.Domain.Catalog.CounterpartyKind.Customer;
|
||||
return foodmarket.Domain.Catalog.CounterpartyKind.Unspecified;
|
||||
}
|
||||
|
||||
static foodmarket.Domain.Catalog.CounterpartyType ResolveType(string? companyType)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export interface PagedResult<T> {
|
|||
totalPages: number
|
||||
}
|
||||
|
||||
export const CounterpartyKind = { Supplier: 1, Customer: 2, Both: 3 } as const
|
||||
export const CounterpartyKind = { Unspecified: 0, Supplier: 1, Customer: 2, Both: 3 } as const
|
||||
export type CounterpartyKind = (typeof CounterpartyKind)[keyof typeof CounterpartyKind]
|
||||
|
||||
export const CounterpartyType = { LegalEntity: 1, Individual: 2 } as const
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ interface Form {
|
|||
}
|
||||
|
||||
const blankForm: Form = {
|
||||
name: '', legalName: '', kind: CounterpartyKind.Supplier, type: CounterpartyType.LegalEntity,
|
||||
name: '', legalName: '', kind: CounterpartyKind.Unspecified, type: CounterpartyType.LegalEntity,
|
||||
bin: '', iin: '', taxNumber: '', countryId: '',
|
||||
address: '', phone: '', email: '',
|
||||
bankName: '', bankAccount: '', bik: '',
|
||||
|
|
@ -44,9 +44,10 @@ const blankForm: Form = {
|
|||
}
|
||||
|
||||
const kindLabel: Record<CounterpartyKind, string> = {
|
||||
[CounterpartyKind.Unspecified]: '—',
|
||||
[CounterpartyKind.Supplier]: 'Поставщик',
|
||||
[CounterpartyKind.Customer]: 'Покупатель',
|
||||
[CounterpartyKind.Both]: 'Оба',
|
||||
[CounterpartyKind.Both]: 'Поставщик + Покупатель',
|
||||
}
|
||||
|
||||
export function CounterpartiesPage() {
|
||||
|
|
@ -138,9 +139,10 @@ export function CounterpartiesPage() {
|
|||
</Field>
|
||||
<Field label="Роль">
|
||||
<Select value={form.kind} onChange={(e) => setForm({ ...form, kind: Number(e.target.value) as CounterpartyKind })}>
|
||||
<option value={CounterpartyKind.Unspecified}>Не указано</option>
|
||||
<option value={CounterpartyKind.Supplier}>Поставщик</option>
|
||||
<option value={CounterpartyKind.Customer}>Покупатель</option>
|
||||
<option value={CounterpartyKind.Both}>Оба</option>
|
||||
<option value={CounterpartyKind.Both}>Поставщик + Покупатель</option>
|
||||
</Select>
|
||||
</Field>
|
||||
<Field label="Тип лица">
|
||||
|
|
|
|||
Loading…
Reference in a new issue