UNO Data Lake

Documentação das Tabelas

Este repositório contém os modelos de dados utilizados no Uno Data Lake, um sistema para gestão e armazenamento de dados de franquias e seus negócios relacionados. Esta documentação explica a estrutura de cada modelo e seus campos.

Bem-vindo(a) à documentação do UNO Data Lake. Este ambiente concentra os dados operacionais das franqueadoras e suas franquias/empresas em um cluster Amazon Redshift, permitindo a construção de dashboards, relatórios e análises de BI sobre uma base unificada.

Esta documentação descreve o que cada tabela representa, quais colunas existem, como elas se relacionam e como consultá-las corretamente. Foi escrita para um público misto: analistas de BI (com SQL básico) e engenheiros de dados.


Índice


Visão geral

O Data Lake recebe réplicas dos dados transacionais das aplicações operacionais (Vendas, CRM, Atendimento, Financeiro, Marketing) e os organiza em tabelas analíticas amplas, denormalizadas (com nomes já materializados em colunas *_name) para facilitar a leitura por ferramentas de BI.

Características principais:

  • Banco: Amazon Redshift.
  • Modelo: estrela "achatada" — cada tabela já contém o nome (denormalizado) das principais entidades relacionadas, evitando a maior parte dos JOINs em consultas típicas.
  • Multi-tenant: todas as tabelas operacionais possuem a coluna schema que isola os dados de cada franquia/empresa. Toda consulta deve filtrar por schema.
  • Histórico: as tabelas refletem o estado atual da operação. Para análises temporais, use as colunas de data (created_at, updated_at, due_date, liquidation_date, etc.).

Convenções importantes

Multi-tenant: a coluna schema e o franchisor_id

Quase todas as tabelas possuem duas colunas críticas:

ColunaDescrição
schemaIdentificador (string) da franquia/empresa dona do registro. Funciona como o "tenant" do Data Lake. É a DISTKEY na maioria das tabelas.
franchisor_idIdentificador da franqueadora (rede/marca) à qual a franquia pertence. Permite consolidar dados entre todas as franquias de uma mesma rede.

Por que isso importa? Os IDs de negócio (como order_id, customer_id, appointment_id) são gerados por franquia — ou seja, não são globalmente únicos. Duas franquias diferentes podem ter um order_id = 1234 apontando para vendas completamente distintas.

⚠️

Sempre filtre por schema (e, quando aplicável, por franchisor_id).

Regra de ouro dos JOINs

Toda relação entre tabelas deve ser feita pela combinação schema + <id_de_negócio> — nunca apenas pelo ID.

Exemplos corretos:

-- ✅ CORRETO: JOIN por schema + order_id
SELECT *
FROM orders o
JOIN payments p
  ON p.schema   = o.schema
 AND p.order_id = o.order_id
WHERE o.schema = 'minha_franquia';

-- ❌ INCORRETO: JOIN apenas por order_id
SELECT *
FROM orders o
JOIN payments p ON p.order_id = o.order_id;  -- vai cruzar dados de franquias diferentes!

Para análises a nível de franqueadora (várias franquias da mesma rede), filtre por franchisor_id e mantenha o schema em todos os JOINs:

SELECT *
FROM orders o
JOIN payments p
  ON p.schema   = o.schema
 AND p.order_id = o.order_id
WHERE o.franchisor_id = '42';

Chaves técnicas vs. chaves de negócio

Cada tabela tem uma coluna id (auto-incremento) usada apenas como chave primária técnica do Redshift. Ela não tem significado de negócio e pode ser ignorada em consultas analíticas.

Use sempre as colunas com sufixo _id (order_id, customer_id, appointment_id, …) — são essas que vêm dos sistemas operacionais e que devem ser usadas em filtros e JOINs (sempre combinadas com schema).

Distribuição e ordenação no Redshift (DISTKEY / SORTKEY)

Para entender por que filtrar por schema é tão importante, vale conhecer como o Redshift organiza as tabelas:

ConceitoComo é usado aqui
DISTKEYColuna usada para distribuir as linhas entre os nós do cluster. Praticamente todas as tabelas usam schema como DISTKEY — isso garante que dados da mesma franquia fiquem no mesmo nó, acelerando JOINs locais.
SORTKEYColunas usadas para ordenar fisicamente os dados em disco. Geralmente é uma combinação de schema, <id_de_negócio> e franchisor_id. Filtros nessas colunas são extremamente rápidos.

Implicação prática: consultas que não filtram por schema forçam o cluster a varrer dados em todos os nós, ficando muito mais lentas e caras.

