Diagrama de classes — Membership, User e UserProfile

TLDR: Modelo de dados do núcleo de filiação: User, UserProfile, Membership e o que orbita cada um (grupo de filiação, procedimento administrativo, remessa de carteira, moderação de perfil).

Visão geral

```mermaid classDiagram class User { +String email +String encrypted_password +String name +String doc_number +String person_type +String phone_number +Boolean admin +String provider +String uid +String roles +DateTime created_at +DateTime updated_at – +active_memberships() Array +confirmed?() Boolean +confirmation_required?() Boolean +phone_number() String +phone_number_flat() String }

class UserProfile {
    +BigInt user_id
    +String full_name
    +String phone
    +Text about
    +Text contacts
    +Text availability
    +String address
    +String address_zipcode
    +String address_number
    +String address_complement
    +String address_neighborhood
    +String address_city
    +String address_state
    +String address_country
    +DateTime admin_approved_at
    +BigInt admin_approved_by_id
    +String documentation_status
    +String approval_type
    +DateTime created_at
    +DateTime updated_at
    --
    +enum documentation_status {pending, analysis, suspended, ok}
    +enum approval_type {manual, automatic}
    +calculate_documentation_status() Symbol
    +suspended?() Boolean
    +has_any_suspended_membership?() Boolean
    +personal_info_status() Boolean
    +address_info_status() Boolean
    +attachments_status() Boolean
    +address_full() String
    +manual_approve!() void
    +automatic_approve!(approver) void
    +public_serialize() Hash
    +private_serialize() Hash
    -update_cached_fields() void
}

class Membership {
    +BigInt user_id
    +BigInt membership_group_id
    +BigInt register_number
    +Date valid_since
    +Date valid_until
    +String card_status
    +String payment_reference
    +String payment_status
    +Boolean suspended
    +DateTime suspended_at
    +Boolean archived
    +DateTime admin_approved_at
    +BigInt admin_approved_by_id
    +DateTime card_issued_at
    +BigInt card_issued_by_id
    +String documentation_status
    +String card_tracking_code
    +DateTime created_at
    +DateTime updated_at
    --
    +enum documentation_status {pending, analysis, suspended, ok}
    +enum card_status {not_issued, issued, processing, auto_issued}
    +is_valid?() Boolean
    +status() Symbol
    +paid?() Boolean
    +apolo_access_permitted?() Boolean
    +suspend!() void
    +unsuspend!() void
    +is_renewal?() Boolean
    +register_number_pad() String
    +register_number_pad_dot() String
    +valid_until_with_status() String
    +public_serialize() Hash
    +local_documentation_status() String
    -update_cached_information() void
    -validate_register_number_belongs_to_one_person() void
}

class MembershipGroup {
    +String name
    +DateTime created_at
    +DateTime updated_at
}

class AdministrativeProcedure {
    +BigInt admin_id
    +BigInt user_profile_id
    +BigInt membership_id
    +Text body
    +Text short_description
    +String status
    +String complaint_side
    +DateTime created_at
    +DateTime updated_at
}

class Shipment {
    +DateTime created_at
    +DateTime updated_at
}

class ShipmentMembership {
    +BigInt membership_id
    +BigInt shipment_id
    +String shipment_kind
    +Integer status
    +String shipment_track
    +DateTime printed_at
    +DateTime packed_at
    +DateTime sent_at
    +DateTime created_at
    +DateTime updated_at
    --
    +enum shipment_kind {first_time, resend, reprint}
    +enum status {draft, printed, packed, sent}
}

class UserProfileModeration {
    +BigInt user_profile_id
    +BigInt moderated_by_id
    +DateTime created_at
    +DateTime updated_at
}

%% Relações
User "1" --> "*" Membership : has_many
User "1" --> "1" UserProfile : has_one
User "*" --> "*" AdministrativeProcedure : admin_id (has_many)

UserProfile "1" --> "1" User : belongs_to
UserProfile "*" --> "1" User : admin_approved_by (belongs_to)
UserProfile "1" --> "*" AdministrativeProcedure : has_many
UserProfile "1" --> "*" UserProfileModeration : has_many

Membership "*" --> "1" User : belongs_to
Membership "*" --> "1" MembershipGroup : belongs_to
Membership "*" --> "1" User : admin_approved_by (belongs_to)
Membership "*" --> "1" User : card_issued_by (belongs_to)
Membership "1" --> "*" AdministrativeProcedure : has_many
Membership "1" --> "*" ShipmentMembership : has_many

Membership "1" --> "1" UserProfile : has_one (through user)

ShipmentMembership "*" --> "1" Membership : belongs_to
ShipmentMembership "*" --> "1" Shipment : belongs_to
Membership "*" --> "*" Shipment : has_many (through shipment_memberships) ```

Principais Relações

User

  • has_many :memberships - Um usuário pode ter várias filiações
  • has_one :user_profile - Um usuário tem um perfil
  • has_many :administrative_procedures (como admin) - Um admin pode ter vários procedimentos administrativos

UserProfile

  • belongs_to :user - Um perfil pertence a um usuário
  • belongs_to :admin_approved_by (User, optional) - Aprovado por um admin (User)
  • has_many :administrative_procedures - Um perfil pode ter vários procedimentos administrativos
  • has_many :user_profile_moderations - Um perfil pode ter várias moderações
  • has_one_attached :id_file, :id_back_file, :address_confirmation_file, :membership_picture_file - Arquivos anexados

Membership

  • belongs_to :user - Uma filiação pertence a um usuário
  • belongs_to :membership_group - Uma filiação pertence a um grupo
  • belongs_to :admin_approved_by (User, optional) - Aprovado por um admin
  • belongs_to :card_issued_by (User, optional) - Cartão emitido por um admin
  • has_one :user_profile (through: :user) - Acessa o perfil através do usuário
  • has_many :administrative_procedures - Uma filiação pode ter vários procedimentos administrativos
  • has_many :shipment_memberships - Uma filiação pode estar em vários envios
  • has_many :shipments (through: :shipment_memberships) - Envios através da tabela de junção
  • has_one_attached :card_picture - Foto do cartão anexada

Enums

Membership

  • documentation_status: pending, analysis, suspended, ok
  • card_status: not_issued, issued, processing, auto_issued — issued e auto_issued contam como carteira efetivamente emitida (Membership::ISSUED_CARD_STATUSES), ver R-004

UserProfile

  • documentation_status: pending, analysis, suspended, ok
  • approval_type: manual, automatic

ShipmentMembership

  • shipment_kind: first_time, resend ("re-send"), reprint — único por (shipment_id, membership_id), ver spec
  • status: draft, printed, packed, sent

Métodos Principais

User

  • active_memberships - Retorna filiações ativas do usuário
  • phone_number - Retorna o telefone do perfil ou do usuário

UserProfile

  • calculate_documentation_status - Calcula o status da documentação
  • suspended? - Verifica se está suspenso
  • personal_info_status - Verifica se informações pessoais estão completas
  • attachments_status - Verifica se todos os anexos foram enviados
  • manual_approve! - Zera a aprovação e marca approval_type como manual (o nome engana)
  • automatic_approve!(approver) - Aprova o perfil automaticamente, registrando quem aprovou

Membership

  • is_valid? - Verifica se a filiação está válida
  • status - Retorna o status (:suspended, :payment_issues, :expired, :active)
  • paid? - Verifica se o pagamento está pago
  • apolo_access_permitted? - Verifica se tem acesso ao Apolo
  • suspend! / unsuspend! - Suspende/reativa a filiação (usam update!, então levantam em falha de validação)
  • is_renewal? - Verifica se é uma renovação

Referências