Some checks failed
Reverts the expandable sub-row design back to a clean one-row-per-member table. All per-store management now happens inside the edit modal. Table: simple 4-column layout (Member | Stores & Roles | Status | Actions) with view + edit buttons. Store badges show orange for pending stores. Edit modal enhanced with per-store cards showing: - Store name, code, and status badge (Active/Pending) - Role dropdown + Update button (for active stores) - Resend invitation button (for pending stores) - Remove from store button - "Remove from all stores" link at bottom Removed: expandedMembers, flattenedRows, toggleMemberExpand, resendStoreInvitation, resendInvitation (member-level). Added: resendForStore, removeFromStore (work inside edit modal). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
45 lines
1.4 KiB
Python
45 lines
1.4 KiB
Python
# app/modules/prospecting/models/prospect_contact.py
|
|
"""
|
|
Contact information for a prospect.
|
|
|
|
Supports both auto-scraped (digital) and manually entered (offline) contacts.
|
|
"""
|
|
|
|
import enum
|
|
|
|
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Text
|
|
from sqlalchemy.orm import relationship
|
|
|
|
from app.core.database import Base
|
|
from models.database.base import TimestampMixin
|
|
|
|
|
|
class ContactType(str, enum.Enum):
|
|
EMAIL = "email"
|
|
PHONE = "phone"
|
|
ADDRESS = "address"
|
|
SOCIAL = "social"
|
|
FORM = "form"
|
|
|
|
|
|
class ProspectContact(Base, TimestampMixin):
|
|
"""Contact information associated with a prospect."""
|
|
|
|
__tablename__ = "prospect_contacts"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
prospect_id = Column(Integer, ForeignKey("prospects.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
|
|
contact_type = Column(String(20), nullable=False)
|
|
value = Column(String(500), nullable=False)
|
|
label = Column(String(100), nullable=True) # e.g., "info", "sales", "main"
|
|
source_url = Column(Text, nullable=True) # Page where contact was found
|
|
source_element = Column(String(100), nullable=True) # e.g., "mailto", "tel", "contact-form"
|
|
|
|
is_validated = Column(Boolean, nullable=False, default=False)
|
|
validation_error = Column(Text, nullable=True)
|
|
is_primary = Column(Boolean, nullable=False, default=False)
|
|
|
|
# Relationships
|
|
prospect = relationship("Prospect", back_populates="contacts")
|