Datas, fuso horário e tipos

  • Todas as colunas de data/hora usam TIMESTAMP WITH TIME ZONE (UTC). Converta para o fuso local da empresa (a coluna companies.timezone indica o fuso, ex.: America/Sao_Paulo) quando for exibir para o usuário final.
  • Valores monetários estão em DOUBLE PRECISION (mapeados como FLOAT no ORM). Sempre use ROUND(...) ao exibir.
  • A moeda padrão de cada empresa está em companies.currency.

Atualização incremental (metadata)

A tabela metadata registra o último updated_at processado por tabela e por schema. Use-a se precisar saber até quando o Data Lake está atualizado para uma franquia específica.


Mapa de relacionamentos

                    franchises (1) ──< companies (N)
                         │
                         └──< franchise_royalties ──< franchise_royalty_periods
                         └──< franchise_advertising_fees ──< franchise_advertising_fee_periods
                         └──< franchise_category_types >── franchise_categories

  customers ──┐
              ├──< deals
              ├──< budgets ──> orders
              ├──< orders ──< order_services ──> services
              │                ──< order_products ──> products
              │                ──< order_plans    ──> plans
              │                ──< order_courses  ──> courses ──< classes
              │                ──< order_lessons
              │                ──< payments
              ├──< appointments ──> rooms ──< room_time_slots
              ├──< measures
              └──< slimming_goals

  employees ──< employee_goals >── goals
  accounts_payable (financeiro – contas a pagar)
  facebook_accounts ──< facebook_campaign_data

Todos os JOINs implícitos acima usam schema + <id>.


Catálogo de tabelas

TabelaDomínioDescrição rápida
franchisesOrganizaçãoFranquias (unidades) cadastradas.
companiesOrganizaçãoDados cadastrais e de endereço das empresas.
employeesOrganizaçãoFuncionários (vendedores, atendentes, etc.).
customersOrganizaçãoClientes finais (PF/PJ).
dealsCRMNegociações/oportunidades do funil comercial.
budgetsCRMOrçamentos gerados para clientes.
ordersVendasVendas (pedidos) consolidadas.
order_servicesVendasItens de serviço dentro de uma venda.
order_productsVendasItens de produto dentro de uma venda.
order_plansVendasPlanos contratados em uma venda.
order_coursesVendasCursos contratados em uma venda.
order_lessonsVendasAulas individuais relacionadas a order_courses.
paymentsFinanceiroRecebíveis (parcelas) gerados por vendas.
accounts_payableFinanceiroContas a pagar da empresa.
servicesCatálogoServiços oferecidos.
productsCatálogoProdutos oferecidos.
plansCatálogoPlanos comercializados.
coursesCatálogoCursos oferecidos.
classesCatálogoTurmas de cursos.
appointmentsAtendimentoAgendamentos de serviços.
roomsAtendimentoSalas de atendimento.
room_time_slotsAtendimentoJanelas de funcionamento das salas.
measuresAtendimentoMedidas corporais coletadas (ramo estética/saúde).
slimming_goalsAtendimentoMetas de emagrecimento por cliente.
goalsMetasMetas globais da empresa por período.
employee_goalsMetasMetas individualizadas por funcionário.
franchise_royaltiesFranqueadoraRegras de cobrança de royalties por franquia.
franchise_royalty_periodsFranqueadoraValores apurados de royalties por período.
franchise_advertising_feesFranqueadoraRegras de taxa de publicidade.
franchise_advertising_fee_periodsFranqueadoraValores apurados de publicidade por período.
franchise_categoriesFranqueadoraCategorias de classificação de franquias.
franchise_category_typesFranqueadoraVínculo entre franquia e categoria.
facebook_accountsMarketingContas de anúncio do Facebook integradas.
facebook_campaign_dataMarketingMétricas diárias por campanha/anúncio.
metadataSistemaÚltima sincronização do Data Lake por tabela/schema.

Tabelas — Estrutura organizacional

franchises

Franquias (unidades operacionais) cadastradas.

ColunaTipoNullableDescrição
franchise_idINTEGERnãoID da franquia (chave de negócio).
schemaVARCHAR(255)nãoTenant.
nameVARCHAR(255)nãoNome da franquia.
statusVARCHAR(255)simVer Status de franquia.
created_atTIMESTAMPTZnãoCriação.
updated_atTIMESTAMPTZnãoÚltima atualização.

companies

Empresas (CNPJs) operadas pelas franquias. Em geral existe uma company por schema.

