Database
 sql >> Base de Dados >  >> RDS >> Database

Modelando um Banco de Dados para Registro de Vendas. Parte 1


Armazenar dados de vendas corretamente e depois combiná-los pode levar à criação de um modelo preditivo com alta taxa de precisão. Neste e nos próximos artigos, analisaremos um design de banco de dados para registro de vendas.

Todo mundo vive vendendo alguma coisa.

Robert Louis Stevenson

No mundo de hoje, vender produtos é onipresente. E os vendedores que têm acesso a ferramentas robustas que aproveitam dados históricos para analisar tendências e permitir que uma empresa ajuste as estratégias de negócios de acordo com isso, têm uma vantagem sobre seus concorrentes. Existem muitos parâmetros que podem afetar os resultados da empresa:a situação econômica global atual, localização dos clientes, idade, estado material e conjugal e histórico de contatos anteriores ou vendas para clientes.

Começaremos com um exemplo muito simples:um modelo de banco de dados para vendas em um café . Nos próximos artigos, estenderemos o modelo para a venda de produtos em outras filiais.

Modelo de vendas


Neste artigo, analisaremos apenas uma parte do modelo que contém dados de vendas com outras partes ausentes.

Ainda temos conexões com tabelas ausentes e veremos o modelo como uma caixa preta, supondo que o seguinte esteja correto para a tabela sale :
  • user_has_role_id consulte o id em user_has_role (conforme apresentado em meu artigo anterior na seção “Componente de tempo adicionado”) e armazena informações sobre o usuário que criou o registro de venda




Este modelo nos permite criar registros de vendas com vários itens. Cada item está relacionado a um produto do nosso catálogo. O momento em que geramos uma venda pode ser diferente do momento em que a venda é paga. Por exemplo, para uma xícara de café, esses momentos serão diferentes em questão de minutos ou horas. Se a nossa loja vendia aparelhos de telecomunicações, a diferença pode ser de alguns dias, talvez até meses.

Tabelas


Vamos dar uma olhada na definição da tabela e explicar o propósito e o uso dos atributos.



A tabela mais importante no modelo é product . É usado para armazenar detalhes sobre os produtos que ofereceremos aos nossos clientes. Os produtos geralmente são entregues a um cliente e pagos uma única vez, geralmente no momento da entrega. Além disso, os produtos geralmente são objetos físicos como carros, telefones, pacotes de açúcar ou xícaras de café.

Falaremos sobre a venda de coisas não físicas (serviços) nos próximos artigos.

Atributos no product tabela são:

  • name – o nome do produto no sistema
  • price_per_unit – custo do produto por unidade (por exemplo, 1 xícara de café custa 1,8 euros, 1 carro custa 17.500 euros, 1 kg de arroz custa 2 euros)
  • basic_unit – unidade base quando estamos vendendo um produto (por exemplo, peça, kg, litro)
  • tax_percentage – porcentagem do price_per_unit a ser cobrado como imposto. Devemos supor que a porcentagem de impostos não seria a mesma para todos os produtos
  • limited – este campo é definido como True se tivermos uma quantidade limitada em estoque e False caso contrário (por exemplo, podemos pedir qualquer quantidade necessária para nossa loja de um distribuidor)
  • in_stock – if limited=True este atributo mostra quantos temos disponíveis para vender
  • active_for_sale – se este atributo for False, não estamos oferecendo esse produto para venda no momento, caso contrário, podemos oferecê-lo aos clientes

Podemos obter uma lista de produtos que podemos oferecer aos clientes com a seguinte consulta:

SELECT product.id, product.price_per_unit, 
       product.basic_unit, product.limited, product.in_stock
FROM product
WHERE product.active_for_sale = True
AND (product.limited = False OR
      (product.limited = True and product.in_stock > 0))



A tabela sale_status é apenas um simples dicionário que contém todos os status que uma venda pode ter no sistema (por exemplo, “recibo emitido”, “recibo pago”).


