Saltar para o conteúdo
PMPaulo Mota
Voltar à demo

Como foi feito

Orçamentos, por dentro

Três decisões: a composição separada em material, horas e equipamento; a linha que guarda uma cópia do preço no momento em que entrou; e o estado que fecha a porta quando o orçamento sai para o cliente.

01

O problema

Quase toda a gente orçamenta em folha de cálculo, e quase toda a gente perde a folha. Pior: a folha mistura material e mão de obra numa célula só, e no fim da obra ninguém consegue dizer se se perdeu dinheiro no material, nas horas ou na máquina. Sem os três separados, orçado contra real é uma conta que não se faz, e é por isso que este sistema começa pela composição e não pelo PDF.

02

As tabelas

Quatro coisas. A base de custos é partilhada com a folha de obra de propósito: o mesmo artigo que se orçamenta é o que se lança em campo, e por isso as duas pontas falam a mesma língua.

TabelaPara que serve
obra_cost_itemsA base de custos. Material, horas e equipamento por unidade, separados. Partilhada com a folha de obra.
obra_quotesCabeçalho: cliente, obra, estado, margem, IVA, validade.
obra_quote_linesA medição e uma cópia da composição no momento em que a linha entrou.
demo_rooms.obra_hourly_centsA hora com que a empresa orçamenta. Vive na sala porque é decisão da empresa.
03

A linha guarda o preço

Uma linha de orçamento não aponta para o preço de hoje: guarda uma cópia da composição no momento em que entrou. Se o cimento subir amanhã, um orçamento já enviado continua a dizer o que dizia quando o cliente o leu. Enquanto é rascunho há uma função que o actualiza de propósito, e que devolve quantas linhas mexeu, para ninguém ser surpreendido em silêncio.

sql
-- A linha guarda o que o artigo custava quando entrou.
-- Se o cimento subir amanhã, um orçamento já assinado não muda
-- debaixo dos pés de quem o assinou.
insert into obra_quote_lines
  (quote_id, cost_item_id, code_snapshot, name_snapshot, unit, category,
   qty, material_cents, labour_hours, equipment_cents, hourly_cents)
values
  (p_quote, v_i.id, v_i.code, v_i.name_pt, v_i.unit, v_i.category,
   round(p_qty, 3), v_i.material_cents, v_i.labour_hours,
   v_i.equipment_cents, obra_room_hourly(p_room));
04

As contas nascem no servidor

O browser manda o artigo e a medição. Custo directo, margem, IVA e total saem de uma função, e a mesma função devolve as contas de todos os orçamentos da sala de uma vez, para a lista não fazer uma consulta por linha. Mexer a margem no ecrã mostra o total a andar, mas só grava quando se larga: um slider a escrever a cada pixel é uma escrita por pixel.

sql
-- Uma chamada devolve as contas de todos os orçamentos da sala.
-- O ecrã da lista não faz uma consulta por linha.
select id,
       (mat + lab + eqp)                                   as direct_cents,
       round((mat + lab + eqp) * margin_pct / 100)         as margin_cents,
       (mat + lab + eqp)
         + round((mat + lab + eqp) * margin_pct / 100)     as net_cents
  from (select q.id, q.margin_pct,
               sum(round(l.qty * l.material_cents))                  as mat,
               sum(round(l.qty * l.labour_hours * l.hourly_cents))   as lab,
               sum(round(l.qty * l.equipment_cents))                 as eqp
          from obra_quotes q
          left join obra_quote_lines l on l.quote_id = q.id
         where q.room_code = p_room
         group by q.id, q.margin_pct) base;
05

O estado fecha a porta

Rascunho, enviado, adjudicado ou perdido, e não se anda para trás. A regra de que um orçamento enviado já não muda de linhas está dentro do update, não dentro do botão: um ecrã velho aberto noutro separador não a contorna, porque a condição corre na base de dados e devolve zero linhas se não bater certo.

sql
-- Um orçamento enviado já não muda de linhas. A regra está no
-- update, não no botão: um ecrã velho noutro separador não a contorna.
update obra_quotes set margin_pct = round(p_pct, 2)
 where id = p_quote and room_code = p_room and status = 'rascunho'
returning * into v_row;
if not found then raise exception 'orcamento fechado'; end if;
06

O que faria diferente num cliente real

PDF com a folha de medições e as condições de pagamento, gerado no servidor e enviado por email com registo de abertura. Versões do orçamento, para saber o que mudou entre a proposta e a revisão que o cliente assinou. Revisão de preços indexada, que numa obra longa é dinheiro a sério. E autenticação: aqui qualquer visitante adjudica um orçamento; num negócio real, só quem pode.