ColunaTipoNullableDescrição
company_idINTEGERnãoID da empresa.
schemaVARCHAR(256)nãoTenant.
franchisor_idINTEGERsimFranqueadora.
legal_nameVARCHAR(256)nãoRazão social.
nameVARCHAR(256)nãoNome fantasia.
cnpjVARCHAR(256)simCNPJ.
statusVARCHAR(256)nãoVer Status de empresa.
street, number, neighborhood, zip_codeVARCHARsimEndereço.
city_name, city_identifierVARCHARsimCidade e código IBGE.
state_name, state_initialsVARCHARsimEstado.
country_nameVARCHARsimPaís.
timezoneVARCHARsimFuso horário (ex.: America/Sao_Paulo).
localeVARCHARsimLocale (ex.: pt-BR).
currencyVARCHARsimMoeda (ex.: BRL).
created_at / updated_atTIMESTAMPTZnãoAuditoria.

employees

Funcionários das empresas (vendedores, atendentes, profissionais, etc.).

ColunaTipoNullableDescrição
employee_idINTEGERnãoID do funcionário.
schema / franchisor_idTenant / rede.
nameVARCHAR(255)nãoNome.
activeBOOLEANnãoEstá ativo?
employee_type_idINTEGERnãoID do tipo (cargo/função).
employee_type_nameVARCHAR(255)nãoNome do tipo.
employee_type_franchise_identifierINTEGERsimID do tipo no escopo da franquia.
employee_type_franchisorBOOLEANnãoSe o tipo é definido pela franqueadora.
expectedmeritlevelVARCHAR(255)simNível de mérito esperado.
created_at / updated_atTIMESTAMPTZnãoAuditoria.

customers

Clientes finais (PF e PJ).

ColunaTipoNullableDescrição
customer_idINTEGERnãoID do cliente.
schema / franchisor_idTenant / rede.
franchise_idINTEGERsimFranquia de origem.
typeVARCHAR(255)nãoTipo: pessoa física, jurídica, etc.
nameVARCHAR(255)simNome (PF) ou nome fantasia (PJ).
legal_nameVARCHAR(255)simRazão social (PJ).
cpf / cnpjVARCHAR(255)simDocumento.
email, cellphone, phoneVARCHAR(255)simContatos.
genderVARCHAR(255)simGênero.
birthdayTIMESTAMPTZsimData de nascimento.
occupation_id, occupation_namesimOcupação/profissão.
street, number, neighborhood, zip_codesimEndereço.
city_id, city_name, state_id, state_name, country_id, country_namesimLocalização.
activeBOOLEANsimAtivo? (default true).
created_at / updated_atTIMESTAMPTZnãoAuditoria.

Tabelas — CRM e funil comercial

deals

Negociações/oportunidades do funil comercial. Um deal pode (ou não) ser convertido em uma order.

ColunaTipoNullableDescrição
deal_idINTEGERnãoID do deal.
schema / franchisor_idTenant / rede.
nameVARCHARsimNome/título do deal.
customer_idINTEGERsimCliente vinculado.
deal_origin_id, deal_origin_namesimOrigem do lead.
deal_stage_id, deal_stage_namenãoEstágio atual no funil.
employee_id, employee_namesimResponsável.
seller_id, seller_namesimVendedor.
aux_id, aux_namesimAuxiliar.
total_priceFLOATsimValor potencial.
ratingINTEGERsimPontuação/qualificação.
customer_appointment_dateTIMESTAMPTZsimData de agendamento de visita.
customer_appointment_status_idINTEGERsimStatus do agendamento.
converted_atTIMESTAMPTZsimQuando foi convertido em venda.
discarded_atTIMESTAMPTZsimQuando foi descartado.
order_idINTEGERsimVenda gerada (JOIN com orders por schema + order_id).
facebook_source_id, facebook_wacl_idVARCHARsimRastreio de origem do Facebook Ads.
created_at / updated_atTIMESTAMPTZnãoAuditoria.

Para taxa de conversão: deals com converted_at IS NOT NULL ou com order_id preenchido.


budgets

Orçamentos elaborados para clientes.

ColunaTipoNullableDescrição
budget_idINTEGERnãoID do orçamento.
schema / franchisor_idTenant / rede.
statusVARCHAR(255)nãoVer Status de orçamento.
customer_id, customer_nameCliente.
employee_id, employee_nameFuncionário responsável.
service_total_price, product_total_price, plan_total_price, course_total_priceFLOATnãoSubtotais por categoria.
total_priceFLOATnãoValor total.
total_discountFLOATnãoDesconto aplicado.
installmentINTEGERsimNº de parcelas previsto.
expiration_atTIMESTAMPTZsimValidade do orçamento.
discarded_atTIMESTAMPTZsimDescartado em.
converted_atTIMESTAMPTZsimConvertido em venda em.
transformationBOOLEANsimIndica orçamento de transformação (renegociação).
observationVARCHARsimObservação livre.
observation_discardedVARCHARsimMotivo do descarte (texto).
budget_discard_reason_idINTEGERsimID do motivo de descarte.
order_idINTEGERsimVenda originada deste orçamento.
order_service_idINTEGERsimItem de venda originado (quando aplicável).
created_at / updated_atTIMESTAMPTZnãoAuditoria.

