Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Add document management routes (upload, download, soft-delete) to board blueprint, link BoardDocument to BoardMeeting via meeting_id FK, add documents section to meeting view template, and include import scripts for meeting 2/2026 data and PDFs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
158 lines
5.2 KiB
Python
158 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Import Board Documents for Meeting 2/2026.
|
|
|
|
Copies PDF files to /data/board-docs/ with UUID filenames and creates
|
|
BoardDocument records linked to the meeting.
|
|
|
|
Prerequisites:
|
|
- Meeting 2/2026 must already exist (run import_board_meeting_2_2026.py first)
|
|
- PDF files must be placed in /tmp/ on the target server:
|
|
/tmp/INPI_NORDABIZNES_PROTOKOL_RADA_2026-02-04.pdf
|
|
/tmp/INPI_NORDABIZNES_LISTA_OBECNOSCI_RADA_2026-02-04.pdf
|
|
|
|
Usage:
|
|
# Local dev:
|
|
python3 scripts/import_board_documents_2_2026.py
|
|
|
|
# Production:
|
|
DATABASE_URL=$(grep DATABASE_URL .env | cut -d'=' -f2) \
|
|
/var/www/nordabiznes/venv/bin/python3 scripts/import_board_documents_2_2026.py
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import uuid
|
|
from datetime import date, datetime
|
|
|
|
# Add project root to path
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from database import SessionLocal, BoardMeeting, BoardDocument, User
|
|
|
|
UPLOAD_BASE = '/data/board-docs'
|
|
|
|
# Source files (expected in /tmp/ after SCP)
|
|
FILES = [
|
|
{
|
|
'source': '/tmp/INPI_NORDABIZNES_PROTOKOL_RADA_2026-02-04.pdf',
|
|
'title': 'Protokół z posiedzenia Rady nr 2/2026',
|
|
'document_type': 'protocol',
|
|
'description': 'Pełny protokół z posiedzenia Rady Izby nr 2/2026 z dnia 04.02.2026',
|
|
'original_filename': 'INPI_NORDABIZNES_PROTOKOL_RADA_2026-02-04.pdf',
|
|
},
|
|
{
|
|
'source': '/tmp/INPI_NORDABIZNES_LISTA_OBECNOSCI_RADA_2026-02-04.pdf',
|
|
'title': 'Lista obecności z podpisami - posiedzenie Rady nr 2/2026',
|
|
'document_type': 'minutes',
|
|
'description': 'Skan listy obecności z fizycznymi podpisami członków Rady',
|
|
'original_filename': 'INPI_NORDABIZNES_LISTA_OBECNOSCI_RADA_2026-02-04.pdf',
|
|
},
|
|
]
|
|
|
|
|
|
def main():
|
|
db = SessionLocal()
|
|
try:
|
|
# Find meeting 2/2026
|
|
meeting = db.query(BoardMeeting).filter(
|
|
BoardMeeting.meeting_number == 2,
|
|
BoardMeeting.year == 2026
|
|
).first()
|
|
|
|
if not meeting:
|
|
print("ERROR: Meeting 2/2026 not found. Run import_board_meeting_2_2026.py first.")
|
|
return False
|
|
|
|
print(f"Found meeting 2/2026 (id={meeting.id})")
|
|
|
|
# Find admin/office_manager as uploader
|
|
uploader = db.query(User).filter(
|
|
User.role.in_(['ADMIN', 'OFFICE_MANAGER']),
|
|
User.is_active == True
|
|
).first()
|
|
|
|
if not uploader:
|
|
print("ERROR: No ADMIN or OFFICE_MANAGER user found.")
|
|
return False
|
|
|
|
print(f"Uploader: {uploader.name} (id={uploader.id})")
|
|
|
|
# Create target directory
|
|
target_dir = os.path.join(UPLOAD_BASE, '2026', '02')
|
|
os.makedirs(target_dir, exist_ok=True)
|
|
print(f"Target directory: {target_dir}")
|
|
|
|
imported = 0
|
|
for file_info in FILES:
|
|
source = file_info['source']
|
|
|
|
# Check if already imported (by title + meeting_id)
|
|
existing = db.query(BoardDocument).filter(
|
|
BoardDocument.meeting_id == meeting.id,
|
|
BoardDocument.title == file_info['title'],
|
|
BoardDocument.is_active == True
|
|
).first()
|
|
|
|
if existing:
|
|
print(f" SKIP: '{file_info['title']}' already exists (id={existing.id})")
|
|
continue
|
|
|
|
# Check source file
|
|
if not os.path.exists(source):
|
|
print(f" WARNING: Source file not found: {source}")
|
|
print(f" SCP the file to the server first:")
|
|
print(f" scp <local-path> maciejpi@<server>:{source}")
|
|
continue
|
|
|
|
# Generate UUID filename
|
|
stored_filename = f"{uuid.uuid4()}.pdf"
|
|
target_path = os.path.join(target_dir, stored_filename)
|
|
|
|
# Copy file
|
|
shutil.copy2(source, target_path)
|
|
file_size = os.path.getsize(target_path)
|
|
|
|
print(f" Copied: {source} -> {target_path} ({file_size} bytes)")
|
|
|
|
# Create database record
|
|
doc = BoardDocument(
|
|
title=file_info['title'],
|
|
description=file_info['description'],
|
|
document_type=file_info['document_type'],
|
|
meeting_id=meeting.id,
|
|
meeting_date=date(2026, 2, 4),
|
|
meeting_number=2,
|
|
original_filename=file_info['original_filename'],
|
|
stored_filename=stored_filename,
|
|
file_extension='pdf',
|
|
file_size=file_size,
|
|
mime_type='application/pdf',
|
|
uploaded_by=uploader.id,
|
|
uploaded_at=datetime(2026, 2, 20, 12, 0),
|
|
)
|
|
db.add(doc)
|
|
db.flush()
|
|
print(f" Created BoardDocument id={doc.id}: '{file_info['title']}'")
|
|
imported += 1
|
|
|
|
db.commit()
|
|
print(f"\nImported {imported} document(s) for meeting 2/2026.")
|
|
return True
|
|
|
|
except Exception as e:
|
|
db.rollback()
|
|
print(f"ERROR: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
success = main()
|
|
if not success:
|
|
sys.exit(1)
|