chore(deploy): SQL-скрипты очистки Демо и исправления внутренних EAN-13
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
stage-reset-demo.sql — очистка орги от транзакционных данных (KEEP каталог/ сотрудники/точки). fix-internal-ean13.sql — пересчёт неверной контрольной цифры у уже выданных внутренних EAN-13 (на стенде исправлен 41 код, список — docs/ean13-fixed-20261008.txt). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
886cb92f30
commit
6f10896d8c
64
deploy/fix-internal-ean13.sql
Normal file
64
deploy/fix-internal-ean13.sql
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
-- deploy/fix-internal-ean13.sql
|
||||||
|
-- Исправление контрольной цифры у внутренних EAN-13 (префикс «2»), которые
|
||||||
|
-- веб-генератор выдавал с НЕверной контрольной цифрой (баг digitsChecksum:
|
||||||
|
-- веса считались слева, а для 12-значного тела чётность переворачивается).
|
||||||
|
-- Фикс генератора — в src/food-market.web/src/lib/barcode.ts; этот скрипт
|
||||||
|
-- чинит УЖЕ ВЫДАННЫЕ коды, не теряя связь с товаром (та же строка product_barcodes,
|
||||||
|
-- тот же ProductId — меняется только последняя цифра Code).
|
||||||
|
--
|
||||||
|
-- Идемпотентно. Пропускает коды, у которых исправленный вариант уже занят
|
||||||
|
-- в этой организации (во избежание нарушения unique(OrganizationId,Code)) —
|
||||||
|
-- такие выводятся отдельно для ручного разбора.
|
||||||
|
--
|
||||||
|
-- Запуск: ssh nns@192.168.1.190 "docker exec -i food-market-stage-postgres \
|
||||||
|
-- psql -U food_market -d food_market" < deploy/fix-internal-ean13.sql
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION pg_temp.ean13_check(body text) RETURNS int AS $f$
|
||||||
|
DECLARE s int := 0; w int := 3; i int;
|
||||||
|
BEGIN
|
||||||
|
IF body !~ '^[0-9]{12}$' THEN RETURN -1; END IF;
|
||||||
|
FOR i IN REVERSE 12..1 LOOP
|
||||||
|
s := s + substr(body,i,1)::int * w;
|
||||||
|
w := CASE WHEN w=3 THEN 1 ELSE 3 END;
|
||||||
|
END LOOP;
|
||||||
|
RETURN (10 - s % 10) % 10;
|
||||||
|
END $f$ LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
|
||||||
|
-- Отчёт: что будет исправлено (старый → новый), с товаром и организацией.
|
||||||
|
SELECT pb."OrganizationId", pb."ProductId", p."Name" AS product,
|
||||||
|
pb."Code" AS old_code,
|
||||||
|
substr(pb."Code",1,12) || pg_temp.ean13_check(substr(pb."Code",1,12))::text AS new_code
|
||||||
|
FROM product_barcodes pb
|
||||||
|
JOIN products p ON p."Id" = pb."ProductId"
|
||||||
|
WHERE pb."Code" ~ '^2[0-9]{12}$'
|
||||||
|
AND substr(pb."Code",13,1)::int <> pg_temp.ean13_check(substr(pb."Code",1,12))
|
||||||
|
ORDER BY pb."OrganizationId", p."Name";
|
||||||
|
|
||||||
|
-- Конфликты: исправленный код уже занят в этой орге — НЕ трогаем.
|
||||||
|
SELECT pb."Code" AS old_code,
|
||||||
|
substr(pb."Code",1,12) || pg_temp.ean13_check(substr(pb."Code",1,12))::text AS new_code,
|
||||||
|
pb."OrganizationId"
|
||||||
|
FROM product_barcodes pb
|
||||||
|
WHERE pb."Code" ~ '^2[0-9]{12}$'
|
||||||
|
AND substr(pb."Code",13,1)::int <> pg_temp.ean13_check(substr(pb."Code",1,12))
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1 FROM product_barcodes x
|
||||||
|
WHERE x."OrganizationId" = pb."OrganizationId"
|
||||||
|
AND x."Code" = substr(pb."Code",1,12) || pg_temp.ean13_check(substr(pb."Code",1,12))::text
|
||||||
|
AND x."Id" <> pb."Id");
|
||||||
|
|
||||||
|
-- Собственно исправление (без конфликтных).
|
||||||
|
UPDATE product_barcodes pb
|
||||||
|
SET "Code" = substr(pb."Code",1,12) || pg_temp.ean13_check(substr(pb."Code",1,12))::text
|
||||||
|
WHERE pb."Code" ~ '^2[0-9]{12}$'
|
||||||
|
AND substr(pb."Code",13,1)::int <> pg_temp.ean13_check(substr(pb."Code",1,12))
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM product_barcodes x
|
||||||
|
WHERE x."OrganizationId" = pb."OrganizationId"
|
||||||
|
AND x."Code" = substr(pb."Code",1,12) || pg_temp.ean13_check(substr(pb."Code",1,12))::text
|
||||||
|
AND x."Id" <> pb."Id");
|
||||||
|
|
||||||
|
-- Контроль: сколько осталось неверных (должно стать = числу конфликтных).
|
||||||
|
SELECT count(*) AS remaining_wrong FROM product_barcodes
|
||||||
|
WHERE "Code" ~ '^2[0-9]{12}$'
|
||||||
|
AND substr("Code",13,1)::int <> pg_temp.ean13_check(substr("Code",1,12));
|
||||||
103
deploy/stage-reset-demo.sql
Normal file
103
deploy/stage-reset-demo.sql
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
-- deploy/stage-reset-demo.sql
|
||||||
|
-- Очистка организации «Демо-магазин» на стенде от ВСЕХ транзакционных данных,
|
||||||
|
-- КРОМЕ каталога (товары/группы/штрихкоды/цены/ед.изм./картинки), сотрудников/
|
||||||
|
-- пользователей/ролей и магазина/точек продаж. По поправке владельца 07.10.2026.
|
||||||
|
--
|
||||||
|
-- Запуск (с обязательной предварительной резервной копией!):
|
||||||
|
-- ssh nns@192.168.1.190 "docker exec -i food-market-stage-postgres \
|
||||||
|
-- psql -U food_market -d food_market -v demo_org=<UUID>" < deploy/stage-reset-demo.sql
|
||||||
|
--
|
||||||
|
-- Идемпотентно. KEEP-таблицы НЕ трогаются. Удаление — только по OrganizationId
|
||||||
|
-- целевой орги; FK-порядок разрешается retry-loop'ом (как в stage-prune-autotest.sql).
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
|
||||||
|
-- psql не подставляет :var внутри dollar-quoted DO-блока, поэтому пробрасываем
|
||||||
|
-- org через GUC и читаем current_setting() внутри блока.
|
||||||
|
SELECT set_config('fm.demo_org', :'demo_org', false);
|
||||||
|
|
||||||
|
DO $do$
|
||||||
|
DECLARE
|
||||||
|
org uuid := current_setting('fm.demo_org')::uuid;
|
||||||
|
keep text[] := ARRAY[
|
||||||
|
-- каталог
|
||||||
|
'products','product_prices','product_barcodes','product_groups','product_images',
|
||||||
|
'org_units_of_measure','price_types',
|
||||||
|
-- сотрудники / пользователи / роли
|
||||||
|
'employees','employee_roles','users','roles',
|
||||||
|
-- магазин и точки продаж
|
||||||
|
'stores','retail_points','employee_retail_point_assignments',
|
||||||
|
-- прочий org-scoped reference, который владелец хочет сохранить
|
||||||
|
'expense_items','user_presets'
|
||||||
|
];
|
||||||
|
tbl text;
|
||||||
|
pass int;
|
||||||
|
remaining int;
|
||||||
|
total_deleted bigint := 0;
|
||||||
|
n bigint;
|
||||||
|
prod_cnt bigint;
|
||||||
|
BEGIN
|
||||||
|
IF org IS NULL THEN
|
||||||
|
RAISE EXCEPTION 'demo_org не задан (psql -v demo_org=...)';
|
||||||
|
END IF;
|
||||||
|
PERFORM 1 FROM organizations WHERE "Id" = org;
|
||||||
|
IF NOT FOUND THEN
|
||||||
|
RAISE EXCEPTION 'Орг % не найдена', org;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RAISE NOTICE 'Очистка Демо-орг % — KEEP % таблиц', org, array_length(keep,1);
|
||||||
|
|
||||||
|
FOR pass IN 1..12 LOOP
|
||||||
|
remaining := 0;
|
||||||
|
FOR tbl IN
|
||||||
|
SELECT c.table_name
|
||||||
|
FROM information_schema.columns c
|
||||||
|
JOIN information_schema.tables t
|
||||||
|
ON t.table_schema=c.table_schema AND t.table_name=c.table_name
|
||||||
|
WHERE c.table_schema='public'
|
||||||
|
AND c.column_name='OrganizationId'
|
||||||
|
AND t.table_type='BASE TABLE'
|
||||||
|
AND c.table_name <> ALL(keep)
|
||||||
|
LOOP
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format('DELETE FROM public.%I WHERE "OrganizationId"=$1', tbl) USING org;
|
||||||
|
GET DIAGNOSTICS n = ROW_COUNT;
|
||||||
|
total_deleted := total_deleted + n;
|
||||||
|
EXCEPTION WHEN foreign_key_violation THEN
|
||||||
|
remaining := remaining + 1;
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
EXIT WHEN remaining = 0;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
IF remaining <> 0 THEN
|
||||||
|
RAISE EXCEPTION 'Остались неудалённые таблицы из-за FK после 12 проходов (remaining=%)', remaining;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT count(*) INTO prod_cnt FROM products WHERE "OrganizationId"=org;
|
||||||
|
RAISE NOTICE 'Удалено строк: %, товаров осталось: %', total_deleted, prod_cnt;
|
||||||
|
END $do$;
|
||||||
|
|
||||||
|
-- Контроль: документы и остатки должны быть 0, каталог/сотрудники/точки целы.
|
||||||
|
SELECT 'products' m, count(*) v FROM products WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'product_prices', count(*) FROM product_prices WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'product_barcodes', count(*) FROM product_barcodes WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'product_groups', count(*) FROM product_groups WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'employees', count(*) FROM employees WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'users', count(*) FROM users WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'stores', count(*) FROM stores WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'retail_points', count(*) FROM retail_points WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'supplies', count(*) FROM supplies WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'retail_sales', count(*) FROM retail_sales WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'stocks', count(*) FROM stocks WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'stock_movements', count(*) FROM stock_movements WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'money_accounts', count(*) FROM money_accounts WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'money_transactions', count(*) FROM money_transactions WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'cash_shifts', count(*) FROM cash_shifts WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'enters', count(*) FROM enters WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'losses', count(*) FROM losses WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'inventories', count(*) FROM inventories WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'invoice_uploads', count(*) FROM invoice_uploads WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'counterparties', count(*) FROM counterparties WHERE "OrganizationId"=:'demo_org'
|
||||||
|
UNION ALL SELECT 'org_audit_log', count(*) FROM org_audit_log WHERE "OrganizationId"=:'demo_org'
|
||||||
|
ORDER BY m;
|
||||||
43
docs/ean13-fixed-20261008.txt
Normal file
43
docs/ean13-fixed-20261008.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
OrganizationId | ProductId | product | old_code | new_code
|
||||||
|
--------------------------------------+--------------------------------------+--------------------------------------+---------------+---------------
|
||||||
|
02a0ba90-0efb-4856-8922-bc90db46032c | 989779be-8c27-4787-8140-4f94dcdb156b | Товар 1 | 2774151174816 | 2774151174818
|
||||||
|
2030055a-1c1e-414e-ac0e-591ebfb27134 | 3edb0b3d-1992-4544-92b6-f5d4a4acd3c3 | Товар 1 | 2322682989291 | 2322682989298
|
||||||
|
241c01d6-319e-42f7-b678-a3d257040d8d | b4d60653-355e-4f52-8b89-9528b9883a52 | Товар 1 | 2989387437553 | 2989387437556
|
||||||
|
2b8ad716-844a-4ccc-8634-1f7054aff4f2 | cb3fec1b-94bf-46a6-9ef3-6a060279f9dd | Товар 1 | 2573011570966 | 2573011570964
|
||||||
|
2d6f1727-649c-4517-8750-4c1055fcd1b8 | ccd8f9f8-551a-4d5a-b500-45d6fe81fec6 | Товар 1 | 2777942088706 | 2777942088707
|
||||||
|
2df1e315-111d-4fb5-8416-d540400ee96e | 3c6c724b-38bd-4bfe-990c-d899b55ffef0 | Товар 1 | 2221311034961 | 2221311034968
|
||||||
|
3d88118f-12ca-491b-ae8b-54889d656217 | 6f0e1fa2-5bdc-4d1e-a4b8-4ea7cd42b1eb | Товар 1 | 2319153165810 | 2319153165817
|
||||||
|
40f09e9d-fce5-4e9b-a25c-1c9c9422b4c3 | de430ffe-b939-4478-8cdb-cf618507f6f2 | Товар 1 | 2778342543970 | 2778342543971
|
||||||
|
43eaa2ec-cdf5-4599-9ea9-de02bd7b7f02 | 57fee67e-1907-4ea3-ab63-efc19966d93f | Товар 1 | 2641783270397 | 2641783270396
|
||||||
|
565819c6-6821-4367-89cf-ac08fd5b8bce | 164f9409-5bb0-4f1d-ae2d-14b57d87cd5e | Товар 1 | 2104944436773 | 2104944436777
|
||||||
|
5744895d-8f8f-4521-a171-8d01a45c9716 | 8207ad35-7321-41ba-bd83-42fe869a57f9 | Товар 1 | 2454147839196 | 2454147839197
|
||||||
|
5ae2d7aa-1e3c-4ab9-8f37-e432c37059bd | 4644bda1-e8c1-49f1-aa4d-e587d8417822 | Товар 1 | 2773341942620 | 2773341942626
|
||||||
|
5c739483-4cf0-4a84-abc9-e5abc2d9498c | a3de6b46-2583-42b9-a149-5c5c1cde44bb | Товар 1 | 2141394451683 | 2141394451684
|
||||||
|
68d55389-9240-48f1-924b-5fcaef582662 | dfe0af38-8273-44e4-af2b-1863373ac7a8 | Товар 1 | 2802175321220 | 2802175321229
|
||||||
|
6da240a9-ed19-422e-a8ff-3e88319411bc | 6005300f-a165-460c-97f5-d0bd5dd82744 | Товар 1 | 2172174489121 | 2172174489122
|
||||||
|
7353187f-af3d-4218-b0b3-b48af77efedc | 3c7f28cb-edef-4ed8-be7f-b5b9acd54217 | Товар 1 | 2975569597001 | 2975569597002
|
||||||
|
82f94765-c378-4eec-80e8-15e1f1216315 | e2cec8e4-9be1-4314-ad61-782dad5135a0 | Товар 1 | 2908501111892 | 2908501111899
|
||||||
|
8404e55e-d325-4c11-9576-9c733c107afb | d38a0cde-db35-468f-8e65-3c038a980e15 | Товар 1 | 2561410176365 | 2561410176368
|
||||||
|
88a1b10b-9006-4dbf-8010-c86833e3226e | 833451f0-eb3e-445d-9672-f501ed98d73e | Товар 1 | 2971275425507 | 2971275425509
|
||||||
|
89262cea-977b-4097-8e78-fc34e25244de | a981266c-d936-4af6-ab29-fbce3313ec00 | Товар 1 | 2022774230099 | 2022774230092
|
||||||
|
8bbb43a0-711f-46d9-a8bb-0f4f0d633ed5 | 681c6c8e-a808-47d7-8d50-9115d6a78395 | Товар 1 | 2166137596314 | 2166137596316
|
||||||
|
929b00b1-cdef-4c72-a1d2-ec48a79c0e50 | 2648291a-9181-497d-b9d5-57852f2e1806 | Товар 1 | 2650860255151 | 2650860255157
|
||||||
|
9aea0e38-cb74-4983-b6f6-b1389620cdfd | e7c5c371-a4a2-40db-9f90-6ff413d9ffa0 | Товар 3 | 2800124503582 | 2800124503580
|
||||||
|
9b22f3cf-46cd-4388-8d39-62da0bec7377 | 2f4441dc-2a94-4a2c-ade6-5c270ad48a86 | Товар 1 | 2769454863444 | 2769454863446
|
||||||
|
9b5593c0-7415-4347-aaf6-7908af63e075 | f4b50e3c-e63a-4c4d-9c3f-2c32a552102a | Товар 2 | 2732219120138 | 2732219120139
|
||||||
|
a70c0d6f-b99b-41bf-b12e-56c733c55202 | 5a857b3b-57c8-4460-8ad7-9f6eaee0ce97 | Товар 1 | 2630344841029 | 2630344841021
|
||||||
|
ab3ba17b-e1c7-4779-b4da-7a6f74fab877 | 5952aac2-0aaa-4e6b-8f73-88c3980f5a76 | Товар 1 | 2479429060400 | 2479429060403
|
||||||
|
b72b5ccf-8b86-41d5-87a5-c69b0ead6c6d | 8e721005-feaf-432e-8ebb-34efac5a7503 | Товар 1 | 2181329206711 | 2181329206712
|
||||||
|
b7c403fe-7fc8-48af-9490-4a9a2eafe2c2 | d93afc1e-ea27-461f-afea-16d409e88468 | Тунец натуральный 240 гр Fish master | 2000000399788 | 2000000399782
|
||||||
|
bf4466f7-2c50-4ca9-8be7-7db2a1dc96d2 | f290ea9b-41f8-485f-8f06-024e2dd67d04 | Товар 1 | 2526982373876 | 2526982373874
|
||||||
|
d1fe3292-a167-4c63-9944-eed29c7494a7 | ea6a9db6-581c-4b5e-a011-9d92c5d903f7 | Товар 1 | 2400138194244 | 2400138194240
|
||||||
|
db7ff78b-1755-4388-bc73-8dde9546279c | 001f8390-fade-4e50-8942-cbe8700e8647 | Товар 1 | 2121043372681 | 2121043372683
|
||||||
|
dcd787cd-3209-4c57-a88e-e17d8bd567da | 4d2f3b56-c73b-49e4-a6f2-1402af486e54 | Товар 1 | 2091076032522 | 2091076032529
|
||||||
|
e1057e0f-493b-458a-ac63-2b0d3b005ce2 | 7a74794c-d672-4e63-afc8-a59e9cafb50b | Товар 1 | 2422506372305 | 2422506372302
|
||||||
|
e166d264-2b56-4fee-8aeb-2c650f0b9e32 | ca3f24ec-ce67-4402-bda0-108205f1e6aa | Товар 1 | 2191353131442 | 2191353131447
|
||||||
|
f158b0b8-6266-4574-bbb0-6cfe2333962b | 2aec0165-42a9-4088-a48d-0b786a367d8d | Товар 3 | 2893012813027 | 2893012813021
|
||||||
|
f4018fd4-041a-4e72-8204-e091ecbfb9b8 | e5ace923-0c5f-4b35-bf8d-559275bd6247 | Товар 2 | 2544714677075 | 2544714677076
|
||||||
|
f44b79c5-e617-4aa4-aeab-b4b2f7d05a7a | ab0ca323-51e9-4242-a0b5-b2833bb7782b | Товар 1 | 2965763672860 | 2965763672865
|
||||||
|
f80269c4-5702-4d67-a56f-5f9e871094a7 | e939a60b-30bb-44d7-9fc6-f7208e318c55 | Товар 1 | 2276824292069 | 2276824292060
|
||||||
|
fbc3505d-585e-47ac-ae91-9339907233a3 | f7ca3aab-10ec-4fb0-8130-f2b29234a225 | Товар 2 | 2021646806852 | 2021646806854
|
||||||
|
fc966697-a6c5-4a74-b5a2-54bdac02f5e6 | 0fbacfc8-dea8-46dc-8927-3e455c1438a0 | Товар 1 | 2718687983533 | 2718687983537
|
||||||
Loading…
Reference in a new issue