Tabelas — Vendas (orders e itens)

orders

Cabeçalho da venda. Os itens estão nas tabelas order_services, order_products, order_plans, order_courses.

ColunaTipoNullableDescrição
order_idINTEGERnãoID da venda.
schema / franchisor_idTenant / rede.
statusVARCHAR(255)nãoVer Status de venda.
customer_id, customer_namenãoCliente.
seller_id, seller_namenãoVendedor.
aux_id, aux_namesimVendedor auxiliar.
service_total_price, product_total_price, plan_total_price, course_total_priceFLOATnãoSubtotais por categoria.
total_priceFLOATnãoValor total da venda.
total_discountFLOATnãoDesconto total.
total_paidFLOATnãoTotal já pago.
total_liquidatedFLOATnãoTotal liquidado (compensado).
is_accountingBOOLEANnãoSe entra em contabilidade/relatórios financeiros.
order_cancellation_reason_id, order_cancellation_namesimMotivo do cancelamento.
order_abandonment_nameVARCHARsimMotivo de abandono.
canceled_atTIMESTAMPTZsimData de cancelamento.
created_at / updated_atTIMESTAMPTZnãoAuditoria.

order_services

Itens de serviço de uma venda.

ColunaTipoNullableDescrição
order_service_idINTEGERnãoID do item.
schema / franchisor_idTenant / rede.
order_idINTEGERsimVenda (JOIN schema + order_id).
service_idINTEGERsimServiço do catálogo (JOIN schema + service_id).
order_plan_idINTEGERsimSe o serviço veio incluído num plano.
quantityINTEGERsimQuantidade.
priceFLOATsimPreço unitário.
discountFLOATsimDesconto.
additional_valueFLOATsimAcréscimo.
created_at / updated_atTIMESTAMPTZnãoAuditoria.

order_products

Itens de produto de uma venda.

ColunaTipoNullableDescrição
order_product_idINTEGERnãoID do item.
schema / franchisor_idTenant / rede.
order_idINTEGERsimVenda.
product_idINTEGERsimProduto (JOIN schema + product_id).
order_plan_idINTEGERsimSe incluso em plano.
quantity, price, discount, additional_valuesimQuantidade e valores.
created_at / updated_atnãoAuditoria.

order_plans

Planos contratados em uma venda.

ColunaTipoNullableDescrição
order_plan_idINTEGERnãoID do item.
schema / franchisor_idTenant / rede.
order_idINTEGERsimVenda.
plan_idINTEGERsimPlano (JOIN schema + plan_id).
price, discount, additional_valueFLOATsimValores.
created_at / updated_atnãoAuditoria.

order_courses

Cursos contratados em uma venda.

ColunaTipoNullableDescrição
order_course_idINTEGERnãoID do item.
schema / franchisor_idTenant / rede.
statusVARCHARsimStatus do curso contratado.
course_idINTEGERsimCurso (JOIN schema + course_id).
order_idINTEGERsimVenda.
price, discount, additional_valueFLOATsimValores.
created_at / updated_atnãoAuditoria.

order_lessons

Aulas individuais associadas a order_courses (controle de presença).

ColunaTipoNullableDescrição
order_lesson_idINTEGERnãoID da aula contratada.
schema / franchisor_idTenant / rede.
order_course_idINTEGERsimVínculo com o curso comprado.
course_id, course_namesimCurso.
class_id, class_namesimTurma.
lesson_id, lesson_namenãoAula.
customer_id, customer_namenãoAluno.
attendanceBOOLEANsimPresença.
start_date, end_dateTIMESTAMPTZsimJanela da aula.
created_at / updated_atnãoAuditoria.

Tabelas — Financeiro

payments

Recebíveis (parcelas a receber) gerados pelas vendas.

