Accounts Models =============== User ---- Extends Django's ``AbstractUser`` to add phone, role, zone, and availability tracking. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Field - Type - Constraints - Description * - id - UUIDField - PK, default=uuid4 - Primary key * - username - CharField(150) - unique, not null - Inherited from AbstractUser * - email - EmailField - unique, nullable - User email address * - phone - CharField(15) - unique, not null - Primary contact number * - role - ForeignKey(Role) - not null, on_delete=PROTECT - User's system role * - zone - ForeignKey(Zone) - nullable, on_delete=SET_NULL - Geographic zone assignment (required for field_team) * - is_available - BooleanField - default=True - Current availability for field assignments * - created_at - DateTimeField - auto_now_add - Account creation timestamp * - updated_at - DateTimeField - auto_now - Last modification timestamp **Indexes**: ``phone``, ``role``, ``zone``, ``is_available`` Role ---- Defines the seven system roles. Uses Django's permission framework for granular access control. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Field - Type - Constraints - Description * - id - AutoField - PK - Primary key * - name - CharField(50) - unique, choices - One of: ``oem``, ``customer``, ``central_ops``, ``field_team``, ``procurement``, ``finance``, ``oem_reporting`` * - description - TextField - blank - Human-readable role description * - permissions - ManyToManyField(Permission) - blank - Django permissions associated with this role Team ---- Groups of field team users operating within a geographic zone. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Field - Type - Constraints - Description * - id - UUIDField - PK, default=uuid4 - Primary key * - name - CharField(100) - not null - Team display name * - zone - ForeignKey(Zone) - not null, on_delete=PROTECT - Operating zone * - team_type - CharField(20) - choices: ``survey``, ``installation``, ``both`` - Team specialization * - is_active - BooleanField - default=True - Whether team is operational **Indexes**: ``zone``, ``team_type``, ``is_active`` TeamMembership -------------- Join table linking users to teams with a position. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Field - Type - Constraints - Description * - id - AutoField - PK - Primary key * - user - ForeignKey(User) - not null, on_delete=CASCADE - Team member * - team - ForeignKey(Team) - not null, on_delete=CASCADE - Team * - role_in_team - CharField(20) - choices: ``lead``, ``member`` - Position within team * - joined_at - DateTimeField - auto_now_add - When user joined the team **Unique constraint**: ``(user, team)`` Zone ---- Geographic service areas that scope teams, stock, and vendor availability. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Field - Type - Constraints - Description * - id - AutoField - PK - Primary key * - name - CharField(100) - unique, not null - Zone name (city/district) * - state - CharField(100) - not null - State/province * - is_active - BooleanField - default=True - Whether zone is currently serviceable