feat(vendor): add contact info inheritance from company
Vendors can now override company contact information for specific branding. Fields are nullable - if null, value is inherited from parent company. Database changes: - Add vendor.contact_email, contact_phone, website, business_address, tax_number - All nullable (null = inherit from company) - Alembic migration: 28d44d503cac Model changes: - Add effective_* properties for resolved values - Add get_contact_info_with_inheritance() helper Schema changes: - VendorCreate: Optional contact fields for override at creation - VendorUpdate: Contact fields + reset_contact_to_company flag - VendorDetailResponse: Resolved values + *_inherited flags API changes: - GET/PUT vendor endpoints return resolved contact info - PUT accepts contact overrides (empty string = reset to inherit) - _build_vendor_detail_response helper for consistent responses Service changes: - admin_service.update_vendor handles reset_contact_to_company flag - Empty strings converted to None for inheritance 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,17 @@ class Vendor(Base, TimestampMixin):
|
||||
Boolean, default=False
|
||||
) # Boolean to indicate if the vendor brand is verified
|
||||
|
||||
# ========================================================================
|
||||
# Contact Information (nullable = inherit from company)
|
||||
# ========================================================================
|
||||
# These fields allow vendor-specific branding/identity.
|
||||
# If null, the value is inherited from the parent company.
|
||||
contact_email = Column(String(255), nullable=True) # Override company contact email
|
||||
contact_phone = Column(String(50), nullable=True) # Override company contact phone
|
||||
website = Column(String(255), nullable=True) # Override company website
|
||||
business_address = Column(Text, nullable=True) # Override company business address
|
||||
tax_number = Column(String(100), nullable=True) # Override company tax number
|
||||
|
||||
# ========================================================================
|
||||
# Relationships
|
||||
# ========================================================================
|
||||
@@ -202,6 +213,66 @@ class Vendor(Base, TimestampMixin):
|
||||
domains.append(domain.domain) # Add other active custom domains
|
||||
return domains
|
||||
|
||||
# ========================================================================
|
||||
# Contact Resolution Helper Properties
|
||||
# ========================================================================
|
||||
# These properties return the effective value (vendor override or company fallback)
|
||||
|
||||
@property
|
||||
def effective_contact_email(self) -> str | None:
|
||||
"""Get contact email (vendor override or company fallback)."""
|
||||
if self.contact_email is not None:
|
||||
return self.contact_email
|
||||
return self.company.contact_email if self.company else None
|
||||
|
||||
@property
|
||||
def effective_contact_phone(self) -> str | None:
|
||||
"""Get contact phone (vendor override or company fallback)."""
|
||||
if self.contact_phone is not None:
|
||||
return self.contact_phone
|
||||
return self.company.contact_phone if self.company else None
|
||||
|
||||
@property
|
||||
def effective_website(self) -> str | None:
|
||||
"""Get website (vendor override or company fallback)."""
|
||||
if self.website is not None:
|
||||
return self.website
|
||||
return self.company.website if self.company else None
|
||||
|
||||
@property
|
||||
def effective_business_address(self) -> str | None:
|
||||
"""Get business address (vendor override or company fallback)."""
|
||||
if self.business_address is not None:
|
||||
return self.business_address
|
||||
return self.company.business_address if self.company else None
|
||||
|
||||
@property
|
||||
def effective_tax_number(self) -> str | None:
|
||||
"""Get tax number (vendor override or company fallback)."""
|
||||
if self.tax_number is not None:
|
||||
return self.tax_number
|
||||
return self.company.tax_number if self.company else None
|
||||
|
||||
def get_contact_info_with_inheritance(self) -> dict:
|
||||
"""
|
||||
Get all contact info with inheritance flags.
|
||||
|
||||
Returns dict with resolved values and flags indicating if inherited from company.
|
||||
"""
|
||||
company = self.company
|
||||
return {
|
||||
"contact_email": self.effective_contact_email,
|
||||
"contact_email_inherited": self.contact_email is None and company is not None,
|
||||
"contact_phone": self.effective_contact_phone,
|
||||
"contact_phone_inherited": self.contact_phone is None and company is not None,
|
||||
"website": self.effective_website,
|
||||
"website_inherited": self.website is None and company is not None,
|
||||
"business_address": self.effective_business_address,
|
||||
"business_address_inherited": self.business_address is None and company is not None,
|
||||
"tax_number": self.effective_tax_number,
|
||||
"tax_number_inherited": self.tax_number is None and company is not None,
|
||||
}
|
||||
|
||||
|
||||
class VendorUserType(str, enum.Enum):
|
||||
"""Types of vendor users."""
|
||||
|
||||
Reference in New Issue
Block a user