From 0f8631bf20aea84b835b5cd3e84205b6d0b575af Mon Sep 17 00:00:00 2001 From: Fedor Date: Sun, 30 Nov 2025 11:37:16 +0300 Subject: [PATCH] =?UTF-8?q?fix(backend):=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B0=D0=BB=D0=B3=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D0=BC=20hash=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=BC=D0=B5=D1=81=D1=82=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D1=81=20JS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Использован ctypes.c_int32 для эмуляции JS 32-битного сдвига - Теперь Python hash совпадает с JS hash в n8n - Кэширование form_draft работает корректно --- ticket_form/backend/app/api/documents.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/ticket_form/backend/app/api/documents.py b/ticket_form/backend/app/api/documents.py index ea2a44ee..0723247f 100644 --- a/ticket_form/backend/app/api/documents.py +++ b/ticket_form/backend/app/api/documents.py @@ -614,14 +614,25 @@ async def generate_documents_list(request: Request): def compute_documents_hash(doc_ids: List[str]) -> str: - """Вычисляет hash от списка document_id для проверки актуальности черновика""" + """ + Вычисляет hash от списка document_id для проверки актуальности черновика. + Должен совпадать с JS алгоритмом в n8n build_form_draft. + """ + import ctypes + sorted_ids = sorted([d for d in doc_ids if d]) hash_input = ','.join(sorted_ids) - # Используем простой hash как в n8n (djb2) + + # djb2 hash — эмуляция JS поведения + # В JS: (hash << 5) возвращает 32-битный signed int hash_val = 5381 for char in hash_input: - hash_val = ((hash_val << 5) + hash_val) + ord(char) - return format(abs(hash_val) & 0xFFFFFFFF, 'x').zfill(8) + # ctypes.c_int32 эмулирует JS 32-битный signed int при сдвиге + shifted = ctypes.c_int32(hash_val << 5).value + hash_val = shifted + hash_val + ord(char) + + # В JS: Math.abs(hash).toString(16).padStart(8, '0') + return format(abs(hash_val), 'x').zfill(8) @router.post("/check-ocr-status")