docid 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
docid-0.1.3/PKG-INFO ADDED
@@ -0,0 +1,566 @@
1
+ Metadata-Version: 2.4
2
+ Name: docid
3
+ Version: 0.1.3
4
+ Summary: Deterministyczny generator identyfikatorów dokumentów z OCR
5
+ Home-page: https://github.com/softreck/docid
6
+ Author: Softreck
7
+ Author-email: Softreck <info@softreck.dev>
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/softreck/docid
10
+ Project-URL: Documentation, https://github.com/softreck/docid#readme
11
+ Project-URL: Repository, https://github.com/softreck/docid
12
+ Project-URL: Issues, https://github.com/softreck/docid/issues
13
+ Keywords: ocr,document,invoice,ksef,polish,accounting
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ Requires-Dist: pillow>=9.0.0
27
+ Requires-Dist: pdf2image>=1.16.0
28
+ Requires-Dist: numpy>=1.21.0
29
+ Requires-Dist: pytesseract>=0.3.10
30
+ Requires-Dist: opencv-python>=4.5.0
31
+ Requires-Dist: reportlab>=3.6.0
32
+ Requires-Dist: lxml>=4.6.0
33
+ Requires-Dist: beautifulsoup4>=4.9.0
34
+ Requires-Dist: pymupdf>=1.23.0
35
+ Requires-Dist: paddleocr>=2.6.0
36
+ Requires-Dist: paddlepaddle>=2.4.0
37
+ Provides-Extra: paddle
38
+ Requires-Dist: paddleocr>=2.6.0; extra == "paddle"
39
+ Requires-Dist: paddlepaddle>=2.4.0; extra == "paddle"
40
+ Provides-Extra: tesseract
41
+ Requires-Dist: pytesseract>=0.3.10; extra == "tesseract"
42
+ Provides-Extra: all
43
+ Requires-Dist: paddleocr>=2.6.0; extra == "all"
44
+ Requires-Dist: paddlepaddle>=2.4.0; extra == "all"
45
+ Requires-Dist: pytesseract>=0.3.10; extra == "all"
46
+ Provides-Extra: dev
47
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
48
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
49
+ Requires-Dist: black>=23.0.0; extra == "dev"
50
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
51
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
52
+ Requires-Dist: build>=0.10.0; extra == "dev"
53
+ Requires-Dist: twine>=4.0.0; extra == "dev"
54
+ Dynamic: author
55
+ Dynamic: home-page
56
+ Dynamic: requires-python
57
+
58
+ # EXEF Document ID Generator
59
+
60
+ Deterministyczny generator identyfikatorów dokumentów z OCR. Generuje **zawsze ten sam ID** dla tego samego dokumentu, niezależnie od formatu źródłowego (skan, PDF, KSeF XML, obrazy).
61
+
62
+ ## 🎯 Problem
63
+
64
+ Masz fakturę w trzech formatach:
65
+ - Skan JPG z telefonu
66
+ - PDF z emaila
67
+ - XML z KSeF
68
+
69
+ Jak uzyskać **ten sam identyfikator** dla wszystkich trzech?
70
+
71
+ ## ✨ Rozwiązanie
72
+
73
+ ```python
74
+ from exef_docid import get_document_id
75
+
76
+ # Wszystkie trzy zwrócą TEN SAM ID!
77
+ get_document_id("faktura_skan.jpg") # EXEF-FV-A7B3C9D2E1F04856
78
+ get_document_id("faktura.pdf") # EXEF-FV-A7B3C9D2E1F04856
79
+ get_document_id("faktura_ksef.xml") # EXEF-FV-A7B3C9D2E1F04856
80
+ ```
81
+
82
+ ## 📦 Instalacja
83
+
84
+ ### Lokalna instalacja (rekomendowana)
85
+
86
+ ```bash
87
+ # Klonuj repozytorium
88
+ git clone https://github.com/softreck/exef-pl.git
89
+ cd exef-pl/app/docid
90
+
91
+ # Utwórz środowisko wirtualne
92
+ python3 -m venv venv
93
+ source venv/bin/activate # Linux/Mac
94
+ # lub venv\Scripts\activate # Windows
95
+
96
+ # Zainstaluj projekt
97
+ make install
98
+ ```
99
+
100
+ ### Z PaddleOCR (zalecane dla CPU i5+)
101
+
102
+ ```bash
103
+ pip install docid[paddle]
104
+ ```
105
+
106
+ ### Z Tesseract (lżejsza alternatywa)
107
+
108
+ ```bash
109
+ # Ubuntu/Debian
110
+ sudo apt install tesseract-ocr tesseract-ocr-pol
111
+
112
+ # Pakiet Python
113
+ pip install docid[tesseract]
114
+ ```
115
+
116
+ ### Wszystkie silniki OCR
117
+
118
+ ```bash
119
+ pip install docid[all]
120
+ ```
121
+
122
+ ## 🚀 Szybki start
123
+
124
+ ### Generator ID dla dokumentów biznesowych
125
+
126
+ ```python
127
+ from exef_docid import generate_invoice_id, generate_receipt_id, generate_contract_id
128
+
129
+ # Faktura VAT
130
+ invoice_id = generate_invoice_id(
131
+ seller_nip="5213017228",
132
+ invoice_number="FV/2025/00142",
133
+ issue_date="2025-01-15",
134
+ gross_amount=1230.50
135
+ )
136
+ print(invoice_id) # EXEF-FV-F0BE35240C77B2DB
137
+
138
+ # Paragon fiskalny
139
+ receipt_id = generate_receipt_id(
140
+ seller_nip="5213017228",
141
+ receipt_date="2025-01-15",
142
+ gross_amount=37.88,
143
+ cash_register_number="001"
144
+ )
145
+ print(receipt_id) # EXEF-PAR-8142B3FC69D7778C
146
+
147
+ # Umowa
148
+ contract_id = generate_contract_id(
149
+ party1_nip="5213017228",
150
+ party2_nip="1234567890",
151
+ contract_date="2025-01-15",
152
+ contract_number="001/2025"
153
+ )
154
+ print(contract_id) # EXEF-UMO-C54CB968D1342642
155
+ ```
156
+
157
+ ### Uniwersalny generator ID (dowolne dokumenty)
158
+
159
+ ```python
160
+ from exef_docid import generate_universal_document_id
161
+
162
+ # Dowolny dokument
163
+ doc_id = generate_universal_document_id("dokument.pdf")
164
+ print(doc_id) # UNIV-PDF-A6BECE56B7FE21DC
165
+
166
+ # Zdjęcie lub skan
167
+ doc_id = generate_universal_document_id("skan.jpg")
168
+ print(doc_id) # UNIV-IMG-4225A473A725978D
169
+
170
+ # Dokument z grafiką/wektorami
171
+ doc_id = generate_universal_document_id("grafika.png")
172
+ print(doc_id) # UNIV-IMG-E2E2131A335F0918
173
+ ```
174
+
175
+ ### Pełne przetwarzanie z OCR
176
+
177
+ ```python
178
+ from exef_docid import process_document, get_document_id
179
+
180
+ # Pełne przetwarzanie z ekstrakcją danych
181
+ result = process_document("faktura.pdf")
182
+ print(result.document_id) # EXEF-FV-F0BE35240C77B2DB
183
+ print(result.extraction.issuer_nip) # 5213017228
184
+ print(result.extraction.invoice_number) # FV/2025/00142
185
+
186
+ # Tylko wygeneruj ID
187
+ doc_id = get_document_id("paragon.jpg")
188
+ print(doc_id) # EXEF-PAR-8142B3FC69D7778C
189
+
190
+ # Weryfikacja ID
191
+ is_valid = verify_document_id("skan.png", "EXEF-FV-F0BE35240C77B2DB")
192
+ print(is_valid) # True/False
193
+ ```
194
+
195
+ ## 🖥️ Interfejs CLI (docid-universal)
196
+
197
+ Projekt dostarcza potężne narzędzie CLI `docid-universal`, które udostępnia wszystkie funkcjonalności pakietu.
198
+
199
+ ### Podstawowe komendy
200
+
201
+ ```bash
202
+ # Generowanie ID dla faktury (dane ręczne)
203
+ docid-universal generate invoice --nip 5213017228 --number FV/2025/00142 --date 2025-01-15 --amount 1230.50
204
+
205
+ # Generowanie uniwersalnego ID dla pliku
206
+ docid-universal universal dokument.pdf
207
+
208
+ # Przetwarzanie dokumentu z OCR i ekstrakcją danych
209
+ docid-universal process samples/invoices/faktura_full.jpg --format json
210
+
211
+ # Analiza cech pliku (rozmiar, hashe, metadane)
212
+ docid-universal analyze samples/invoices/faktura_full.png
213
+
214
+ # Porównanie dwóch dokumentów
215
+ docid-universal compare samples/invoices/faktura_full.jpg samples/invoices/faktura_full.pdf
216
+ ```
217
+
218
+ ### Przetwarzanie wsadowe (Batch)
219
+
220
+ Możesz przetworzyć cały folder dokumentów i automatycznie wykryć duplikaty:
221
+
222
+ ```bash
223
+ docid-universal batch ./scany --recursive --duplicates --output wyniki.json
224
+ ```
225
+
226
+ ### Testowanie determinizmu
227
+
228
+ Sprawdź, czy generator zwraca zawsze ten sam ID dla tego samego pliku:
229
+
230
+ ```bash
231
+ docid-universal test faktura.pdf --iterations 10
232
+ ```
233
+
234
+ ## 🌐 Usługa Web (REST API)
235
+
236
+ Możesz łatwo uruchomić `docid` jako usługę webową (wymaga `fastapi` i `uvicorn`):
237
+
238
+ ### Uruchomienie serwera
239
+ ```bash
240
+ make run-web
241
+ # Serwer wystartuje na http://localhost:8000
242
+ ```
243
+
244
+ ### Przykłady CURL
245
+
246
+ **1. Generowanie ID z pliku:**
247
+ ```bash
248
+ curl -X POST -F "file=@faktura.pdf" http://localhost:8000/process
249
+ ```
250
+
251
+ **2. Weryfikacja ID:**
252
+ ```bash
253
+ curl -X POST -F "file=@skan.jpg" -F "document_id=EXEF-FV-F0BE35240C77B2DB" http://localhost:8000/verify
254
+ ```
255
+
256
+ **3. Porównywanie plików:**
257
+ ```bash
258
+ curl -X POST -F "file1=@plik1.pdf" -F "file2=@plik2.png" http://localhost:8000/compare
259
+ ```
260
+
261
+ ## 🧪 Testy Jakości i OCR
262
+
263
+ Pakiet zawiera zaawansowane narzędzia do testowania odporności ID na zniekształcenia obrazu (szumy, kompresja stratna).
264
+
265
+ ### Test odporności na szumy
266
+ ```bash
267
+ # Testuje determinizm ID przy dodawaniu szumu, rozmycia i zmianie jasności
268
+ python examples/quality_test.py samples/invoices/faktura_full.png --noise --iterations 5
269
+ ```
270
+
271
+ ### Test formatów stratnych (JPG vs PNG)
272
+ ```bash
273
+ # Sprawdza czy ID pozostaje spójne mimo kompresji stratnej
274
+ python examples/quality_test.py samples/invoices/faktura_full.png --formats
275
+ ```
276
+
277
+ ### Uruchomienie przez Makefile
278
+ ```bash
279
+ make test-quality FILE=samples/invoices/faktura_full.png
280
+ ```
281
+
282
+ ## 🛠️ Makefile - Wszystkie komendy
283
+
284
+ ### Instalacja i Budowanie
285
+ ```bash
286
+ make install # Instalacja projektu
287
+ make install-all # Instalacja z wszystkimi zależnościami OCR
288
+ make build # Budowanie paczki (wymaga 'build')
289
+ make upload # Publikacja na PyPI (wymaga 'twine')
290
+ ```
291
+
292
+ ### Testy i Narzędzia
293
+ ```bash
294
+ make test # Uruchom wszystkie testy
295
+ make test-cli # Test interfejsu CLI
296
+ make test-universal # Test dokumentów uniwersalnych
297
+ make test-quality FILE=plik.png # Test jakości OCR
298
+ make run-web # Uruchom serwer API
299
+ ```
300
+
301
+ ## 📚 Przykłady użycia
302
+
303
+ ### 1. Przetwarzanie faktur
304
+
305
+ ```python
306
+ from exef_docid import process_document
307
+
308
+ # Przetwarzanie faktury PDF
309
+ result = process_document("faktura.pdf")
310
+ print(f"ID: {result.document_id}")
311
+ print(f"NIP: {result.extraction.issuer_nip}")
312
+ print(f"Kwota: {result.extraction.gross_amount}")
313
+
314
+ # Przetwarzanie skanu JPG
315
+ result = process_document("skan_faktury.jpg")
316
+ print(f"ID: {result.document_id}")
317
+ ```
318
+
319
+ ### 2. Porównywanie dokumentów
320
+
321
+ ```python
322
+ from exef_docid import compare_universal_documents
323
+
324
+ # Porównaj dwa dokumenty
325
+ comparison = compare_universal_documents("dokument1.pdf", "dokument2.png")
326
+ print(f"Identyczne ID: {comparison['identical_ids']}")
327
+ print(f"Ten sam typ: {comparison['same_type']}")
328
+ print(f"Ten sam rozmiar: {comparison['same_size']}")
329
+ ```
330
+
331
+ ### 3. Weryfikacja ID
332
+
333
+ ```python
334
+ from exef_docid import verify_document_id, verify_universal_document_id
335
+
336
+ # Weryfikacja ID dokumentu biznesowego
337
+ is_valid = verify_document_id("faktura.pdf", "EXEF-FV-F0BE35240C77B2DB")
338
+
339
+ # Weryfikacja uniwersalnego ID
340
+ is_valid = verify_universal_document_id("dowolny_plik.jpg", "UNIV-IMG-4225A473A725978D")
341
+ ```
342
+
343
+ ### 4. Praca z kolekcją dokumentów
344
+
345
+ ```python
346
+ from pathlib import Path
347
+ from exef_docid import generate_universal_document_id
348
+
349
+ # Przetwarzaj wszystkie pliki w folderze
350
+ documents_dir = Path("dokumenty")
351
+ for file_path in documents_dir.glob("*"):
352
+ if file_path.is_file():
353
+ doc_id = generate_universal_document_id(file_path)
354
+ print(f"{file_path.name}: {doc_id}")
355
+ ```
356
+
357
+ ## 🔍 Formaty plików i przetwarzanie
358
+
359
+ ### Obsługiwane formaty
360
+
361
+ | Format | Opis | Przetwarzanie | ID Generator |
362
+ |--------|------|---------------|--------------|
363
+ | **PDF** | Dokumenty PDF | ✅ Pełne | Uniwersalny |
364
+ | **PNG** | Obrazy bezstratne | ✅ OCR + Wizualne | Oba |
365
+ | **JPG/JPEG** | Obrazy stratne | ✅ OCR + Wizualne | Oba |
366
+ | **XML** | Struktura danych | ✅ Tekst | Biznesowy |
367
+ | **HTML** | Strony WWW | ✅ Tekst | Biznesowy |
368
+ | **TXT** | Czysty tekst | ✅ Tekst | Biznesowy |
369
+
370
+ ### 📝 PNG i JPG - Przetwarzanie przez OCR
371
+
372
+ **TAK!** Formaty PNG i JPG są w pełni przetwarzane przez OCR:
373
+
374
+ ```python
375
+ from exef_docid import process_document
376
+
377
+ # Przetwarzanie skanu PNG z OCR
378
+ result = process_document("skan_faktury.png")
379
+ print(result.document_id) # EXEF-FV-F0BE35240C77B2DB
380
+ print(result.extraction.issuer_nip) # 5213017228
381
+
382
+ # Przetwarzanie zdjęcia JPG z OCR
383
+ result = process_document("zdjecie_paragonu.jpg")
384
+ print(result.document_id) # EXEF-PAR-8142B3FC69D7778C
385
+ ```
386
+
387
+ #### Co jest ekstrahowane z PNG/JPG:
388
+
389
+ 1. **OCR (PaddleOCR/Tesseract)**:
390
+ - Tekst z dokumentów
391
+ - NIP, numery faktur
392
+ - Kwoty, daty
393
+ - Struktura dokumentu
394
+
395
+ 2. **Analiza wizualna (Uniwersalny generator)**:
396
+ - Hash wizualny (resize 64x64)
397
+ - Histogram kolorów
398
+ - Wymiary obrazu
399
+ - Metadane pliku
400
+
401
+ ### Przykłady dla różnych formatów
402
+
403
+ ```python
404
+ # Ten sam dokument w różnych formatach - ten sam ID biznesowy
405
+ generate_invoice_id(...) # -> EXEF-FV-F0BE35240C77B2DB
406
+
407
+ # Przetwarzanie przez OCR daje ten sam wynik
408
+ process_document("faktura.pdf") # -> EXEF-FV-F0BE35240C77B2DB
409
+ process_document("faktura.png") # -> EXEF-FV-F0BE35240C77B2DB
410
+ process_document("faktura.jpg") # -> EXEF-FV-F0BE35240C77B2DB
411
+ process_document("faktura.xml") # -> EXEF-FV-F0BE35240C77B2DB
412
+
413
+ # Różne ID uniwersalne dla różnych formatów
414
+ generate_universal_document_id("faktura.pdf") # -> UNIV-PDF-...
415
+ generate_universal_document_id("faktura.png") # -> UNIV-IMG-...
416
+ generate_universal_document_id("faktura.jpg") # -> UNIV-IMG-...
417
+ ```
418
+
419
+ ## 🧪 Testowanie
420
+
421
+ ### Uruchomienie testów
422
+
423
+ ```bash
424
+ # Wszystkie testy
425
+ make test
426
+
427
+ # Testy deterministyczności
428
+ make test-samples
429
+
430
+ # Testy formatów
431
+ make test-complete-formats
432
+
433
+ # Testy uniwersalne
434
+ make test-universal
435
+ ```
436
+
437
+ ### Struktura testów
438
+
439
+ ```
440
+ tests/
441
+ ├── test_document_id.py # Testy generatora ID
442
+ ├── test_extractors.py # Testy ekstrakcji danych
443
+ └── conftest.py # Konfiguracja testów
444
+ ```
445
+
446
+ ### Przykładowe wyniki testów
447
+
448
+ ```
449
+ ================================================================================
450
+ TEST WSZYSTKICH FORMATÓW - PDF, PNG, JPG, HTML, TXT, XML
451
+ ================================================================================
452
+
453
+ FOLDER: FAKTURY (invoices/)
454
+ 📄 faktura_full.pdf (.pdf ) [ 2242B] -> EXEF-FV-F0BE35240C77B2DB
455
+ 📄 faktura_full.xml (.xml ) [ 2077B] -> EXEF-FV-F0BE35240C77B2DB
456
+ 📄 faktura_full.html (.html) [ 3334B] -> EXEF-FV-F0BE35240C77B2DB
457
+ 📄 faktura_full.jpg (.jpg ) [ 28182B] -> EXEF-FV-F0BE35240C77B2DB
458
+ 📄 faktura_full.png (.png ) [ 32325B] -> EXEF-FV-F0BE35240C77B2DB
459
+ 📄 faktura_full.txt (.txt ) [ 2839B] -> EXEF-FV-F0BE35240C77B2DB
460
+
461
+ 📊 Podsumowanie folderu invoices:
462
+ Plików przetworzonych: 6
463
+ Unikalnych ID: 1
464
+ Wszystkie identyczne: True
465
+ ✅ ID: EXEF-FV-F0BE35240C77B2DB
466
+ ```
467
+
468
+ ## 📁 Struktura projektu
469
+
470
+ ```
471
+ docid/
472
+ ├── exef_docid/ # Główny pakiet
473
+ │ ├── __init__.py # Eksporty API
474
+ │ ├── document_id.py # Generator ID biznesowy
475
+ │ ├── document_id_universal.py # Generator ID uniwersalny
476
+ │ ├── extractors.py # Ekstraktory danych
477
+ │ ├── ocr_processor.py # Przetwarzanie OCR
478
+ │ └── pipeline.py # Główny pipeline
479
+ ├── samples/ # Przykładowe dokumenty
480
+ │ ├── invoices/ # Faktury (6 formatów)
481
+ │ ├── receipts/ # Paragony (6 formatów)
482
+ │ ├── contracts/ # Umowy (6 formatów)
483
+ │ └── universal/ # Dokumenty uniwersalne
484
+ ├── tests/ # Testy jednostkowe
485
+ ├── examples/ # Przykłady użycia
486
+ ├── Makefile # Komendy projektu
487
+ ├── pyproject.toml # Konfiguracja projektu
488
+ └── README.md # Dokumentacja
489
+ ```
490
+
491
+ ## 🔧 Konfiguracja
492
+
493
+ ### Silniki OCR
494
+
495
+ ```python
496
+ from exef_docid import OCREngine, get_pipeline
497
+
498
+ # Użyj PaddleOCR (domyślnie)
499
+ pipeline = get_pipeline(ocr_engine=OCREngine.PADDLE)
500
+
501
+ # Użyj Tesseract
502
+ pipeline = get_pipeline(ocr_engine=OCREngine.TESSERACT)
503
+ ```
504
+
505
+ ### Custom prefix
506
+
507
+ ```python
508
+ from exef_docid import UniversalDocumentIDGenerator
509
+
510
+ generator = UniversalDocumentIDGenerator(prefix="MOJA")
511
+ doc_id = generator.generate_universal_id("plik.pdf")
512
+ # Wynik: MOJA-PDF-A6BECE56B7FE21DC
513
+ ```
514
+
515
+ ## 📈 Wydajność
516
+
517
+ ### Czas przetwarzania
518
+
519
+ | Format | Rozmiar | Czas | Metoda |
520
+ |--------|--------|------|--------|
521
+ | PDF (tekst) | 10KB | ~50ms | Bez OCR |
522
+ | PDF (skan) | 1MB | ~500ms | OCR |
523
+ | PNG (600x400) | 50KB | ~200ms | OCR |
524
+ | JPG (1200x800) | 200KB | ~300ms | OCR |
525
+
526
+ ### Optymalizacja
527
+
528
+ ```python
529
+ # Wyłącz OCR dla czystych PDF
530
+ result = process_document("czysty_pdf.pdf", use_ocr=False)
531
+
532
+ # Użyj cache dla wielokrotnego przetwarzania
533
+ pipeline = get_pipeline()
534
+ pipeline.enable_cache = True
535
+ ```
536
+
537
+ ## 🤝 Współpraca
538
+
539
+ 1. Fork repozytorium
540
+ 2. Utwórz branch (`git checkout -b feature/NowaFunkcja`)
541
+ 3. Commit zmiany (`git commit -am 'Dodaj nową funkcję'`)
542
+ 4. Push do brancha (`git push origin feature/NowaFunkcja`)
543
+ 5. Otwórz Pull Request
544
+
545
+ ## 📄 Licencja
546
+
547
+ MIT License - zobacz [LICENSE](LICENSE) dla szczegółów.
548
+
549
+ ## 🆘 Wsparcie
550
+
551
+ - 📧 Email: info@softreck.dev
552
+ - 🐛 Issues: [GitHub Issues](https://github.com/softreck/exef-pl/issues)
553
+ - 📖 Dokumentacja: [GitHub Wiki](https://github.com/softreck/exef-pl/wiki)
554
+
555
+ ## 🗺️ Roadmap
556
+
557
+ - [ ] Obsługa dodatkowych formatów (DOCX, XLSX)
558
+ - [ ] Integracja z bazami danych
559
+ - [ ] API REST
560
+ - [ ] Interfejs webowy
561
+ - [ ] Przetwarzanie wsadowe
562
+ - [ ] Chmura (AWS, Azure, GCP)
563
+
564
+ ---
565
+
566
+ **EXEF Document ID Generator** - Deterministyczne identyfikatory dla każdego dokumentu! 🚀