feat: complete KRS data import with all available fields
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

Map remaining KRS API fields: registration date, company agreement date,
duration, capital currency, OPP status, representation rules, shareholders
(wspólnicy), and financial reports (sprawozdania finansowe).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-02-20 13:58:35 +01:00
parent b5458b69fc
commit cbe3cd3f6e

View File

@ -17,7 +17,7 @@ from . import bp
from database import (
SessionLocal, MembershipApplication, CompanyDataRequest,
Company, Category, User, UserNotification, Person, CompanyPerson, CompanyPKD,
SystemRole, UserCompany
CompanyFinancialReport, SystemRole, UserCompany
)
from krs_api_service import get_company_from_krs
from utils.decorators import role_required
@ -25,6 +25,21 @@ from utils.decorators import role_required
logger = logging.getLogger(__name__)
def _parse_krs_date(date_str):
"""Parse KRS date format 'DD.MM.YYYY' to Python date. Returns None on failure."""
if not date_str:
return None
# Extract first date-like pattern (handles "25.10.2011 R. - ASESOR..." format)
import re as _re
match = _re.search(r'(\d{2})\.(\d{2})\.(\d{4})', date_str)
if match:
try:
return date(int(match.group(3)), int(match.group(2)), int(match.group(1)))
except ValueError:
return None
return None
def _generate_slug(name):
"""Generate URL-safe slug from company name."""
slug = re.sub(r'[^\w\s-]', '', name.lower())
@ -124,6 +139,35 @@ def _enrich_company_from_krs(company, db):
kapital = data_dict.get('kapital', {})
if kapital.get('zakladowy'):
company.capital_amount = kapital['zakladowy']
if kapital.get('waluta'):
company.capital_currency = kapital['waluta']
# Representation rules
if data_dict.get('sposob_reprezentacji'):
company.krs_representation_rules = data_dict['sposob_reprezentacji']
# Registration date
daty = data_dict.get('daty', {})
if daty.get('rejestracji'):
parsed = _parse_krs_date(daty['rejestracji'])
if parsed:
company.krs_registration_date = parsed
# Company agreement (umowa spółki)
umowa = data_dict.get('umowa_spolki', {})
if umowa.get('data_umowy'):
parsed = _parse_krs_date(umowa['data_umowy'])
if parsed:
company.krs_company_agreement_date = parsed
if umowa.get('czas_trwania'):
company.krs_duration = umowa['czas_trwania']
# OPP status
if 'czy_opp' in data_dict:
company.is_opp = bool(data_dict['czy_opp'])
# Last audit timestamp
company.krs_last_audit_at = datetime.now()
# Primary PKD on Company model
pkd_list = data_dict.get('przedmiot_dzialalnosci', [])
@ -191,6 +235,77 @@ def _enrich_company_from_krs(company, db):
)
db.add(cpkd)
# Import shareholders (wspólnicy)
for wspolnik in data_dict.get('wspolnicy', []):
nazwisko = wspolnik.get('nazwisko', '')
imiona = wspolnik.get('imiona', wspolnik.get('imie', ''))
if not nazwisko:
continue
person = db.query(Person).filter(
Person.nazwisko == nazwisko,
Person.imiona == imiona
).first()
if not person:
person = Person(nazwisko=nazwisko, imiona=imiona)
db.add(person)
db.flush()
existing = db.query(CompanyPerson).filter(
CompanyPerson.company_id == company.id,
CompanyPerson.person_id == person.id,
CompanyPerson.role_category == 'wspolnik'
).first()
if not existing:
cp = CompanyPerson(
company_id=company.id,
person_id=person.id,
role=wspolnik.get('funkcja', 'WSPÓLNIK'),
role_category='wspolnik',
shares_count=wspolnik.get('liczba_udzialow'),
shares_value=wspolnik.get('wartosc_udzialow'),
source='ekrs.ms.gov.pl',
fetched_at=datetime.now()
)
db.add(cp)
# Import financial reports (sprawozdania finansowe)
for sf in data_dict.get('sprawozdania_finansowe', []):
za_okres = sf.get('za_okres', '')
data_zlozenia = sf.get('data_zlozenia', '')
period_start = None
period_end = None
if ' - ' in za_okres:
parts = za_okres.split(' - ')
period_start = _parse_krs_date(parts[0].strip())
period_end = _parse_krs_date(parts[1].strip())
filed = _parse_krs_date(data_zlozenia)
if not period_start and not period_end:
continue
existing = db.query(CompanyFinancialReport).filter(
CompanyFinancialReport.company_id == company.id,
CompanyFinancialReport.period_start == period_start,
CompanyFinancialReport.period_end == period_end
).first()
if not existing:
cfr = CompanyFinancialReport(
company_id=company.id,
period_start=period_start,
period_end=period_end,
filed_at=filed,
report_type='annual',
source='ekrs'
)
db.add(cfr)
logger.info(f"Enriched company {company.id} with KRS data")
return True