feat: implement company-based ownership architecture
- Add database migration to make vendor.owner_user_id nullable - Update Vendor model to support company-based ownership (DEPRECATED vendor.owner_user_id) - Implement company_service with singleton pattern (consistent with vendor_service) - Create Company model with proper relationships to vendors and users - Add company exception classes for proper error handling - Refactor companies API to use singleton service pattern Architecture Change: - OLD: Each vendor has its own owner (vendor.owner_user_id) - NEW: Vendors belong to a company, company has one owner (company.owner_user_id) - This allows one company owner to manage multiple vendor brands Technical Details: - Company service uses singleton pattern (not factory) - Company service accepts db: Session as parameter (follows SVC-003) - Uses AuthManager for password hashing (consistent with admin_service) - Added _generate_temp_password() helper method
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
"""make_vendor_owner_user_id_nullable_for_company_ownership
|
||||
|
||||
Revision ID: 5818330181a5
|
||||
Revises: d0325d7c0f25
|
||||
Create Date: 2025-12-01 20:30:06.158027
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '5818330181a5'
|
||||
down_revision: Union[str, None] = 'd0325d7c0f25'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""
|
||||
Make vendor.owner_user_id nullable to support company-level ownership.
|
||||
|
||||
Architecture Change:
|
||||
- OLD: Each vendor has its own owner (vendor.owner_user_id)
|
||||
- NEW: Vendors belong to a company, company has one owner (company.owner_user_id)
|
||||
|
||||
This allows one company owner to manage multiple vendor brands.
|
||||
"""
|
||||
# Use batch operations for SQLite compatibility
|
||||
with op.batch_alter_table('vendors', schema=None) as batch_op:
|
||||
batch_op.alter_column('owner_user_id',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=True)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""
|
||||
Revert vendor.owner_user_id to non-nullable.
|
||||
|
||||
WARNING: This will fail if there are vendors without owner_user_id!
|
||||
"""
|
||||
# Use batch operations for SQLite compatibility
|
||||
with op.batch_alter_table('vendors', schema=None) as batch_op:
|
||||
batch_op.alter_column('owner_user_id',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=False)
|
||||
Reference in New Issue
Block a user