feat: Link Users to Persons (KRS data)
- Add person_id column to users table - Template shows person profile link when person_id exists - Add script to match and link users to persons by name Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1207a188f5
commit
f174f4d4da
@ -182,6 +182,8 @@ class User(Base, UserMixin):
|
|||||||
company_nip = Column(String(10))
|
company_nip = Column(String(10))
|
||||||
company_id = Column(Integer, ForeignKey('companies.id'), nullable=True)
|
company_id = Column(Integer, ForeignKey('companies.id'), nullable=True)
|
||||||
company = relationship('Company', backref='users', lazy='joined') # eager load to avoid DetachedInstanceError
|
company = relationship('Company', backref='users', lazy='joined') # eager load to avoid DetachedInstanceError
|
||||||
|
person_id = Column(Integer, ForeignKey('people.id'), nullable=True)
|
||||||
|
person = relationship('Person', backref='users', lazy='joined') # Link to Person (KRS data)
|
||||||
phone = Column(String(50))
|
phone = Column(String(50))
|
||||||
|
|
||||||
# Status
|
# Status
|
||||||
|
|||||||
80
scripts/link_users_to_persons.py
Normal file
80
scripts/link_users_to_persons.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Link Users to Persons based on name matching.
|
||||||
|
Adds person_id column to users table and links users to their Person records.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Load .env first
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from sqlalchemy import text
|
||||||
|
from database import SessionLocal, User, Person
|
||||||
|
|
||||||
|
def main():
|
||||||
|
db = SessionLocal()
|
||||||
|
|
||||||
|
# Step 1: Add person_id column if not exists
|
||||||
|
try:
|
||||||
|
db.execute(text("""
|
||||||
|
ALTER TABLE users
|
||||||
|
ADD COLUMN IF NOT EXISTS person_id INTEGER REFERENCES people(id)
|
||||||
|
"""))
|
||||||
|
db.commit()
|
||||||
|
print("✓ Kolumna person_id dodana (lub już istnieje)")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Uwaga przy dodawaniu kolumny: {e}")
|
||||||
|
db.rollback()
|
||||||
|
|
||||||
|
# Step 2: Get all users with names
|
||||||
|
users = db.query(User).filter(User.name.isnot(None)).all()
|
||||||
|
print(f"\nZnaleziono {len(users)} użytkowników z nazwami")
|
||||||
|
|
||||||
|
# Step 3: Get all persons
|
||||||
|
persons = db.query(Person).all()
|
||||||
|
print(f"Znaleziono {len(persons)} osób w bazie KRS")
|
||||||
|
|
||||||
|
# Build a lookup dict for persons by full name (lowercase)
|
||||||
|
person_lookup = {}
|
||||||
|
for p in persons:
|
||||||
|
full_name = f"{p.imiona} {p.nazwisko}".lower().strip()
|
||||||
|
person_lookup[full_name] = p
|
||||||
|
# Also try just first name + last name (first word of imiona)
|
||||||
|
first_name = p.imiona.split()[0] if p.imiona else ""
|
||||||
|
short_name = f"{first_name} {p.nazwisko}".lower().strip()
|
||||||
|
if short_name not in person_lookup:
|
||||||
|
person_lookup[short_name] = p
|
||||||
|
|
||||||
|
# Step 4: Match users to persons
|
||||||
|
matched = 0
|
||||||
|
for user in users:
|
||||||
|
if user.person_id:
|
||||||
|
print(f" {user.name} - już powiązany z person_id={user.person_id}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
user_name = user.name.lower().strip()
|
||||||
|
|
||||||
|
if user_name in person_lookup:
|
||||||
|
person = person_lookup[user_name]
|
||||||
|
user.person_id = person.id
|
||||||
|
matched += 1
|
||||||
|
print(f" ✓ {user.name} → Person #{person.id} ({person.full_name()})")
|
||||||
|
else:
|
||||||
|
print(f" ✗ {user.name} - brak dopasowania")
|
||||||
|
|
||||||
|
if matched > 0:
|
||||||
|
db.commit()
|
||||||
|
print(f"\n✓ Powiązano {matched} użytkowników z osobami")
|
||||||
|
else:
|
||||||
|
print("\nBrak nowych powiązań do zapisania")
|
||||||
|
|
||||||
|
db.close()
|
||||||
|
print("Gotowe!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@ -265,19 +265,22 @@
|
|||||||
<div class="attendees-list">
|
<div class="attendees-list">
|
||||||
{% for attendee in event.attendees|sort(attribute='user.name') %}
|
{% for attendee in event.attendees|sort(attribute='user.name') %}
|
||||||
<div class="attendee-badge">
|
<div class="attendee-badge">
|
||||||
{% if attendee.user.company %}
|
{# Person badge - link to person profile if person_id exists #}
|
||||||
<a href="{{ url_for('company_detail_by_slug', slug=attendee.user.company.slug) }}" class="attendee-name">
|
{% if attendee.user.person_id %}
|
||||||
|
<a href="{{ url_for('person_detail', person_id=attendee.user.person_id) }}" class="attendee-name">
|
||||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||||
<circle cx="12" cy="7" r="4"></circle>
|
<circle cx="12" cy="7" r="4"></circle>
|
||||||
</svg>
|
</svg>
|
||||||
{{ attendee.user.name or attendee.user.email.split('@')[0] }}
|
{{ attendee.user.name or attendee.user.email.split('@')[0] }}
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('company_detail_by_slug', slug=attendee.user.company.slug) }}" class="attendee-company">
|
{% elif attendee.user.company %}
|
||||||
|
<a href="{{ url_for('company_detail_by_slug', slug=attendee.user.company.slug) }}" class="attendee-name">
|
||||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||||
<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v5m-4 0h4"></path>
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||||
|
<circle cx="12" cy="7" r="4"></circle>
|
||||||
</svg>
|
</svg>
|
||||||
{{ attendee.user.company.name }}
|
{{ attendee.user.name or attendee.user.email.split('@')[0] }}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="attendee-name">
|
<span class="attendee-name">
|
||||||
@ -288,6 +291,16 @@
|
|||||||
{{ attendee.user.name or attendee.user.email.split('@')[0] }}
|
{{ attendee.user.name or attendee.user.email.split('@')[0] }}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{# Company badge - always link to company profile #}
|
||||||
|
{% if attendee.user.company %}
|
||||||
|
<a href="{{ url_for('company_detail_by_slug', slug=attendee.user.company.slug) }}" class="attendee-company">
|
||||||
|
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||||
|
<path d="M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v5m-4 0h4"></path>
|
||||||
|
</svg>
|
||||||
|
{{ attendee.user.company.name }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user