Implantação da função de controle de consolidaçoes pagas e pendentes
This commit is contained in:
47
app/views/consolidacao_mailer/pagamento_efetuado.html.erb
Normal file
47
app/views/consolidacao_mailer/pagamento_efetuado.html.erb
Normal file
@@ -0,0 +1,47 @@
|
||||
<%# app/views/consolidacao_mailer/pagamento_efetuado.html.erb %>
|
||||
<div style="font-family: Arial, sans-serif; max-width: 520px; margin: 0 auto; background: #0a0a0a; border-radius: 12px; overflow: hidden;">
|
||||
|
||||
<div style="background: #0a0a0a; padding: 24px; border-left: 6px solid #f97316;">
|
||||
<h1 style="color: #ffffff; margin: 0; font-size: 20px;">REEM TRANSPORTE</h1>
|
||||
<p style="color: #f97316; margin: 4px 0 0; font-size: 13px;">Sistema de Logística</p>
|
||||
</div>
|
||||
|
||||
<div style="background: #ffffff; padding: 28px;">
|
||||
<h2 style="color: #0a0a0a; margin-top: 0;">Olá, <%= @user.nome.split.first %>! ✅</h2>
|
||||
|
||||
<p style="color: #374151; font-size: 15px; line-height: 1.6;">
|
||||
Seu pagamento de entregas foi <strong>efetuado</strong> pela empresa.
|
||||
</p>
|
||||
|
||||
<table style="width: 100%; margin: 20px 0; border-collapse: collapse;">
|
||||
<tr>
|
||||
<td style="background: #f3f4f6; padding: 10px 14px; font-weight: bold; color: #374151;">Período</td>
|
||||
<td style="padding: 10px 14px; color: #0a0a0a;"><%= @consolidacao.nome %></td>
|
||||
</tr>
|
||||
<% if @forma.present? %>
|
||||
<tr>
|
||||
<td style="background: #f3f4f6; padding: 10px 14px; font-weight: bold; color: #374151;">Forma</td>
|
||||
<td style="padding: 10px 14px; color: #0a0a0a;"><%= @forma.to_s.humanize %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
<div style="background: #22c55e; border-radius: 10px; padding: 20px; text-align: center; margin: 20px 0;">
|
||||
<p style="color: rgba(0,0,0,0.6); margin: 0; font-size: 12px; font-weight: bold;">VALOR PAGO</p>
|
||||
<p style="color: #0a0a0a; margin: 6px 0 0; font-size: 32px; font-weight: 900;">
|
||||
R$ <%= format('%.2f', @valor).gsub('.', ',') %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p style="text-align: center; margin: 24px 0;">
|
||||
<a href="<%= @link_painel %>"
|
||||
style="background: #0a0a0a; color: #f97316; text-decoration: none; padding: 14px 28px; border-radius: 8px; font-weight: bold; display: inline-block;">
|
||||
Ver meu painel e baixar holerite →
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p style="color: #9ca3af; font-size: 12px; text-align: center;">
|
||||
Entre com seu PIN de 4 números ou escaneie o QR Code do seu holerite.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<%# ── Filtros ──────────────────────────────────────────── %>
|
||||
<%= form_with url: consolidacoes_path, method: :get,
|
||||
class: 'bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4 mb-6 grid grid-cols-1 md:grid-cols-5 gap-3' do |f| %>
|
||||
class: 'bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4 mb-6 grid grid-cols-1 md:grid-cols-6 gap-3' do |f| %>
|
||||
<%= f.text_field :nome, value: params[:nome], placeholder: 'Buscar por nome…',
|
||||
class: 'bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-2.5 focus:border-orange-500 focus:outline-none' %>
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
options_for_select([['Todos os status', ''], ['📝 Rascunho', 'rascunho'], ['✅ Finalizada', 'finalizada']], params[:status]),
|
||||
{}, class: 'bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-2.5' %>
|
||||
|
||||
<%= f.select :pagamento,
|
||||
options_for_select([['💵 Pagamento (todos)', ''], ['💰 Pagas', 'pago'], ['⏳ Parciais', 'parcial'], ['🕗 Pendentes', 'pendente']], params[:pagamento]),
|
||||
{}, class: 'bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-2.5' %>
|
||||
|
||||
<%= f.date_field :inicio, value: params[:inicio],
|
||||
class: 'bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-2.5' %>
|
||||
|
||||
@@ -44,6 +48,7 @@
|
||||
<div class="flex items-center gap-3 mb-1">
|
||||
<h3 class="text-white font-bold text-lg"><%= c.nome %></h3>
|
||||
<%= badge_status(c.status) %>
|
||||
<% if c.finalizada? %><%= badge_pagamento(c.status_pagamento) %><% end %>
|
||||
</div>
|
||||
<p class="text-gray-400 text-sm">
|
||||
📅 <%= l c.data_inicio, format: :short %> → <%= l c.data_fim, format: :short %>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<%# app/views/consolidacoes/show.html.erb %>
|
||||
<% content_for :title, @consolidacao.nome %>
|
||||
<% formas_pagamento = [['PIX', 'pix'], ['Transferência', 'transferencia'], ['Dinheiro', 'dinheiro']] %>
|
||||
<% pode_pagar = @consolidacao.finalizada? && policy(@consolidacao).registrar_pagamento? %>
|
||||
|
||||
<div class="max-w-4xl mx-auto">
|
||||
|
||||
@@ -7,9 +9,10 @@
|
||||
<%= link_to '← Consolidações', consolidacoes_path, class: 'text-gray-500 hover:text-orange-500 text-sm' %>
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3 mt-2">
|
||||
<div>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex items-center gap-3 flex-wrap">
|
||||
<h1 class="text-2xl font-bold text-white"><%= @consolidacao.nome %></h1>
|
||||
<%= badge_status(@consolidacao.status) %>
|
||||
<% if @consolidacao.finalizada? %><%= badge_pagamento(@consolidacao.status_pagamento) %><% end %>
|
||||
</div>
|
||||
<p class="text-gray-400 text-sm mt-1">
|
||||
📅 <%= l @consolidacao.data_inicio, format: :short %> → <%= l @consolidacao.data_fim, format: :short %>
|
||||
@@ -31,6 +34,28 @@
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── Pagamento da operação inteira ─────────────────────── %>
|
||||
<% if pode_pagar %>
|
||||
<div class="flex flex-col sm:flex-row sm:items-center gap-2 mt-4 bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4">
|
||||
<span class="text-gray-400 text-sm font-medium mr-1">💵 Operação inteira:</span>
|
||||
<% if @consolidacao.status_pagamento != :pago %>
|
||||
<%= form_with url: registrar_pagamento_consolidacao_path(@consolidacao), method: :post,
|
||||
data: { turbo_confirm: 'Marcar TODOS os motoristas pendentes desta consolidação como PAGOS?' },
|
||||
class: 'flex items-center gap-2' do |f| %>
|
||||
<%= f.select :forma_pagamento, options_for_select(formas_pagamento, 'pix'),
|
||||
{}, class: 'bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-2.5 text-sm' %>
|
||||
<%= f.submit '💰 Marcar tudo como pago',
|
||||
class: 'bg-green-600 hover:bg-green-700 text-white font-bold px-4 py-2.5 rounded-lg text-sm cursor-pointer min-h-[44px]' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if @consolidacao.status_pagamento != :pendente %>
|
||||
<%= button_to '↩ Estornar tudo', cancelar_pagamento_consolidacao_path(@consolidacao), method: :post,
|
||||
data: { turbo_confirm: 'Estornar o pagamento de TODOS os motoristas?' },
|
||||
class: 'text-gray-400 hover:text-white border border-[#2a2a2a] px-4 py-2.5 rounded-lg text-sm min-h-[44px]' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# Total geral %>
|
||||
@@ -46,8 +71,39 @@
|
||||
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-5">
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
||||
<div>
|
||||
<p class="text-white font-bold text-lg"><%= cm.motorista_nome %></p>
|
||||
<div class="flex items-center gap-2 flex-wrap">
|
||||
<p class="text-white font-bold text-lg"><%= cm.motorista_nome %></p>
|
||||
<% if @consolidacao.finalizada? %>
|
||||
<%= badge_pagamento(cm.pago? ? :pago : :pendente) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<p class="text-orange-500 font-black text-xl"><%= moeda(cm.valor_total) %></p>
|
||||
<% if cm.pago? %>
|
||||
<p class="text-green-400 text-xs mt-1">
|
||||
💰 Pago em <%= l cm.pago_em, format: :short %>
|
||||
<% if cm.forma_pagamento.present? %>via <%= cm.forma_pagamento.humanize %><% end %>
|
||||
<% if cm.pagador.present? %>por <%= cm.pagador.nome_display %><% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if pode_pagar %>
|
||||
<div class="mt-2">
|
||||
<% if cm.pago? %>
|
||||
<%= button_to '↩ Estornar pagamento', cancelar_pagamento_consolidacao_path(@consolidacao, consolidacao_motorista_id: cm.id), method: :post,
|
||||
data: { turbo_confirm: "Estornar o pagamento de #{cm.motorista_nome}?" },
|
||||
class: 'text-gray-400 hover:text-white border border-[#2a2a2a] px-3 py-2 rounded-lg text-xs min-h-[40px]' %>
|
||||
<% else %>
|
||||
<%= form_with url: registrar_pagamento_consolidacao_path(@consolidacao, consolidacao_motorista_id: cm.id), method: :post,
|
||||
data: { turbo_confirm: "Marcar #{cm.motorista_nome} como pago?" },
|
||||
class: 'flex items-center gap-2' do |f| %>
|
||||
<%= f.select :forma_pagamento, options_for_select(formas_pagamento, 'pix'),
|
||||
{}, class: 'bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-2 py-2 text-xs' %>
|
||||
<%= f.submit '💰 Marcar pago',
|
||||
class: 'bg-green-600 hover:bg-green-700 text-white font-bold px-3 py-2 rounded-lg text-xs cursor-pointer min-h-[40px]' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<%# Preview abre modal %>
|
||||
|
||||
@@ -138,6 +138,79 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── PAGAMENTOS (pago x pendente) ──────────────────────── %>
|
||||
<div class="grid grid-cols-1 xl:grid-cols-3 gap-4">
|
||||
|
||||
<%# Rosca pago vs a pagar (por valor) %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<h2 class="text-lg font-semibold text-white mb-1">💵 Pagamentos</h2>
|
||||
<p class="text-gray-400 text-sm mb-4">Consolidações finalizadas no período</p>
|
||||
|
||||
<% if (@pag_pago_qtd + @pag_pend_qtd).zero? %>
|
||||
<div class="text-center py-8 text-gray-500">
|
||||
<div class="text-3xl mb-2">🧾</div>
|
||||
<p class="text-sm">Nenhuma consolidação finalizada no período</p>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="relative h-44 mb-4">
|
||||
<canvas id="grafico-pagamentos"></canvas>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<span class="text-green-400">● Pago</span>
|
||||
<span class="text-white font-semibold">
|
||||
<%= moeda(@pag_pago_valor) %> · <%= @pag_pago_qtd %> motorista(s)
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<span class="text-gray-400">● A pagar</span>
|
||||
<span class="text-white font-semibold">
|
||||
<%= moeda(@pag_pend_valor) %> · <%= @pag_pend_qtd %> motorista(s)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# Tabela de consolidações com status de pagamento %>
|
||||
<div class="xl:col-span-2 bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<h2 class="text-lg font-semibold text-white mb-4">📋 Status de pagamento por consolidação</h2>
|
||||
|
||||
<% if @tabela_pagamentos.any? %>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="text-gray-500 text-left border-b border-white/5">
|
||||
<th class="py-2 pr-3 font-medium">Consolidação</th>
|
||||
<th class="py-2 px-3 font-medium">Status</th>
|
||||
<th class="py-2 px-3 font-medium text-right">Pago</th>
|
||||
<th class="py-2 pl-3 font-medium text-right">A pagar</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @tabela_pagamentos.each do |linha| %>
|
||||
<tr class="border-b border-white/5">
|
||||
<td class="py-2.5 pr-3">
|
||||
<%= link_to linha[:consolidacao].nome, consolidacao_path(linha[:consolidacao]),
|
||||
class: 'text-white hover:text-orange-500 font-medium' %>
|
||||
</td>
|
||||
<td class="py-2.5 px-3"><%= badge_pagamento(linha[:status]) %></td>
|
||||
<td class="py-2.5 px-3 text-right text-green-400"><%= moeda(linha[:pago]) %></td>
|
||||
<td class="py-2.5 pl-3 text-right text-gray-400"><%= moeda(linha[:pendente]) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-8 text-gray-500">
|
||||
<div class="text-3xl mb-2">📋</div>
|
||||
<p class="text-sm">Nenhuma consolidação finalizada no período</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# Por operação %>
|
||||
<% if @por_operacao.any? %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
@@ -271,3 +344,47 @@
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<%# Rosca de pagamentos (pago x a pagar, por valor) %>
|
||||
<script>
|
||||
(function () {
|
||||
const ctx = document.getElementById('grafico-pagamentos');
|
||||
if (!ctx || typeof Chart === 'undefined') return;
|
||||
Chart.getChart(ctx)?.destroy();
|
||||
|
||||
const pago = <%= @pag_pago_valor.to_f %>;
|
||||
const aPagar = <%= @pag_pend_valor.to_f %>;
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ['Pago', 'A pagar'],
|
||||
datasets: [{
|
||||
data: [pago, aPagar],
|
||||
backgroundColor: ['#22c55e', '#374151'],
|
||||
borderColor: '#1a1a1a',
|
||||
borderWidth: 3
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
cutout: '62%',
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
backgroundColor: '#0a0a0a',
|
||||
borderColor: '#22c55e',
|
||||
borderWidth: 1,
|
||||
titleColor: '#9ca3af',
|
||||
bodyColor: '#ffffff',
|
||||
padding: 12,
|
||||
callbacks: {
|
||||
label: (c) => ` ${c.label}: R$ ${c.parsed.toFixed(2).replace('.', ',')}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -6,6 +6,27 @@
|
||||
<h1 class="text-2xl font-bold text-white mb-1">Olá, <%= current_user.nome.split.first %>! 👋</h1>
|
||||
<p class="text-gray-400 mb-6">Aqui estão seus valores de entregas.</p>
|
||||
|
||||
<%# ── Aviso de pagamento recém-confirmado ───────────────── %>
|
||||
<% if @pagamentos_recentes.any? %>
|
||||
<div class="bg-green-600/15 border border-green-600/40 rounded-2xl p-5 mb-6">
|
||||
<p class="text-green-400 font-bold text-sm uppercase tracking-wide mb-2">✅ Pagamento confirmado!</p>
|
||||
<div class="space-y-2">
|
||||
<% @pagamentos_recentes.each do |cm| %>
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-1">
|
||||
<p class="text-white text-sm">
|
||||
Você recebeu <span class="font-black text-green-400"><%= moeda(cm.valor_total) %></span>
|
||||
pela consolidação <span class="font-semibold"><%= cm.consolidacao.nome %></span>
|
||||
</p>
|
||||
<p class="text-gray-400 text-xs">
|
||||
💰 <%= l cm.pago_em.to_date, format: :short %>
|
||||
<% if cm.forma_pagamento.present? %>· <%= cm.forma_pagamento.humanize %><% end %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%# ── 2 Cards grandes ─────────────────────────────────── %>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||
|
||||
@@ -41,14 +62,23 @@
|
||||
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-5">
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-3">
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex items-center gap-2 flex-wrap">
|
||||
<p class="text-white font-bold"><%= c.nome %></p>
|
||||
<%= badge_status(c.status) %>
|
||||
<% if c.finalizada? %>
|
||||
<%= badge_pagamento(cm&.pago? ? :pago : :pendente) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<p class="text-gray-400 text-sm mt-1">
|
||||
📅 <%= l c.data_inicio, format: :short %> a <%= l c.data_fim, format: :short %>
|
||||
</p>
|
||||
<p class="text-orange-500 font-black text-xl mt-1"><%= moeda(cm&.valor_total || 0) %></p>
|
||||
<% if cm&.pago? %>
|
||||
<p class="text-green-400 text-xs mt-1">
|
||||
💰 Pago em <%= l cm.pago_em.to_date, format: :short %>
|
||||
<% if cm.forma_pagamento.present? %>via <%= cm.forma_pagamento.humanize %><% end %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if c.finalizada? %>
|
||||
<%= link_to '⬇️ Baixar meu holerite',
|
||||
|
||||
Reference in New Issue
Block a user