Skip to content

feat: adiciona username e banner ao usuario - #12

Merged
Megueutu merged 2 commits into
mainfrom
feat/user-profile-fields
Sep 11, 2026
Merged

Megueutu merged 2 commits into
mainfrom
feat/user-profile-fields

Conversation

@Megueutu

@Megueutu Megueutu commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Objetivo

Dar a todo usuário a capacidade de ter avatar, banner de perfil e um
username/handle (@user) público, distinto do nome legal em person.name.
De quebra: auditei db/core/db/auth inteiros contra as entidades reais de
api-core/api-auth, corrigi o que estava fora de sincronia, e coloquei o
make dataload para efetivamente funcionar — populando coredb e authdb
juntos, com dados em português e corretos (CPF/CNPJ com dígito verificador
válido, texto livre vindo de bancos de frases curados em vez de lorem
pseudo-latino do Faker). Isso desbloqueia consumir os dados no
databricks-sync/databricks-analytics.

PR irmã em api-core: Solierrr/api-core#52
(adiciona username/banner na entidade User, já que db/core/schema.sql
se declara reconstruído a partir das entidades reais — sem isso as colunas
novas ficariam sem correspondência real).

Alterações

Schema (users) + auditoria completa db/core/db/auth

  • db/core/schema.sql + migrations/V1__create_core_schema.sql: adiciona
    users.username (VARCHAR(30), UNIQUE, CHECK ~ '^[a-z0-9_]{3,30}$')
    e users.banner (VARCHAR(255), mesmo padrão do avatar já existente).
  • Rodei uma auditoria coluna-a-coluna de db/core/db/auth inteiros contra
    as entidades JPA reais de api-core/api-auth. db/auth bateu 100% (uma
    cópia fiel da migration Flyway real). db/core tinha 4 colunas declaradas
    como TEXT que na entidade real (sem columnDefinition) são
    VARCHAR(255) por padrão do Hibernate: position.accesses,
    professional_review.comment, proposal.notes,
    unit_specifications.specifications/location_photos — corrigido para
    bater com o banco real.

scripts/dataload.py — reescrita para funcionar de ponta a ponta

  • Bug de arquitetura: o script rodava todos os passos (auth e core
    misturados) numa única conexão psycopg2 — mas auth_user e afins vivem
    em authdb, users e o resto em coredb, dois bancos Postgres
    fisicamente separados. Seeder agora recebe a conexão por fase
    (use_connection); main() roda AUTH_STEPS contra authdb, comita, e
    só depois roda CORE_STEPS contra coredb (que referencia os
    auth_user.id já gerados).
  • Colunas/tabelas fictícias: vários self.insert(...) referenciavam
    tabelas que nunca existiram (media_asset, company_photo, model_photo,
    local_unit_photo, offer_service_region, offer_translation,
    session_authentication_method — MFA na verdade é um TEXT[] direto em
    auth_session.authentication_methods) ou colunas erradas (fk_user em
    vez de user_id/fk_users, fk_sessionsession_id,
    fk_replaced_byreplaced_by_id, fk_accepted_byaccepted_by,
    id_position/id_permission trocados, model.width/length em vez de
    dimension, company.business_type/slug, offer.slug/
    discount_percentage/etc., technician.slug,
    energy_bill.photo_url/photo_public_id — nenhuma dessas colunas existe
    no schema real). Removido/corrigido tudo; validei com um dry-run completo
    (mock de conexão) rodando as 50 tabelas sem exceção, e um script que
    compara cada self.insert() contra as colunas reais de db/core +
    db/auth — 0 mismatches.
  • recompute_proposal_totals chamava fn_proposal_total(), uma function
    que nunca existiu (db/core/procedures está vazio) — trocado por uma
    agregação SQL direta (proposal_item x offer).
  • Dados corretos e em português: cpf/cnpj agora usam
    Faker.cpf()/Faker.cnpj() (dígito verificador válido) em vez de dígitos
    aleatórios. FAKE.bs() (inglês) e FAKE.text()/FAKE.sentence() (lorem
    pseudo-latino, mesmo com locale pt_BR) foram trocados por bancos de
    frases em português curados (scripts/data/catalog/certification_name.csv,
    certification_description.csv, technical_service_purpose.csv,
    review_comment.csv, business_note.csv, security_event_note.csv) via
    novo helper pick_text().

CSVs de imagem — banner único e fallback seguro

  • media_pool() não levanta mais erro em CSV vazio; pick_media() cai num
    placeholder do Faker enquanto o CSV não for preenchido.
  • hero.csv/company_banner.csv viraram um único banner.csv, populado
    com 50 imagens do Unsplash (paisagem urbana, natureza, espaço, animais,
    oceano — 10 de cada) já enviadas para o Cloudinary (cloud solaria,
    pasta console), consumido tanto por users.banner quanto (quando
    company ganhar banner) por empresa.
  • unit_specifications.location_photos (campo real, antes só
    FAKE.url() genérico) agora usa unit_specifications_photos.csv.

Makefile + scripts/connection.py

  • scripts/connection.py usava um esquema de env vars (CORE_HOST,
    AUTH_NAME, etc.) que não existe em .env.examplemake dataload
    quebrava na conexão. Agora reusa exatamente as mesmas variáveis
    HOST/PORT/USER/PASSWORD/ENVIRONMENT que o Makefile já usa,
    construindo o nome do banco do mesmo jeito ($(TARGET)$(SUFIX)).
    scripts/databases.py (o mapeamento antigo, que também estava errado)
    foi removido.
  • make dataload não recebe mais TARGET: como uma execução sempre
    popula os dois bancos juntos (dependência users.auth_id
    auth_user.id), não fazia sentido escolher um banco só.

