Este commit introduz o módulo financeiro completo e refatora o sistema de profissionais para suportar múltiplas funções, corrigindo a contabilização e validação de equipes. Principais alterações: - **Módulo Financeiro:** - Criação da tabela `financial_transactions` e queries associadas. - Implementação do backend (Handler/Service) para gerenciar transações. - Nova página [Finance.tsx](cci:7://file:///c:/Projetos/photum/frontend/pages/Finance.tsx:0:0-0:0) com listagem, edição, filtros avançados e agrupamento por FOT. - Correção na busca de FOTs e formatação de datas. - **Gestão de Equipe e Profissionais:** - Refatoração para suportar múltiplas funções por profissional (Backend & Frontend). - Atualização do [Dashboard](cci:1://file:///c:/Projetos/photum/frontend/pages/Dashboard.tsx:31:0-1663:2) e [EventTable](cci:1://file:///c:/Projetos/photum/frontend/components/EventTable.tsx:28:0-659:2) para contabilizar corretamente profissionais (Fotografo, Cinegrafista, Recepcionista) verificando a lista de funções. - Implementação de validação de cota no aceite de convites (bloqueia se a equipe da função específica já estiver completa). - Ajuste visual nos indicadores de "Equipe Completa" e contadores de faltantes na listagem de eventos. - **Geral:** - Atualização da documentação Swagger. - Ajustes de tipagem e migrações de banco de dados.
111 lines
3.4 KiB
Go
111 lines
3.4 KiB
Go
package finance
|
|
|
|
import (
|
|
"context"
|
|
"photum-backend/internal/db/generated"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
type Service struct {
|
|
queries *generated.Queries
|
|
}
|
|
|
|
func NewService(queries *generated.Queries) *Service {
|
|
return &Service{queries: queries}
|
|
}
|
|
|
|
func (s *Service) Create(ctx context.Context, params generated.CreateTransactionParams) (generated.FinancialTransaction, error) {
|
|
txn, err := s.queries.CreateTransaction(ctx, params)
|
|
if err != nil {
|
|
return generated.FinancialTransaction{}, err
|
|
}
|
|
|
|
if params.FotID.Valid {
|
|
_ = s.updateFotExpenses(ctx, params.FotID)
|
|
}
|
|
|
|
return txn, nil
|
|
}
|
|
|
|
func (s *Service) Update(ctx context.Context, params generated.UpdateTransactionParams) (generated.FinancialTransaction, error) {
|
|
txn, err := s.queries.UpdateTransaction(ctx, params)
|
|
if err != nil {
|
|
return generated.FinancialTransaction{}, err
|
|
}
|
|
|
|
// Recalculate for the new FOT (if changed, we should technically recalc old one too, but simpler for now)
|
|
if params.FotID.Valid {
|
|
_ = s.updateFotExpenses(ctx, params.FotID)
|
|
}
|
|
return txn, nil
|
|
}
|
|
|
|
func (s *Service) Delete(ctx context.Context, id pgtype.UUID) error {
|
|
// First fetch to get FotID
|
|
txn, err := s.queries.GetTransaction(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = s.queries.DeleteTransaction(ctx, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if txn.FotID.Valid {
|
|
_ = s.updateFotExpenses(ctx, txn.FotID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) ListByFot(ctx context.Context, fotID pgtype.UUID) ([]generated.FinancialTransaction, error) {
|
|
return s.queries.ListTransactionsByFot(ctx, fotID)
|
|
}
|
|
|
|
func (s *Service) ListAll(ctx context.Context) ([]generated.ListTransactionsRow, error) {
|
|
return s.queries.ListTransactions(ctx)
|
|
}
|
|
|
|
func (s *Service) AutoFillSearch(ctx context.Context, fotNumber int32) (generated.GetCadastroFotByFotJoinRow, error) {
|
|
return s.queries.GetCadastroFotByFotJoin(ctx, fotNumber)
|
|
}
|
|
|
|
func (s *Service) ListFotEvents(ctx context.Context, fotID pgtype.UUID) ([]generated.ListAgendasByFotRow, error) {
|
|
return s.queries.ListAgendasByFot(ctx, fotID)
|
|
}
|
|
|
|
func (s *Service) SearchProfessionals(ctx context.Context, query string) ([]generated.SearchProfissionaisRow, error) {
|
|
return s.queries.SearchProfissionais(ctx, pgtype.Text{String: query, Valid: true})
|
|
}
|
|
|
|
func (s *Service) SearchProfessionalsByFunction(ctx context.Context, query string, functionName string) ([]generated.SearchProfissionaisByFunctionRow, error) {
|
|
return s.queries.SearchProfissionaisByFunction(ctx, generated.SearchProfissionaisByFunctionParams{
|
|
Column1: pgtype.Text{String: query, Valid: true}, // $1 - Name
|
|
Nome: functionName, // $2 - Function Name
|
|
})
|
|
}
|
|
|
|
func (s *Service) GetStandardPrice(ctx context.Context, eventName string, serviceName string) (pgtype.Numeric, error) {
|
|
// serviceName here is the Function Name (e.g. Fotógrafo)
|
|
return s.queries.GetStandardPrice(ctx, generated.GetStandardPriceParams{
|
|
Nome: eventName, // $1 - Event Name
|
|
Nome_2: serviceName, // $2 - Function Name
|
|
})
|
|
}
|
|
|
|
func (s *Service) SearchFot(ctx context.Context, query string) ([]generated.SearchFotRow, error) {
|
|
return s.queries.SearchFot(ctx, pgtype.Text{String: query, Valid: true})
|
|
}
|
|
|
|
func (s *Service) updateFotExpenses(ctx context.Context, fotID pgtype.UUID) error {
|
|
total, err := s.queries.SumTotalByFot(ctx, fotID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.queries.UpdateCadastroFotGastos(ctx, generated.UpdateCadastroFotGastosParams{
|
|
ID: fotID,
|
|
GastosCaptacao: total,
|
|
})
|
|
}
|