ColunaTipoNullableDescrição
payment_idINTEGERnãoID do recebível.
schema / franchisor_idTenant / rede.
order_idINTEGERsimVenda originadora (JOIN schema + order_id).
customer_id, customer_namesimCliente.
employee_id, employee_namenãoFuncionário responsável (vendedor/financeiro).
valueFLOATnãoValor da parcela.
installmentFLOATsimNúmero da parcela.
original_due_dateTIMESTAMPTZsimVencimento original.
due_dateTIMESTAMPTZnãoVencimento atual.
liquidation_dateTIMESTAMPTZsimData de liquidação (compensação).
billed_dateTIMESTAMPTZnãoData de faturamento.
interest_valueFLOATsimJuros.
fee_valueFLOATsimTarifa.
discount_valueFLOATsimDesconto concedido.
storeBOOLEANnãoRecebido no balcão (loja)?
payment_status_id, payment_status_namenãoStatus. Ver Status de pagamento.
payment_type_id, payment_type_namenãoForma/tipo de pagamento.
payment_brand_id, payment_brand_namesimBandeira (cartão, boleto, etc.).
chart_account_id, chart_account_namesimPlano de contas.
credit_card_brandVARCHARsimBandeira do cartão (integrações).
last_credit_card_numberVARCHARsimÚltimos 4 dígitos.
created_at / updated_atnãoAuditoria.

accounts_payable

Contas a pagar da empresa (despesas, fornecedores, etc.).

ColunaTipoNullableDescrição
account_payable_idINTEGERnãoID da conta.
schema / franchisor_idTenant / rede.
descriptionVARCHAR(255)nãoDescrição.
typeVARCHAR(255)nãoTipo.
valueFLOATnãoValor.
installmentFLOATnãoParcela.
feesFLOATsimJuros.
fineFLOATsimMulta.
due_dateTIMESTAMPTZnãoVencimento.
payment_dateTIMESTAMPTZsimData do pagamento.
competence_dateTIMESTAMPTZsimCompetência contábil.
supplier_id, supplier_namesimFornecedor.
payment_brand_id, payment_brand_namesimForma de pagamento.
chart_account_id, chart_account_namesimPlano de contas.
cost_center_id, cost_center_namesimCentro de custo.
created_at / updated_atnãoAuditoria.

Tabelas — Catálogo (produtos, serviços, planos, cursos)

Todas as tabelas de catálogo seguem o mesmo padrão: *_id, schema, franchisor_id, franchise_identifier (id no escopo da franquia), name, price, active, created_at, updated_at.

services

Serviços oferecidos pela franquia.

Coluna extraTipoDescrição
is_budgetBOOLEANSe o serviço só pode ser vendido via orçamento.

products

Produtos comercializados. Sem colunas adicionais além do padrão.

plans

Planos comercializados. Sem colunas adicionais além do padrão.

courses

Cursos oferecidos. Sem colunas adicionais além do padrão.

classes

Turmas de cursos.

ColunaTipoNullableDescrição
class_idINTEGERnãoID da turma.
schema / franchisor_idTenant / rede.
nameVARCHAR(255)nãoNome da turma.
start_date, end_dateTIMESTAMPTZsimPeríodo da turma.
is_cyclicBOOLEANnãoTurma cíclica?
class_limitFLOATsimLimite de alunos.
minimum_frequencyFLOATsimFrequência mínima exigida.
class_status_id, class_status_namenãoStatus da turma.
course_id, course_namesimCurso.
employee_id, employee_namesimProfessor responsável.
created_at / updated_atnãoAuditoria.

Tabelas — Operação clínica/atendimento

appointments

Agendamentos de serviços para clientes.

ColunaTipoNullableDescrição
appointment_idINTEGERnãoID do agendamento.
schema / franchisor_idTenant / rede.
order_idINTEGERnãoVenda relacionada.
customer_id, customer_namenãoCliente.
employee_id, employee_namesimProfissional.
service_id, service_franchise_identifier, service_nameServiço.
service_budgetBOOLEANnãoÉ serviço de orçamento?
status_idINTEGERnãoStatus. Ver Status de agendamento.
service_sessionINTEGERnãoNº da sessão.
start_date, end_dateTIMESTAMPTZsimJanela do atendimento.
room_id, room_namesimSala (JOIN schema + room_id).
ratingINTEGERsimAvaliação do cliente.
rescheduledINTEGERnãoQuantidade de reagendamentos.
created_at / updated_atnãoAuditoria.

rooms

Salas de atendimento.

ColunaTipoNullableDescrição
room_idINTEGERnãoID da sala.
schema / franchisor_idTenant / rede.
nameVARCHAR(256)nãoNome.
customer_limitsINTEGERnãoCapacidade simultânea.
statusVARCHAR(256)nãoStatus (ativa/inativa, etc.).
employee_idINTEGERsimFuncionário responsável.
created_at / updated_atnãoAuditoria.

room_time_slots

Janelas de funcionamento das salas (por dia da semana).

ColunaTipoNullableDescrição
room_time_slot_idINTEGERnãoID.
schema / franchisor_idTenant / rede.
room_idINTEGERnãoSala.
day_of_weekVARCHAR(256)nãoDia da semana (ex.: MONDAY).
start_timeINTEGERnãoInício (em minutos a partir de 00:00).
end_timeINTEGERnãoFim (em minutos a partir de 00:00).
created_at / updated_atnãoAuditoria.

