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.