A tabela sale é a segunda tabela mais importante neste modelo. Até agora, esta tabela não tem nenhuma relação com os clientes para os quais vendemos produtos porque, no nosso exemplo de cafeteria, não precisamos saber dessas informações. Na parte 2, o modelo será estendido para cobrir esses casos.
Os atributos na tabela e seus significados são:

  • time_created – hora em que um registro de venda foi gerado no sistema (por exemplo, hora automática em que o registro foi criado quando geramos uma venda de café em nossa cafeteria ou uma hora adicionada manualmente, se assim o desejarmos)
  • time_paid – geralmente podemos esperar que algumas vendas sejam pagas dentro de alguns dias ou até um mês após a criação (por exemplo, se entregarmos software e criarmos um recibo podemos esperar até 90 dias para receber o pagamento em alguns países, se tudo der certo a lei)
  • sale_amount – valor original destinado a ser cobrado do cliente
  • sale_amount_paid – valor que o cliente realmente pagou. Pode ser nulo porque no momento em que criamos um recibo nem sempre temos essa informação
  • tax_amount – soma de todos os valores de impostos para itens nesse recibo
  • sale_status_id – referência a sale_status tabela
  • user_has_role_id – referência ao usuário e sua função no momento em que ele inseriu o recibo no sistema



Podemos obter o valor emitido e pago (de acordo com time_created) dentro de um período de tempo com consulta como esta:

SELECT SUM(sale.sale_amount) AS amount_issued,
       SUM(sale.sale_amount_paid) AS amount_paid 
FROM sale
WHERE sale.time_created >= @start_time 
AND sale.time_created <= @end_time;

Para obter o valor exato pago dentro de um período de tempo, devemos usar uma consulta como esta:

SELECT SUM(sale.sale_amount_paid) AS amount_paid 
FROM sale
WHERE sale.time_paid >= @start_time 
AND sale.time_paid <= @end_time;

A consulta abaixo calculará o valor emitido e pago dentro de um período de tempo com a data de emissão e a data de pagamento marcadas separadamente:

SELECT 
SUM(CASE WHEN sale.time_created >= @start_time 
    AND sale.time_created <= @end_time 
    THEN sale.sale_amount END) AS amount_issued,
SUM(CASE WHEN sale.time_paid >= @start_time 
    AND sale.time_paid <= @end_time 
    THEN sale.sale_amount_paid END) AS amount_paid 
FROM sale

Em todos os exemplos @start_time e @end_time são variáveis ​​que contêm a hora de início e a hora de término do período para o qual queremos verificar o SUM emitido e pago.



A tabela sale_item conecta produtos e vendas. Claro, devemos assumir que teremos vários itens em um recibo, então precisamos que essa tabela tenha um relacionamento muitos-para-muitos.

Os atributos e seus significados são:

  • quantity_sold – quantidade de produto que foi vendida e é cobrada nessa venda/recibo (por exemplo, 3 cafés)
  • price_per_unit – mesmo valor que product.price_per_unit no momento em que a venda foi criada. Temos que salvá-lo porque price_per_unit no product tabela pode mudar ao longo do tempo
  • price – produto de quantity_sold e price_per_unit; uma pequena redundância que nos ajuda a evitar esse cálculo nas consultas. Geralmente, a soma de todos os preços dos itens pertencentes à mesma venda deve ser igual ao sale.sale_amount
  • tax_amount – valor do imposto para esse item no recebimento
  • sale_id – id de venda a que este item pertence
  • product_id – ID do produto relacionado a este item

Agora poderíamos facilmente fazer um relatório simples, quantos produtos/serviços vendemos no período e a que preço.

SELECT product.name, SUM(sale_item.quantity_sold) AS quantity, 
       SUM(sale_item.price) AS price
FROM sale, sale_item, product
WHERE sale.id = sale_item.sale_id
AND sale_item.product_id = product.id
AND sale.time_created >= @start_time 
AND sale.time_created <= @end_time
GROUP BY product.id