measures

Medidas corporais coletadas (típico de redes de estética/saúde).

ColunaTipoNullableDescrição
measure_idINTEGERnãoID da medição.
schema / franchisor_idTenant / rede.
customer_idINTEGERnãoCliente.
order_service_idINTEGERsimItem de venda associado.
dateTIMESTAMPTZsimData da medição.
weight, heightFLOATsimPeso e altura.
hip, waist, high_waist, low_waistFLOATsimQuadril e cinturas.
left_arm, right_armFLOATsimBraços.
left_thigh_high, left_thigh_low, right_thigh_high, right_thigh_lowFLOATsimCoxas.
calfFLOATsimPanturrilha.
abdominal_circumferenceFLOATsimCircunferência abdominal.
fat_percentageFLOATsim% de gordura.
blood_pressure_max, blood_pressure_minFLOATsimPressão arterial.
baseline_measureFLOATsimLinha de base.
first_measureBOOLEANsimÉ a primeira medição?
observationVARCHARsimObservação.
created_at / updated_atnãoAuditoria.

slimming_goals

Metas de emagrecimento por cliente.

ColunaTipoNullableDescrição
slimming_goal_idINTEGERnãoID.
schema / franchisor_idTenant / rede.
customer_idINTEGERnãoCliente.
start_date, end_dateTIMESTAMPTZnãoPeríodo da meta.
finished_atTIMESTAMPTZsimQuando concluída.
weight, height, hip, waist, high_waist, low_waist, left_arm, right_arm, left_thigh_high, left_thigh_low, right_thigh_high, right_thigh_low, calfFLOATsimMedidas-alvo.
observationVARCHARsimObservação.
created_at / updated_atnãoAuditoria.

Tabelas — Metas e desempenho

goals

Metas globais da empresa por período.

ColunaTipoNullableDescrição
goal_idINTEGERnãoID.
schema / franchisor_idTenant / rede.
initial_date, end_dateTIMESTAMPTZnãoPeríodo da meta.
indicationINTEGERsimMeta de indicações.
product, service, plan, course, transformationFLOAT/INTsimMetas por categoria.
ticketFLOATsimMeta de ticket médio.
efficiencyFLOATsimMeta de eficiência.
totalFLOATsimMeta total (R$).
count_days, count_past_daysINTEGERsimDias úteis no período / já transcorridos.
created_at / updated_atnãoAuditoria.

employee_goals

Metas individuais por funcionário.

ColunaTipoNullableDescrição
employee_goal_idINTEGERnãoID.
schema / franchisor_idTenant / rede.
employee_idINTEGERnãoFuncionário.
goal_idINTEGERsimMeta global associada.
initial_date, end_dateTIMESTAMPTZnãoPeríodo.
indication, product, service, plan, course, transformation, totalFLOAT/INTsimMetas por categoria.
count_days, count_past_daysINTEGERnãoDias do período / dias passados.
created_at / updated_atnãoAuditoria.

Tabelas — Royalties e taxas da franqueadora

franchise_royalties

Regras de cobrança de royalties por franquia.

ColunaTipoNullableDescrição
franchise_royalty_idINTEGERnãoID da regra.
schemaVARCHAR(255)nãoTenant.
franchise_idINTEGERnãoFranquia.
start_at, end_atTIMESTAMPTZsim/nãoVigência.
due_dayINTEGERnãoDia de vencimento.
typeVARCHAR(255)nãoTipo de cobrança.
min_valueFLOATsimValor mínimo.
percentageFLOATsimPercentual.
calculation_typeVARCHAR(255)simForma de cálculo (sobre faturamento, etc.).
payment_brand_id, payment_brand_namesimForma de pagamento.
created_at / updated_atnãoAuditoria.

franchise_royalty_periods

Valores apurados de royalties por período.

ColunaTipoNullableDescrição
franchise_royalty_period_idINTEGERnãoID.
schemaVARCHARnãoTenant.
franchise_royalty_idINTEGERnãoRegra associada.
start_at, end_atTIMESTAMPTZnãoPeríodo de apuração.
valueFLOATnãoValor apurado.
created_at / updated_atnãoAuditoria.

franchise_advertising_fees

Regras de taxa de publicidade. Mesma estrutura de franchise_royalties, trocando royalty por advertising_fee.

franchise_advertising_fee_periods

Valores apurados de taxa de publicidade. Mesma estrutura de franchise_royalty_periods, trocando royalty por advertising_fee.

franchise_categories

Categorias para classificar franquias.

