fix(web): EAN-13 контрольная цифра, валюты в приёмке сканированием, поиск товара на накладной

1) digitsChecksum считал веса слева — для 12-значного тела (EAN-13) чётность
переворачивалась и контрольная цифра была неверной; теперь справа налево
(EAN-8/UPC-A не изменились). 2) SupplyScanPage читал /api/catalog/currencies как
массив, а это PagedResult {items} → список валют пуст (нет KZT). 3) InvoiceReviewPage
слал ?q=, а API ждёт ?search= (PagedRequest.Search).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nns 2026-10-08 02:10:11 +05:00
parent 839fcaf9fc
commit 009a9d8a50
3 changed files with 16 additions and 8 deletions

View file

@ -6,12 +6,15 @@
import { BarcodeType } from '@/lib/types'
function digitsChecksum(first: string, weightAtOdd: number): number {
// Общая EAN/UPC-подобная формула: сумма с чередующимися весами, остаток от 10.
// Нечётные позиции (с индекса 0) — weightAtOdd, чётные — 1.
// Контрольная цифра EAN/UPC: веса идут СПРАВА НАЛЕВО (цифра перед контрольной
// имеет вес 3, затем 1,3,1…). Нельзя привязывать вес к индексу слева: для
// чётной длины тела (EAN-13 = 12 цифр) чётность переворачивается и check-digit
// получается неверным. Для нечётной длины (EAN-8=7, UPC-A=11) результат тот же.
let sum = 0
for (let i = 0; i < first.length; i++) {
const d = first.charCodeAt(i) - 48
sum += i % 2 === 0 ? d * weightAtOdd : d
let w = weightAtOdd
for (let i = first.length - 1; i >= 0; i--) {
sum += (first.charCodeAt(i) - 48) * w
w = w === weightAtOdd ? 1 : weightAtOdd
}
return (10 - (sum % 10)) % 10
}

View file

@ -595,7 +595,9 @@ function ProductSearchDialog({ q, onClose, onPick }: {
queryKey: ['product-search', query],
queryFn: async () => {
if (query.trim().length < 2) return []
const { data } = await api.get<{ items: ProductSearchHit[] }>(`/api/catalog/products?q=${encodeURIComponent(query)}&pageSize=20`)
// API ждёт параметр `search` (PagedRequest.Search), а не `q` — иначе
// фильтр игнорируется и поиск товара на экране накладной не работает.
const { data } = await api.get<{ items: ProductSearchHit[] }>(`/api/catalog/products?search=${encodeURIComponent(query)}&pageSize=20`)
return data.items ?? []
},
enabled: query.trim().length >= 2,

View file

@ -65,8 +65,11 @@ export function SupplyScanPage() {
const main = r.data.items?.find(s => s.isMain) ?? r.data.items?.[0]
if (main) setStoreId(main.id)
})
api.get<Currency[]>('/api/catalog/currencies?pageSize=20').then(r => {
const list = Array.isArray(r.data) ? r.data : []
// /api/catalog/currencies отдаёт PagedResult {items,...}, а не голый массив —
// раньше Array.isArray(r.data) давал пустой список валют, и черновик приёмки
// сканированием не сохранялся (нет currencyId, в т.ч. KZT по умолчанию).
api.get<{ items: Currency[] }>('/api/catalog/currencies?pageSize=20').then(r => {
const list = r.data?.items ?? []
setCurrencies(list)
const kzt = list.find(c => c.code === 'KZT') ?? list[0]
if (kzt) setCurrencyId(kzt.id)