Users - Serializers

Location: api/nextango/apps/users/serializers.py Last Updated: 2026-07-08

Overview

Two families of serializer cover the Users domain: nested role serializers used inside UserSerializer for a single-request view of a user and their roles, and standalone role serializers used for direct CRUD against a role model. Both read and write the same underlying Employee/Customer/Manager/Influencer/Vip models; the standalone versions additionally surface user_name and user_email so a role list view does not need a second lookup.

UserSerializer

Exposes User model fields plus four computed fields sourced from user_roles_data (primary_role, all_roles, roles_count, primary_role_data) and five computed fields sourced from the role models (employee_roles, customer_roles, manager_roles, influencer_roles, vip_roles), each rendered through the matching nested role serializer below.

Read-only fields: id, created_date, is_staff, is_superuser. The last two are set only through a manager role's adminAccess data, never directly by an API client.

Writing user_roles_data validates that the value is an array of objects, each carrying a _type from the five valid Sanity role types (roleEmployee, roleCustomer, roleManager, roleInfluencer, roleVip). A successful update that includes user_roles_data calls sync_roles_to_model_records() afterward so the role models stay current.

Nested Role Serializers

Used inside UserSerializer's employee_roles / customer_roles / etc. fields. Each resolves Sanity ID references embedded in its model's JSONFields to Django IDs, in a single batched query rather than one lookup per reference, logging unresolved IDs as a warning (they indicate a record that has not synced yet, not necessarily an error).

SerializerModelKey fieldsNotes
EmployeeRoleSerializerEmployeeemployee_id, pin_code (write-only), hourly_rate, commission_rate, store_assignments, hire_datestore_assignments resolves Sanity store references to Django store UUIDs
CustomerRoleSerializerCustomerloyalty_points, store_credit (read-only), wishlist, marketing_opt_in, preferred_store, order_history (read-only)preferred_store and wishlist resolve to Django UUIDs
ManagerRoleSerializerManageremployee_id, pin_code (write-only), hourly_rate, department, reporting_level, override_permissions, reports_to, store_assignmentsoverride_permissions is validated against a fixed whitelist (canOverridePrice, canIssueRefund, canOverrideDiscount)
InfluencerRoleSerializerInfluencersocial_handle, commission_rate, follower_count, discount_codeNo custom validation
VipRoleSerializerVipvip_tier, personal_shopper_id, exclusive_access, special_discount_rateexclusive_access is validated against a fixed whitelist (earlyProductAccess, privateSales, vipEvents, conciergeService)

store_credit and order_history on CustomerRoleSerializer are read-only because they are computed (store_credit from Customer.recalculate_store_credit()) or transaction-managed rather than directly editable.

Standalone Role Serializers

EmployeeSerializer, CustomerSerializer, ManagerSerializer, InfluencerSerializer, VipSerializer back the deprecated role-specific ViewSets (see Views). Each includes the same fields as its nested counterpart plus user, user_name, and user_email. Validation on store_assignments and override_permissions in the standalone versions checks only that the value is an array; the nested versions' Sanity-reference-shape and whitelist checks are not repeated here, so a write through a standalone serializer accepts a looser payload than the same write through UserSerializer.

Writing a standalone role serializer updates the role model directly; it does not currently propagate the change back into the parent user's user_roles_data, so a client that needs both in sync should write through UserSerializer instead.

UserProductCollectionSerializer

Exposes UserProductCollection with computed owner_name, owner_email, item_count, and a capped items_details (first 50 items, rendered via InventoryLevelSerializer). Cross-field validation enforces that a curation-type collection must be public, and that only curation or staff-pick collections can be is_featured. create() and update() set the M2M items field separately from the scalar fields (a Django M2M requirement) and refresh statistics afterward via update_statistics().

UserProductCollectionWebhookSerializer

A separate serializer for the Sanity webhook path into UserProductCollection, accepting the Sanity camelCase field names (collectionType, isPublic, shareToken, and so on) directly rather than relying on DRF's Meta-model field mapping. Resolves the owner and items Sanity references to Django User and InventoryLevel instances during validation, and exposes to_django_data() to produce a plain dict of snake_case fields ready for objects.create() or an instance update.

Was this page helpful?