ColunaTipoNullableDescrição
franchise_category_idINTEGERnãoID.
schemaVARCHARnãoTenant.
nameVARCHARnãoNome da categoria.
activeBOOLEANnãoAtiva?
created_at / updated_atnãoAuditoria.

franchise_category_types

Tabela de junção entre franquia e categoria.

ColunaTipoNullableDescrição
schemaVARCHARnãoTenant.
franchise_category_idINTEGERnãoCategoria.
franchise_idINTEGERnãoFranquia.
created_at / updated_atnãoAuditoria.

Tabelas — Marketing (Facebook Ads)

facebook_accounts

Contas de anúncio do Facebook integradas.

ColunaTipoNullableDescrição
facebook_account_idINTEGERnãoID.
schema / franchisor_idTenant / rede.
nameVARCHARsimNome da conta.
account_statusINTEGERsimStatus (códigos do Facebook).
currencyVARCHARsimMoeda.
amount_spentVARCHARsimTotal gasto (acumulado).
spend_capVARCHARsimLimite de gasto.
business_id, business_nameVARCHARsimBusiness Manager.
bm_idVARCHARsimID do BM.
created_timeTIMESTAMPTZsimQuando a conta foi criada no Facebook.
last_campaign_syncTIMESTAMPTZsimÚltima sincronização.
activeBOOLEANsimEstá ativa no nosso sistema?
created_at / updated_atnãoAuditoria.

facebook_campaign_data

Métricas diárias por anúncio.

ColunaTipoNullableDescrição
facebook_campaign_data_idINTEGERnãoID.
schema / franchisor_idTenant / rede.
account_idVARCHARnãoConta de anúncio.
identifierVARCHARnãoIdentificador do registro.
dateDATEnãoDia da métrica.
source_idVARCHARnãoID de origem (anúncio).
ad_campaign_name, ad_set_name, ad_nameVARCHARnãoHierarquia do anúncio.
total_spentFLOATnãoGasto.
impressions, link_clicks, reachINTEGERnãoMétricas de entrega.
frequencyFLOATnãoFrequência.
started_messagesINTEGERnãoConversas iniciadas.
video_view_25_count, video_view_50_count, video_view_75_count, video_view_95_countINTEGERnãoVisualizações de vídeo por % assistido.
created_at / updated_atnãoAuditoria.

Para atribuir leads/vendas a campanhas, cruze com deals.facebook_source_id.


Tabelas — Sistema

metadata

Registra a última atualização processada para cada par (schema, table).

ColunaTipoDescrição
schemaVARCHAR(255)Tenant.
tableVARCHAR(256)Nome da tabela.
last_updatedTIMESTAMPTZMaior updated_at já carregado para essa tabela/schema.

Use para verificar a "freshness" do Data Lake:

SELECT "table", last_updated
FROM metadata
WHERE schema = 'minha_franquia'
ORDER BY "table";

Enums e dicionários de valores

franchises.status

ValorSignificado
IN_IMPLEMENTATIONEm implementação.
ACTIVEAtiva.
TERMINATION_REQUESTSolicitação de encerramento.
TERMINATIONEm encerramento.
CANCELEDCancelada.
LEGALEm situação jurídica.

companies.status

ValorSignificado
ACTIVEAtiva.
INACTIVEInativa.
IMPLANTATIONEm implantação.
BLOCKEDBloqueada.

orders.status

ValorSignificado
BILLEDFaturada.
CLOSEDFechada.
CANCELEDCancelada.
ABANDONMENTAbandono.
PENDING_BALANCESaldo pendente.

budgets.status

ValorSignificado
PENDINGAguardando.
ACCOMPLISHEDRealizada.
CONVERTEDConvertida em venda.
DISCARDEDDescartada.

payments.payment_status_id

IDNome
0Cancelado
1Pendente
2Conciliação
3Vencido
4Liquidado

appointments.status_id

IDNome
1Agendado
2Confirmado
3Em espera
4Em andamento
5Realizado
6Falta
7Bloqueio

Exemplos de queries para BI

Em todos os exemplos, troque 'minha_franquia' pelo schema desejado.

1. Faturamento mensal (vendas faturadas)

SELECT date_trunc('month', created_at) AS mes,
       SUM(total_price)               AS faturamento,
       COUNT(*)                       AS qtd_vendas
FROM orders
WHERE schema = 'minha_franquia'
  AND status = 'BILLED'
  AND created_at >= '2025-01-01'
GROUP BY 1
ORDER BY 1;

2. Recebíveis pendentes (a vencer e vencidos)

SELECT payment_status_name,
       COUNT(*)        AS qtd,
       SUM(value)      AS total