Fora de escopo (mantido de propósito)

  • offer_translation/company_photo/model_photo/etc. eram tabelas
    fictícias — removi as chamadas em vez de desenhar esse schema do zero,
    já que ninguém pediu multi-idioma de oferta ou fotos de empresa/modelo
    ainda. Se quiser essa funcionalidade, é um schema novo (fora do pedido
    original de usuário).
  • Não toquei nos bugs pré-existentes do Makefile fora de dataload
    (migrate aponta pra migrations/ na raiz em vez de db/$(TARGET)/migrations/;
    reset cria um banco $(TARGET) que não é o mesmo que $(TARGET)$(SUFIX)
    usado no resto) — sinalizados numa conversa anterior, não pedidos agora.

Tipo de mudança

  • Schema (tabela/coluna/constraint)
  • View
  • Function/Procedure
  • Trigger
  • Índice
  • Dataload/seed

Banco(s) afetado(s)

coredb e authdb (o dataload agora sempre popula os dois juntos)

É destrutiva ou difícil de reverter?

Não é destrutiva (só adiciona colunas/corrige tipos e arquivos de dados).
users.username é NOT NULL; num banco com dados reais pré-existentes o
ALTER TABLE equivalente precisaria de backfill — não se aplica a um banco
criado do zero via schema.sql.

Como validar

make schema TARGET=core && make enums TARGET=core && make seed TARGET=core
make schema TARGET=auth && make enums TARGET=auth && make seed TARGET=auth
make dataload ROWS=50

Não tive acesso a um Postgres válido neste ambiente para rodar de ponta a
ponta contra um banco real (tentei, autenticação falhou). Validei tudo que
dava para validar sem banco: sintaxe Python, dry-run completo das 50 tabelas
com conexão mockada (0 exceções), comparação automatizada de cada
self.insert() contra as colunas reais de db/core + db/auth (0
mismatches), 2000 usernames gerados contra o regex do CHECK, geração de
CPF/CNPJ com dígito verificador válido. Recomendo fortemente rodar o passo
acima contra um banco real antes do merge.

Copilot AI lite review requested due to automatic review settings September 11, 2026 13:27
@Megueutu
Megueutu requested a review from maykitw1 as a code owner September 11, 2026 13:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
40.0% Duplication on New Code (required ≤ 3%)
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Megueutu
Megueutu merged commit 385ca6d into main Sep 11, 2026
1 check failed
@Megueutu
Megueutu deleted the feat/user-profile-fields branch September 11, 2026 13:29
@Megueutu

Copy link
Copy Markdown
Contributor Author

Atualização: validei tudo contra um Postgres real (subi um container Postgres 16 descartável só pra isso, credenciais via infra-platform/scripts/extract-env.ps1).

Rodei enums → schema → seed → indexes para core e auth, depois python -m scripts.dataload 50tudo aplicou/rodou sem erro, nos dois bancos.

Aproveitei e confirmei a convenção real de nome de banco contra os secrets do Infisical: só qa usa sufixo (coredbqa/authdbqa, banco compartilhado com prod no mesmo host Aiven) — local e prod usam o nome puro (coredb/authdb), cada um no seu próprio host. O Makefile/connection.py tratavam local igual a qa (sufixo errado), então make schema local nunca teria batido com o banco local de verdade. Corrigido no último commit, junto com dois bugs que eu já tinha sinalizado antes (migrate sem o prefixo db/$(TARGET)/, e reset tentando DROP DATABASE estando conectado nele mesmo).

Conferi os dados inseridos: username minúsculo, CPF/CNPJ com dígito verificador válido, textos em português (certificação, propósito de serviço), proposal.total_amount calculado corretamente, e auth_session.authentication_methods gravando certo como array.

Megueutu added a commit that referenced this pull request Sep 11, 2026
…lign schema with production (#13)

pr #12 was squash-merged keeping only its first commit (schema.sql
username/banner) -- the six commits after it (dataload split into
auth/core connections, column-name fixes, csv-driven text/images,
connection.py and makefile fixes, databases.py removal) never made it
into main. This restores all of that from the feat/user-profile-fields
branch, plus new fixes found by actually running dataload against the
real qa databases:

- company.fk_address/fk_business_contact, local_unit.fk_address,
  technician_affiliation.fk_company, technical_project.fk_requester/
  fk_local_unit/status/start_date are NOT NULL in the real schema --
  dataload was treating them as optional.
- certification has a completely different real structure
  (fk_technician, type and information required; name/issuer/
  description/validity optional) -- rewritten to match, and moved
  after seed_technician in the seed order since it now depends on it.
- technical_company is a real table this schema never had (added,
  no seed yet -- not part of the current ask).
- federated_identity and inventory have composite UNIQUE constraints
  that random picks with replacement could violate at higher row
  counts -- both now sample without replacement/dedupe.
- db/core/seed.sql's second company insert was missing fk_address/
  fk_business_contact for the same reason.

Verified end to end against the real coredbqa/authdbqa (qa environment,
credentials via infra-platform/scripts/extract-env.ps1): both databases
seed cleanly with no errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants