ServiçoProServiçoPro

Arquitetura do ServiçoPro

Arquitetura do ServiçoPro — Visão Atual

Plataforma de marketplace de serviços locais multi-região, construída sobre Base44 BaaS. Frontend: React + Vite + Tailwind + shadcn/ui. Backend: Base44 (entidades, functions, auth, storage). Domínio publicado: https://servico-profissionais.base44.app


1. Diagrama de Alto Nível

┌─────────────────────────────────────────────────────────────────────┐
│                        USUÁRIO (navegador/app)                        │
│                  Visitante | Profissional | Admin                    │
└───────────────────────────────┬─────────────────────────────────────┘
                                │ HTTPS
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     FRONTEND (React SPA — Vite)                       │
│                                                                       │
│  App.jsx  ─ AuthProvider ─ QueryClientProvider ─ Router ─ Helmet     │
│              │                │               │                      │
│         AuthContext      React Query     NavigationTracker           │
│                                                                       │
│  Layout.jsx (CityProvider + Header + Footer + AdBannerFooter)        │
│       └─ Seletor de Cidade (localStorage → reload)                   │
│                                                                       │
│  Páginas (43) ─── agrupadas por perfil (ver §3)                      │
│  Componentes ─── home/ admin/ ads/ regional/ profile/ coupons/       │
│                  jobs/ layout/ turismo/ onboarding/ ui/(shadcn)      │
└───────────────────────────────┬─────────────────────────────────────┘
                                │ base44 SDK (fetch)
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    BASE44 BAAS (plataforma)                           │
│                                                                       │
│  ┌──────────┐  ┌───────────────┐  ┌───────────────┐  ┌───────────┐   │
│  │   Auth   │  │   Entidades   │  │   Functions  │  │  Storage  │   │
│  │ (tokens) │  │   (20+ tables)│  │   (40+ APIs) │  │ (uploads) │   │
│  └────┬─────┘  └───────┬───────┘  └───────┬───────┘  └─────┬─────┘   │
│       │                │                   │                │         │
│       │         Row-Level Security         │                │         │
│       │   (admin / regional_admin / user)  │                │         │
└───────┼────────────────┼──────────────────┼────────────────┼─────────┘
        │                │                  │                │
        ▼                ▼                  ▼                ▼
┌────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│  Asaas API │  │ Google Places│  │   Supabase   │  │ Google Ads/  │
│ (pagamentos│  │  (descoberta │  │   Storage    │  │  Analytics   │
│  + assinat)│  │  planejada)  │  │ (logo, PDFs) │  │ G-TFTYQE86DV │
└────────────┘  └──────────────┘  └──────────────┘  └──────────────┘

2. Camadas da Aplicação

2.1 Frontend

| Camada | Responsabilidade | Arquivo-chave | |--------|------------------|---------------| | Entrypoint | Providers (Auth, Query, Helmet, Router, Toaster) | src/App.jsx | | Layout | Header, nav por perfil, seletor de cidade, footer, banner rodapé | src/Layout.jsx | | Contexto de Cidade | Cidade atual em localStorage, troca com reload | src/components/context/CityContext.jsx | | Roteamento | pagesConfig (loop de páginas legadas) + rotas explícitas extras em App.jsx | src/App.jsx, src/pages.config.js | | Páginas | 43 telas (39 no pagesConfig + 4 rotas explícitas) agrupadas por perfil | src/pages/* | | Componentes | UI reutilizável e seções de domínio | src/components/* | | Estilo | Tailwind + tokens em index.css | src/index.css, tailwind.config.js |

2.2 Backend (Base44)

| Camada | Responsabilidade | |--------|------------------| | Auth | Login/registro/sessão gerenciados pela plataforma; roles admin, regional_admin, user; flag is_regional_admin no User | | Entidades | 20+ tabelas com schema JSON e RLS por perfil | | Backend Functions | 40+ APIs serverless em base44/functions/ (TypeScript) | | Storage | Uploads públicos (UploadFile) e privados (UploadPrivateFile + CreateFileSignedUrl) | | Interações Core | InvokeLLM, SendEmail, GenerateImage/Video/Speech, TranscribeAudio, ExtractDataFromUploadedFile |


3. Mapa de Páginas por Perfil

PÚBLICO (visitante)
├── Home                    Descoberta: busca, categorias, profissionais, banners
├── TurismoAtibaia          Conteúdo turístico específico de Atibaia
├── ProfessionalProfile     Perfil público do profissional (slug)
├── CategoryAdvertisers     Anunciantes por categoria
├── AdvertiserDetails       Detalhes do anunciante + cupons
├── JobBoard / JobDetails   Vagas de emprego
├── PartnerBenefits         Benefícios do parceiro regional
└── TermsOfUse              Termos de uso

PROFISSIONAL (autenticado)
├── MyProfile               Edição de perfil + mensagens + assinatura
├── MyRequests              Pedidos de serviço recebidos
├── MyNotifications         Notificações in-app
├── SubscriptionPlans       Planos e checkout
├── RegisterProfessional    Cadastro de profissional
└── AuthCallback            Retorno do login

ADMIN REGIONAL (is_regional_admin)
├── RegionalDash            Dashboard regional (estatísticas)
├── Ads?tab=overview         Meus anúncios (banners)
├── Ads?tab=coupons          Meus cupons
└── GuiaExpensaoRegional     Guia de expansão

ADMIN (role=admin)
├── AdminPanel               Gerenciar profissionais + assinaturas + import Places
├── Partners                 Parceiros regionais (subadmins)
├── Commissions              Comissões a pagar
├── Messages                 Mensagens de contato
├── AdsApproval              Aprovação de banners
├── BusScheduleAdmin         Horários de ônibus (Atibaia)
├── BulkAssignRegionalPartners Atribuição em massa de parceiros
├── FixRegionalPartnerUser    Correção de usuário parceiro
├── TestAds / Test*           Páginas de teste de pagamento/assinatura
├── ManualAdministrador      Documentação interna
├── AsaasConfig              Configuração Asaas
├── AsaasSubscribe            Inscrição Asaas
├── AsaasTestCheckout/Plan    Testes Asaas
├── AsaasWebhookSetup         Setup de webhook Asaas
├── JobScraper                Scraper de vagas (manual)
└── TestCityContext / TestCheckSubscriptions / TestSubscription*  Testes

4. Modelo de Dados (Entidades)

4.1 Núcleo de Marketplace

Professional ──── (1:N) ──── ServiceRequest
     │                          (cliente → profissional)
     ├── category (enum 30+ serviços)
     ├── source: manual | google_places | organic
     ├── subscription_status / subscription_plan
     ├── region_id / regional_partner_id
     ├── needs_category_review (importados com 'outros')
     └── engagement: notification_cycle_start_date, last_notification_step

4.2 Multi-região (Tenant)

RegionalPartner (subadmin)  ── manages ──>  cities / cep_ranges
       │                                          │
       └── user_id (User)                          │
                                                   ▼
RegionalAppConfig (region_id, branding, subdomain, cores, logo)
       │
       └── regional_partner_id
                   │
                   ▼
Professional.region_id  +  RegionalAdBanner.region_id

4.3 Publicidade Regional

RegionalAdBanner ──── (1:N) ──── Coupon
     │  banner_type: footer | home_below_fold | between_cards |
     │              benefits_page | hero_category_icon
     │  ad_plan: basico_local | destaque_regional | premium_nacional |
     │          hero_icon_highlight
     │  status: pending_approval → approved → active
     │
     ├── advertiser (nome, cpf/cnpj, contato)
     ├── contract (datas, valor, comissão)
     └── métricas: click_count, view_count

RegionalAdvertiser (cadastro do anunciante)

4.4 Pagamentos e Assinaturas

                    Asaas (provedor principal)
                         │
        ┌────────────────┼─────────────────┐
        ▼                ▼                 ▼
  AsaasConfig     AsaasSubscription   AsaasPayment
  (chave/amb)    (assinatura)         (cobrança)
                         │
                         ├── plan_type: basico | profissional | premium
                         ├── cycle: MONTHLY | QUARTERLY | YEARLY
                         └── status: ACTIVE | OVERDUE | EXPIRED | CANCELED

  PagBank (alternativo)
    PagBankConfig → PagBankPlan → PagBankSubscriber → PagBankCharge → PagBankSubscription

  AppSubscriptionCharge  (cobrança interna manual)
  Subscription            (assinatura interna)
  SubscriptionNotification (notificações de cobrança)

  BoletoTransaction + C6BankConfig  (boletos — planejado)
  PixTransaction                   (PIX — planejado)

4.5 Comissões Regionais

AsaasPayment / RegionalAdBanner
        │
        ▼
RegionalCommission  ─── (N:1) ─── RegionalPartner
   source: subscription | advertisement
   commission_rate → commission_amount
   status: pending → paid → cancelled
        │
        ▼
CommissionAuditLog  (auditoria periódica de divergências)

4.6 Outros

JobPosting (vagas)          BusLine (horários de ônibus - Atibaia)
ContactMessage (fale conosco)  InAppNotification (notificações do prof)
InvoiceConfig + Invoice (NF)  PriceBugAlert (monitor de preço)

5. Backend Functions por Domínio

5.1 Asaas (Pagamentos) — 12 functions

asaas_create_customer ─→ asaas_create_subscription ─→ asaas_create_checkout
         │                        │                           │
         ▼                        ▼                           ▼
asaas_init_subscription   asaas_get_subscription      asaas_list_payments
         │                        │
asaas_cancel_subscription  asaas_test_api_key
         │
asaas_webhook (recebe notificações) ─→ atualiza AsaasPayment + RegionalCommission
         │
asaas_configure_invoice ─→ asaas_generate_payment_book
         │
asaas_create_ad_payment (publicidade)

5.2 Comissões — 3 functions

generate_ad_commission    (calcula comissão do banner)
get_commissions_extract   (extrato do parceiro)
auditCommissions          (conciliação periódica)

5.3 Regional / Subadmin — 5 functions

assign_regional_partner        (atribui prof → parceiro por CEP)
bulk_assign_regional_partners  (atribuição em massa)
auto_fix_regional_partner      (corrige is_regional_admin no login)
get_regional_dashboard_data    (dados do dashboard regional)
generate_regional_guide_pdf     (guia de expansão em PDF)

5.4 Assinaturas — 3 functions

check_subscriptions            (verifica status/vencimentos)
app_create_subscription_charge (cobrança manual interna)
cancel_professional_trial       (encerra trial 30 dias)

5.5 Anúncios — 3 functions

get_public_ads     (lista banners para exibir no front)
get_ad_details     (detalhes do anunciante)
sync_ad_payments   (sincroniza pagamentos de publicidade)

5.6 Cupons — 2 functions

coupon_operations       (CRUD de cupons)
download_coupon_number  (número sequencial)

5.7 Perfil / Engajamento — 6 functions

track_profile_view              (incrementa visualização)
send_profile_view_notifications (notifica prof de novas views)
welcome_professional            (email de boas-vindas no create)
update_photos_by_gender         (foto placeholder por gênero)
generate_slugs / auto_generate_slugs  (URL amigável)

5.8 Vagas & SEO — 3 functions

import_jobs          (importa vagas de fontes — requer admin)
scrape_pat_atibaia   (scraper PAT Atibaia)
generateSitemap      (sitemap.xml dinâmico)

5.9 Monitoramento — 1 function

monitor_price_bugs  (detecta anomalias de preço)

5.10 Legado / Abandonado

importarProfissionaisSolutudo   (❌ proibido — termos legais)
importarProfissionaisgetninjas  (❌ proibido — anti-scraping)

5.11 Descoberta de Profissionais (Google Places) — ✅ em produção

google_places_import  (Nearby Search v1 + Details + dedup por google_place_id + bulkCreate)
   ├── Automação semanal ativa ("Importação Semanal Google Places", segundas 06:00)
   ├── 80+ tipos de Places → enum Professional mapeados
   ├── Limite: 6 categorias/run, 20 novos/run, cooldown 24h
   └── Importados com categoria 'outros' → needs_category_review=true

6. Fluxograma: Descoberta de Profissional (usuário final)

[Visitante abre Home]
        │
        ▼
[CityContext define cidade] ── localStorage('selectedCity')
        │
        ▼
[HeroSection: busca + categoria + CEP]
        │
        ├── SearchAutocomplete (sinônimos → categoria)
        ├── AdvancedFilters (disponibilidade, preço, experiência)
        ├── SearchSortControl (rating, distância, preço)
        │
        ▼
[Home.jsx: filter profissionais]
        │  base44.entities.Professional.filter({region_id, category, ...})
        │  + regionalAdFilter.jsx (prioriza anúncios regionais)
        │
        ├── Banners regionais (hero_icon_highlight, home_below_fold)
        ├── ProfessionalCard (rating, WhatsApp, favoritar)
        │       └── FavoriteButton → useFavorites (localStorage + evento)
        │
        ▼
[Paginação "Carregar mais"]
        │
        ▼
[Clique no card] → ProfessionalProfile (slug)
        │
        ├── track_profile_view (backend)
        ├── send_profile_view_notifications (backend → InAppNotification)
        └── Solicitar serviço → ServiceRequest → MyRequests (profissional)

7. Fluxograma: Cadastro & Engajamento do Profissional

[Profissional clica "Entrar/Cadastrar"]
        │
        ▼
[LoginHelpModal] → base44.auth.redirectToLogin
        │
        ▼
[AuthCallback] → base44.auth.me()
        │
        ▼
[RegisterProfessional] ── cria Professional
        │
        ▼
[welcome_professional (entity:create trigger)] ── ❌ known issue
        │  deveria: SendEmail boas-vindas + InAppNotification
        │
        ▼
[auto_generate_slugs] ── gera slug
        │
        ▼
[SubscriptionPlans] ── escolhe plano
        │
        ▼
[AsaasSubscribe / Asaas checkout]
        │  asaas_create_customer → asaas_create_subscription → asaas_create_checkout
        │
        ▼
[asaas_webhook] ── confirma pagamento
        │  → AsaasPayment + RegionalCommission + Professional.subscription_status
        │
        ▼
[Ciclo de engajamento]
   profile_view_count → views_at_last_notification
        │
   send_profile_view_notifications (passos 1→2→3)
        │  notification_cycle_start_date, last_notification_step
        │
   check_subscriptions (verifica trial → converte)

8. Fluxograma: Publicidade Regional

[Parceiro Regional] ── Ads?tab=overview ── RegionalAdForm
        │
        ▼
[RegionalAdBanner criado] ── status: pending_approval
        │
        ▼
[Admin: AdsApproval] ── aprova/rejeita
        │  approved_by, approved_date
        │
        ▼
[asaas_create_ad_payment] ── gera cobrança
        │  → AsaasPayment (payment_source: advertisement)
        │
        ▼
[asaas_webhook] ── pagamento confirmado
        │  → sync_ad_payments
        │  → generate_ad_commission → RegionalCommission
        │
        ▼
[Banner ativo (is_active=true)]
        │  → get_public_ads (frontend busca)
        │  → AdBannerFooter / AdBannerHome / AdBannerCard
        │  → Coupon (se houver) → CouponCard

9. Fluxograma: Multi-região (Tenant)

[Visitante seleciona cidade]
        │
        ▼
[validateAndFetchCity(slug)] ── cities.jsx
        │
        ▼
[updateCity() + localStorage.setItem('selectedCity')] ── sem reload
        │
        ▼
[CityProvider lê cidade] ── useCity() disponível globalmente
        │
        ├── Layout: banner de cidade no header
        ├── Home: filter region_id + cep_ranges
        ├── AdBannerFooter: banners da região + nacionais
        └── SEO: Schema.org JSON-LD por cidade
                │
                ▼
        [RegionalAppConfig] (branding, cores, subdomínio)
                │
                ▼
        [RegionalPartner] (comissão, gestão de cidades)
                │
                ▼
        [Professional.region_id / RegionalAdBanner.region_id]

10. Segurança (RLS)

| Entidade | create | read | update | delete | |----------|--------|------|--------|--------| | Professional | admin, regional_admin | público | admin, regional_admin | admin | | RegionalPartner | admin | público | admin, próprio (email) | admin | | RegionalAppConfig | admin | admin, regional_admin | admin | admin | | RegionalAdBanner | admin, regional_admin | público | admin, regional_admin | admin | | RegionalCommission | admin | admin, regional_admin | admin | admin | | InAppNotification | admin | próprio (email/id), admin | próprio, admin | — | | C6BankConfig | — | próprio (email), admin | próprio, admin | — | | Coupon | admin, regional_admin | público | true | admin | | JobPosting | admin | público | admin | — |

⚠️ RLS é silenciosa: regra frouxa = dado exposto; regra apertada = lock-out do próprio dono.


11. Integrações Externas

| Serviço | Status | Uso | |---------|--------|-----| | Asaas | ✅ configurado (sandbox/prod) | Assinaturas e pagamentos de anúncios | | PagBank | ⚠ schema pronto, sem fluxo ativo | Alternativa de pagamento (planejado) | | C6Bank | ⚠ schema pronto | Boletos/PIX (planejado) | | Google Places API | ✅ em produção (function + automação semanal ativas) | Descoberta de estabelecimentos | | Google Analytics | ✅ G-TFTYQE86DV (gtag injetado no Layout) | Analytics web | | Supabase Storage | ✅ assets estáticos | Logo, PDF do contrato | | InvokeLLM (Core) | ✅ disponível | LLM para classificação/extração | | SendEmail (Core) | ✅ disponível | E-mails transacionais |


12. Fluxo de Dados de Descoberta (Google Places — ✅ em produção)

[Admin: AdminPanel → aba "Importar Google Places"]  OU  Automação semanal
        │
        ▼
[google_places_import] ── Places API v1 Nearby Search (paginado)
        │  location (lat/lng da cidade) + radius + type
        │  limite: 6 categorias/run, 20 novos/run, cooldown 24h
        │
        ▼
[Place Details por establishment] ── nome, endereço, telefone, rating, photo
        │
        ▼
[Mapping Places category → enum Professional]
        │  match direto (80+ tipos) → categoria correta
        │  sem match → category='outros' + needs_category_review=true
        │
        ▼
[Dedup por google_place_id]
        │  existe? → skip
        │  novo? → bulkCreate (source='google_places')
        │
        ▼
[Resumo do lote: novos / duplicados / para revisar]
        │
        ▼
[Admin: aba Profissionais → filtro "Revisar categoria"]
        │  ProfessionalManagementCard mostra badge "Revisar categoria"
        │  Admin reclassifica → needs_category_review=false (auto)
        │
        ▼
[Automação semanal ativa] ── segundas 06:00, repete para regiões ativas

13. Pontos de Atenção (Known Issues)

✅ Todos os bugs históricos abaixo foram corrigidos (ver /projeto-atualização — roadmap 100%).

| # | Issue (histórico) | Status | Resolução | |---|-------|--------|-----------| | 1 | welcome_professional não disparava no entity:create | ✅ Corrigido | Automação entity:create recriada e ativa | | 2 | send_profile_view_notifications com e-mail de debug hardcoded | ✅ Corrigido | Refatorado para usar professional.email | | 3 | Link "Acessar Meu Perfil" no e-mail apontava para domínio antigo | ✅ Corrigido | Atualizado para o domínio publicado | | 4 | import_jobs falhava (requer credenciais admin) | ✅ Corrigido | Refatorado para service role | | 5 | Asaas: 401 Unauthorized / dessincronia de status | ✅ Corrigido | Refatoração completa + User-Agent + AsaasConfig | | 6 | InAppNotification.type com valor de enum inválido | ✅ Corrigido | Enum corrigido para valores válidos | | 7 | google_places_import pendente (Builder+) | ✅ Concluído | Implementado + automação semanal ativa | | 8 | Scraper Solutudo/GetNinjas abandonado (legal) | ⛔ Abandonado | 10 automações arquivadas |

13.1 Itens de monitoramento ativos (não-bloqueantes)

  • ⚠️ Chave GOOGLE_PLACES_API_KEY: restrição no Google Cloud Console deve permitir chamadas server-side (trocar "HTTP referrers" por "IP addresses" ou "None").
  • ⚠️ Automação "Importação Automática de Vagas" (import_jobs) legada está arquivada; a ativa é "Atualização Automática de Vagas" (a cada 2h).

14. Stack Técnica

Frontend:  React 18 + Vite + Tailwind CSS + shadcn/ui (Radix)
           react-router-dom, @tanstack/react-query, framer-motion
           react-leaflet (mapas), recharts (gráficos), @hello-pangea/dnd
           react-helmet-async (SEO), react-quill (editor), three.js (3D)
           lucide-react (ícones), date-fns, lodash, moment

Backend:   Base44 BaaS (entidades JSON + functions TS serverless)
           Auth gerenciada (JWT, sessões, verificação de e-mail)
           RLS por entidade, Storage de arquivos, React Query cache

Storage:   Base44 Storage (uploads) + Supabase (assets estáticos)

Analytics: Google Analytics (G-TFTYQE86DV)

Build:     Vite (ESM) → dist/ → deploy automático Base44

15. Capacidades Ativas do Plano

  • ✅ Backend Functions — 43 functions serverless ativas (Asaas, comissões, regional, assinaturas, anúncios, cupons, perfil/engajamento, vagas, SEO, monitoramento, Google Places).
  • ✅ Automações — 8 ativas: Google Places (semanal), Sitemap (diário), Verificação de Assinaturas (diária), Boas-vindas (entity:create), Auditoria de Comissões (mensal), Monitor de Preço (diário), Atualização de Vagas (2h), Notificações de Visualização (diária).
  • ⚠️ Conectores OAuth (Slack, Google Calendar, etc.) exigem configuração por integração.
  • ✅ Frontend, entidades, RLS, Auth, Storage e integrações Core (LLM, e-mail, upload, geração de imagem/vídeo/áudio) funcionando.

Estado detalhado do roadmap técnico em /projeto-atualização.


Última atualização: 2026-09-09 — gerado a partir do estado atual do código e automações ativas.