FROM payments
WHERE schema = 'minha_franquia'
  AND payment_status_id IN (1, 3) -- Pendente, Vencido
GROUP BY 1;

3. Ranking de vendedores no mês

SELECT seller_id,
       seller_name,
       COUNT(*)            AS qtd_vendas,
       SUM(total_price)    AS receita,
       SUM(total_paid)     AS recebido
FROM orders
WHERE schema = 'minha_franquia'
  AND status = 'BILLED'
  AND created_at >= date_trunc('month', current_date)
GROUP BY 1, 2
ORDER BY receita DESC;

4. Conversão do funil de CRM

SELECT COUNT(*)                                                 AS leads,
       COUNT(converted_at)                                      AS convertidos,
       COUNT(discarded_at)                                      AS descartados,
       ROUND(100.0 * COUNT(converted_at) / NULLIF(COUNT(*),0), 2) AS taxa_conversao_pct
FROM deals
WHERE schema = 'minha_franquia'
  AND created_at >= current_date - INTERVAL '90 days';

5. Vendas com seus pagamentos (uso correto do JOIN)

SELECT o.order_id,
       o.customer_name,
       o.total_price,
       o.total_paid,
       p.payment_id,
       p.value,
       p.due_date,
       p.payment_status_name
FROM orders o
JOIN payments p
  ON p.schema   = o.schema    -- ✅ obrigatório
 AND p.order_id = o.order_id
WHERE o.schema = 'minha_franquia'
  AND o.created_at >= current_date - INTERVAL '30 days';

6. Ocupação de agenda por profissional

SELECT employee_id,
       employee_name,
       COUNT(*) FILTER (WHERE status_id = 5) AS realizados,
       COUNT(*) FILTER (WHERE status_id = 6) AS faltas,
       COUNT(*)                              AS total_agendamentos
FROM appointments
WHERE schema = 'minha_franquia'
  AND start_date >= date_trunc('month', current_date)
GROUP BY 1, 2
ORDER BY total_agendamentos DESC;

7. Custo por lead (Facebook Ads × Deals)

WITH gasto AS (
  SELECT date, SUM(total_spent) AS spent
  FROM facebook_campaign_data
  WHERE schema = 'minha_franquia'
    AND date >= current_date - INTERVAL '30 days'
  GROUP BY 1
),
leads AS (
  SELECT date(created_at) AS date, COUNT(*) AS qtd
  FROM deals
  WHERE schema = 'minha_franquia'
    AND facebook_source_id IS NOT NULL
    AND created_at >= current_date - INTERVAL '30 days'
  GROUP BY 1
)
SELECT g.date,
       g.spent,
       l.qtd                                AS leads,
       ROUND(g.spent / NULLIF(l.qtd, 0), 2) AS cpl
FROM gasto g
LEFT JOIN leads l ON l.date = g.date
ORDER BY g.date;

8. Consolidado por franqueadora (várias franquias da mesma rede)

SELECT schema,
       SUM(total_price) AS faturamento
FROM orders
WHERE franchisor_id = '42'
  AND status = 'BILLED'
  AND created_at >= date_trunc('month', current_date)
GROUP BY schema
ORDER BY faturamento DESC;

Boas práticas de performance no Redshift

  1. Sempre filtre por schema. É a DISTKEY e a primeira SORTKEY da maioria das tabelas. Sem isso, o cluster faz varredura completa.
  2. Faça JOINs por schema + <id>. Isso evita "data movement" entre nós (porque ambos os lados do JOIN ficam no mesmo nó).
  3. Use os campos *_name denormalizados sempre que possível, em vez de fazer JOIN com tabelas-mestras (customers, services, etc.). Eles existem justamente para evitar JOINs em queries comuns de BI.
  4. Filtre por colunas da SORTKEY (geralmente schema, <id_de_negócio>, franchisor_id). Filtros nessas colunas são extremamente baratos.
  5. Evite SELECT * — Redshift é colunar; selecionar apenas as colunas necessárias reduz drasticamente o I/O.
  6. Prefira agregações GROUP BY em colunas de baixa cardinalidade (status, employee_id, schema) e dimensões temporais (date_trunc(...)).
  7. Use WITH (CTEs) para deixar a query mais legível — o otimizador do Redshift lida bem com elas.
  8. Janelas curtas no created_at/updated_at ajudam muito (ex.: últimos 90 dias) e reduzem o volume escaneado.
  9. Para reprocessamentos, consulte metadata para saber até onde o Data Lake está atualizado.

Em caso de dúvidas sobre o significado de um campo ou enum específico, consulte o time de dados — esta documentação é viva e será atualizada conforme novas tabelas e colunas forem adicionadas ao Data Lake.