feat(backend): implementa módulo Agenda com lógica automática de status
- Cria tabela 'agenda' com FKs normalizadas e colunas específicas de evento - Gera operações CRUD via SQLC para Agenda - Implementa Service e Handler da Agenda - Adiciona cálculo automático de 'status_profissionais' (OK/FALTA/ERRO) baseado na contagem de faltantes - Registra rotas da Agenda em /api/agenda - Atualiza documentação Swagger - Corrige caminhos de importação e tipagem UUID no novo serviço
This commit is contained in:
parent
d84d6ff022
commit
a1a4d0a5d1
11 changed files with 1764 additions and 0 deletions
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
|
||||
"photum-backend/docs"
|
||||
"photum-backend/internal/agenda"
|
||||
"photum-backend/internal/anos_formaturas"
|
||||
"photum-backend/internal/auth"
|
||||
"photum-backend/internal/cadastro_fot"
|
||||
|
|
@ -68,6 +69,7 @@ func main() {
|
|||
tiposServicosService := tipos_servicos.NewService(queries)
|
||||
tiposEventosService := tipos_eventos.NewService(queries)
|
||||
cadastroFotService := cadastro_fot.NewService(queries)
|
||||
agendaService := agenda.NewService(queries)
|
||||
|
||||
// Seed Demo Users
|
||||
if err := authService.EnsureDemoUsers(context.Background()); err != nil {
|
||||
|
|
@ -84,6 +86,7 @@ func main() {
|
|||
tiposServicosHandler := tipos_servicos.NewHandler(tiposServicosService)
|
||||
tiposEventosHandler := tipos_eventos.NewHandler(tiposEventosService)
|
||||
cadastroFotHandler := cadastro_fot.NewHandler(cadastroFotService)
|
||||
agendaHandler := agenda.NewHandler(agendaService)
|
||||
|
||||
r := gin.Default()
|
||||
|
||||
|
|
@ -182,6 +185,12 @@ func main() {
|
|||
api.PUT("/cadastro-fot/:id", cadastroFotHandler.Update)
|
||||
api.DELETE("/cadastro-fot/:id", cadastroFotHandler.Delete)
|
||||
|
||||
api.GET("/agenda", agendaHandler.List)
|
||||
api.POST("/agenda", agendaHandler.Create)
|
||||
api.GET("/agenda/:id", agendaHandler.Get)
|
||||
api.PUT("/agenda/:id", agendaHandler.Update)
|
||||
api.DELETE("/agenda/:id", agendaHandler.Delete)
|
||||
|
||||
admin := api.Group("/admin")
|
||||
{
|
||||
admin.GET("/users", authHandler.ListUsers)
|
||||
|
|
|
|||
|
|
@ -410,6 +410,247 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/agenda": {
|
||||
"get": {
|
||||
"description": "List all agenda events with details",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "List all agenda events",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create a new agenda event",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Create a new agenda event",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Create Agenda Request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/agenda.CreateAgendaRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/agenda/{id}": {
|
||||
"get": {
|
||||
"description": "Get agenda event details by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Get agenda event by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Agenda ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"description": "Update agenda event by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Update agenda event",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Agenda ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update Agenda Request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/agenda.CreateAgendaRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete agenda event by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Delete agenda event",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Agenda ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/anos-formaturas": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -2164,6 +2405,80 @@ const docTemplate = `{
|
|||
}
|
||||
},
|
||||
"definitions": {
|
||||
"agenda.CreateAgendaRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cine_faltante": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data_evento": {
|
||||
"type": "string"
|
||||
},
|
||||
"endereco": {
|
||||
"type": "string"
|
||||
},
|
||||
"fot_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"foto_faltante": {
|
||||
"type": "integer"
|
||||
},
|
||||
"horario": {
|
||||
"type": "string"
|
||||
},
|
||||
"local_evento": {
|
||||
"type": "string"
|
||||
},
|
||||
"logistica_observacoes": {
|
||||
"type": "string"
|
||||
},
|
||||
"observacoes_evento": {
|
||||
"type": "string"
|
||||
},
|
||||
"pre_venda": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"qtd_cinegrafistas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_estudios": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_formandos": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_fotografos": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_plataforma_360": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_ponto_decorado": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_ponto_foto": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_ponto_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_pontos_led": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_recepcionistas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"recep_faltante": {
|
||||
"type": "integer"
|
||||
},
|
||||
"status_profissionais": {
|
||||
"type": "string"
|
||||
},
|
||||
"tipo_evento_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"anos_formaturas.AnoFormaturaResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -404,6 +404,247 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/agenda": {
|
||||
"get": {
|
||||
"description": "List all agenda events with details",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "List all agenda events",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create a new agenda event",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Create a new agenda event",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Create Agenda Request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/agenda.CreateAgendaRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/agenda/{id}": {
|
||||
"get": {
|
||||
"description": "Get agenda event details by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Get agenda event by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Agenda ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"description": "Update agenda event by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Update agenda event",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Agenda ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update Agenda Request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/agenda.CreateAgendaRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete agenda event by ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"agenda"
|
||||
],
|
||||
"summary": "Delete agenda event",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Agenda ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/anos-formaturas": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -2158,6 +2399,80 @@
|
|||
}
|
||||
},
|
||||
"definitions": {
|
||||
"agenda.CreateAgendaRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cine_faltante": {
|
||||
"type": "integer"
|
||||
},
|
||||
"data_evento": {
|
||||
"type": "string"
|
||||
},
|
||||
"endereco": {
|
||||
"type": "string"
|
||||
},
|
||||
"fot_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"foto_faltante": {
|
||||
"type": "integer"
|
||||
},
|
||||
"horario": {
|
||||
"type": "string"
|
||||
},
|
||||
"local_evento": {
|
||||
"type": "string"
|
||||
},
|
||||
"logistica_observacoes": {
|
||||
"type": "string"
|
||||
},
|
||||
"observacoes_evento": {
|
||||
"type": "string"
|
||||
},
|
||||
"pre_venda": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"qtd_cinegrafistas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_estudios": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_formandos": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_fotografos": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_plataforma_360": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_ponto_decorado": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_ponto_foto": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_ponto_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_pontos_led": {
|
||||
"type": "integer"
|
||||
},
|
||||
"qtd_recepcionistas": {
|
||||
"type": "integer"
|
||||
},
|
||||
"recep_faltante": {
|
||||
"type": "integer"
|
||||
},
|
||||
"status_profissionais": {
|
||||
"type": "string"
|
||||
},
|
||||
"tipo_evento_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"anos_formaturas.AnoFormaturaResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,54 @@
|
|||
basePath: /
|
||||
definitions:
|
||||
agenda.CreateAgendaRequest:
|
||||
properties:
|
||||
cine_faltante:
|
||||
type: integer
|
||||
data_evento:
|
||||
type: string
|
||||
endereco:
|
||||
type: string
|
||||
fot_id:
|
||||
type: string
|
||||
foto_faltante:
|
||||
type: integer
|
||||
horario:
|
||||
type: string
|
||||
local_evento:
|
||||
type: string
|
||||
logistica_observacoes:
|
||||
type: string
|
||||
observacoes_evento:
|
||||
type: string
|
||||
pre_venda:
|
||||
type: boolean
|
||||
qtd_cinegrafistas:
|
||||
type: integer
|
||||
qtd_estudios:
|
||||
type: integer
|
||||
qtd_formandos:
|
||||
type: integer
|
||||
qtd_fotografos:
|
||||
type: integer
|
||||
qtd_plataforma_360:
|
||||
type: integer
|
||||
qtd_ponto_decorado:
|
||||
type: integer
|
||||
qtd_ponto_foto:
|
||||
type: integer
|
||||
qtd_ponto_id:
|
||||
type: integer
|
||||
qtd_pontos_led:
|
||||
type: integer
|
||||
qtd_recepcionistas:
|
||||
type: integer
|
||||
recep_faltante:
|
||||
type: integer
|
||||
status_profissionais:
|
||||
type: string
|
||||
tipo_evento_id:
|
||||
type: string
|
||||
type: object
|
||||
anos_formaturas.AnoFormaturaResponse:
|
||||
properties:
|
||||
ano_semestre:
|
||||
|
|
@ -650,6 +699,167 @@ paths:
|
|||
summary: List pending users
|
||||
tags:
|
||||
- admin
|
||||
/api/agenda:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: List all agenda events with details
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
type: array
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
summary: List all agenda events
|
||||
tags:
|
||||
- agenda
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Create a new agenda event
|
||||
parameters:
|
||||
- description: Create Agenda Request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/agenda.CreateAgendaRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
summary: Create a new agenda event
|
||||
tags:
|
||||
- agenda
|
||||
/api/agenda/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Delete agenda event by ID
|
||||
parameters:
|
||||
- description: Agenda ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
summary: Delete agenda event
|
||||
tags:
|
||||
- agenda
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get agenda event details by ID
|
||||
parameters:
|
||||
- description: Agenda ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
summary: Get agenda event by ID
|
||||
tags:
|
||||
- agenda
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Update agenda event by ID
|
||||
parameters:
|
||||
- description: Agenda ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Update Agenda Request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/agenda.CreateAgendaRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
summary: Update agenda event
|
||||
tags:
|
||||
- agenda
|
||||
/api/anos-formaturas:
|
||||
get:
|
||||
consumes:
|
||||
|
|
|
|||
152
backend/internal/agenda/handler.go
Normal file
152
backend/internal/agenda/handler.go
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
package agenda
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewHandler(service *Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
// Create godoc
|
||||
// @Summary Create a new agenda event
|
||||
// @Description Create a new agenda event
|
||||
// @Tags agenda
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body CreateAgendaRequest true "Create Agenda Request"
|
||||
// @Success 201 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/agenda [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateAgendaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Dados inválidos: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
agenda, err := h.service.Create(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro ao criar agenda: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, agenda)
|
||||
}
|
||||
|
||||
// List godoc
|
||||
// @Summary List all agenda events
|
||||
// @Description List all agenda events with details
|
||||
// @Tags agenda
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {array} map[string]interface{}
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/agenda [get]
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
agendas, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro ao listar agendas: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, agendas)
|
||||
}
|
||||
|
||||
// Get godoc
|
||||
// @Summary Get agenda event by ID
|
||||
// @Description Get agenda event details by ID
|
||||
// @Tags agenda
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Agenda ID"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/agenda/{id} [get]
|
||||
func (h *Handler) Get(c *gin.Context) {
|
||||
idParam := c.Param("id")
|
||||
id, err := uuid.Parse(idParam)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
agenda, err := h.service.Get(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro ao buscar agenda: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, agenda)
|
||||
}
|
||||
|
||||
// Update godoc
|
||||
// @Summary Update agenda event
|
||||
// @Description Update agenda event by ID
|
||||
// @Tags agenda
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Agenda ID"
|
||||
// @Param request body CreateAgendaRequest true "Update Agenda Request"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/agenda/{id} [put]
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
idParam := c.Param("id")
|
||||
id, err := uuid.Parse(idParam)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateAgendaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Dados inválidos: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
agenda, err := h.service.Update(c.Request.Context(), id, req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro ao atualizar agenda: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, agenda)
|
||||
}
|
||||
|
||||
// Delete godoc
|
||||
// @Summary Delete agenda event
|
||||
// @Description Delete agenda event by ID
|
||||
// @Tags agenda
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Agenda ID"
|
||||
// @Success 204 {object} nil
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/agenda/{id} [delete]
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
idParam := c.Param("id")
|
||||
id, err := uuid.Parse(idParam)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID inválido: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro ao deletar agenda: " + err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
136
backend/internal/agenda/service.go
Normal file
136
backend/internal/agenda/service.go
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
package agenda
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
queries *generated.Queries
|
||||
}
|
||||
|
||||
func NewService(db *generated.Queries) *Service {
|
||||
return &Service{queries: db}
|
||||
}
|
||||
|
||||
type CreateAgendaRequest struct {
|
||||
FotID uuid.UUID `json:"fot_id"`
|
||||
DataEvento time.Time `json:"data_evento"`
|
||||
TipoEventoID uuid.UUID `json:"tipo_evento_id"`
|
||||
ObservacoesEvento string `json:"observacoes_evento"`
|
||||
LocalEvento string `json:"local_evento"`
|
||||
Endereco string `json:"endereco"`
|
||||
Horario string `json:"horario"`
|
||||
QtdFormandos int32 `json:"qtd_formandos"`
|
||||
QtdFotografos int32 `json:"qtd_fotografos"`
|
||||
QtdRecepcionistas int32 `json:"qtd_recepcionistas"`
|
||||
QtdCinegrafistas int32 `json:"qtd_cinegrafistas"`
|
||||
QtdEstudios int32 `json:"qtd_estudios"`
|
||||
QtdPontoFoto int32 `json:"qtd_ponto_foto"`
|
||||
QtdPontoID int32 `json:"qtd_ponto_id"`
|
||||
QtdPontoDecorado int32 `json:"qtd_ponto_decorado"`
|
||||
QtdPontosLed int32 `json:"qtd_pontos_led"`
|
||||
QtdPlataforma360 int32 `json:"qtd_plataforma_360"`
|
||||
StatusProfissionais string `json:"status_profissionais"`
|
||||
FotoFaltante int32 `json:"foto_faltante"`
|
||||
RecepFaltante int32 `json:"recep_faltante"`
|
||||
CineFaltante int32 `json:"cine_faltante"`
|
||||
LogisticaObservacoes string `json:"logistica_observacoes"`
|
||||
PreVenda bool `json:"pre_venda"`
|
||||
}
|
||||
|
||||
func (s *Service) CalculateStatus(fotoFaltante, recepFaltante, cineFaltante int32) string {
|
||||
if fotoFaltante < 0 || recepFaltante < 0 || cineFaltante < 0 {
|
||||
return "ERRO"
|
||||
}
|
||||
|
||||
sum := fotoFaltante + recepFaltante + cineFaltante
|
||||
if sum == 0 {
|
||||
return "OK"
|
||||
} else if sum > 0 {
|
||||
return "FALTA"
|
||||
}
|
||||
|
||||
return "ERRO"
|
||||
}
|
||||
|
||||
func (s *Service) Create(ctx context.Context, req CreateAgendaRequest) (generated.Agenda, error) {
|
||||
status := s.CalculateStatus(req.FotoFaltante, req.RecepFaltante, req.CineFaltante)
|
||||
|
||||
params := generated.CreateAgendaParams{
|
||||
FotID: pgtype.UUID{Bytes: req.FotID, Valid: true},
|
||||
DataEvento: pgtype.Date{Time: req.DataEvento, Valid: true},
|
||||
TipoEventoID: pgtype.UUID{Bytes: req.TipoEventoID, Valid: true},
|
||||
ObservacoesEvento: pgtype.Text{String: req.ObservacoesEvento, Valid: req.ObservacoesEvento != ""},
|
||||
LocalEvento: pgtype.Text{String: req.LocalEvento, Valid: req.LocalEvento != ""},
|
||||
Endereco: pgtype.Text{String: req.Endereco, Valid: req.Endereco != ""},
|
||||
Horario: pgtype.Text{String: req.Horario, Valid: req.Horario != ""},
|
||||
QtdFormandos: pgtype.Int4{Int32: req.QtdFormandos, Valid: true},
|
||||
QtdFotografos: pgtype.Int4{Int32: req.QtdFotografos, Valid: true},
|
||||
QtdRecepcionistas: pgtype.Int4{Int32: req.QtdRecepcionistas, Valid: true},
|
||||
QtdCinegrafistas: pgtype.Int4{Int32: req.QtdCinegrafistas, Valid: true},
|
||||
QtdEstudios: pgtype.Int4{Int32: req.QtdEstudios, Valid: true},
|
||||
QtdPontoFoto: pgtype.Int4{Int32: req.QtdPontoFoto, Valid: true},
|
||||
QtdPontoID: pgtype.Int4{Int32: req.QtdPontoID, Valid: true},
|
||||
QtdPontoDecorado: pgtype.Int4{Int32: req.QtdPontoDecorado, Valid: true},
|
||||
QtdPontosLed: pgtype.Int4{Int32: req.QtdPontosLed, Valid: true},
|
||||
QtdPlataforma360: pgtype.Int4{Int32: req.QtdPlataforma360, Valid: true},
|
||||
StatusProfissionais: pgtype.Text{String: status, Valid: true},
|
||||
FotoFaltante: pgtype.Int4{Int32: req.FotoFaltante, Valid: true},
|
||||
RecepFaltante: pgtype.Int4{Int32: req.RecepFaltante, Valid: true},
|
||||
CineFaltante: pgtype.Int4{Int32: req.CineFaltante, Valid: true},
|
||||
LogisticaObservacoes: pgtype.Text{String: req.LogisticaObservacoes, Valid: req.LogisticaObservacoes != ""},
|
||||
PreVenda: pgtype.Bool{Bool: req.PreVenda, Valid: true},
|
||||
}
|
||||
|
||||
return s.queries.CreateAgenda(ctx, params)
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context) ([]generated.ListAgendasRow, error) {
|
||||
return s.queries.ListAgendas(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) Get(ctx context.Context, id uuid.UUID) (generated.Agenda, error) {
|
||||
return s.queries.GetAgenda(ctx, pgtype.UUID{Bytes: id, Valid: true})
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id uuid.UUID, req CreateAgendaRequest) (generated.Agenda, error) {
|
||||
status := s.CalculateStatus(req.FotoFaltante, req.RecepFaltante, req.CineFaltante)
|
||||
|
||||
params := generated.UpdateAgendaParams{
|
||||
ID: pgtype.UUID{Bytes: id, Valid: true},
|
||||
FotID: pgtype.UUID{Bytes: req.FotID, Valid: true},
|
||||
DataEvento: pgtype.Date{Time: req.DataEvento, Valid: true},
|
||||
TipoEventoID: pgtype.UUID{Bytes: req.TipoEventoID, Valid: true},
|
||||
ObservacoesEvento: pgtype.Text{String: req.ObservacoesEvento, Valid: req.ObservacoesEvento != ""},
|
||||
LocalEvento: pgtype.Text{String: req.LocalEvento, Valid: req.LocalEvento != ""},
|
||||
Endereco: pgtype.Text{String: req.Endereco, Valid: req.Endereco != ""},
|
||||
Horario: pgtype.Text{String: req.Horario, Valid: req.Horario != ""},
|
||||
QtdFormandos: pgtype.Int4{Int32: req.QtdFormandos, Valid: true},
|
||||
QtdFotografos: pgtype.Int4{Int32: req.QtdFotografos, Valid: true},
|
||||
QtdRecepcionistas: pgtype.Int4{Int32: req.QtdRecepcionistas, Valid: true},
|
||||
QtdCinegrafistas: pgtype.Int4{Int32: req.QtdCinegrafistas, Valid: true},
|
||||
QtdEstudios: pgtype.Int4{Int32: req.QtdEstudios, Valid: true},
|
||||
QtdPontoFoto: pgtype.Int4{Int32: req.QtdPontoFoto, Valid: true},
|
||||
QtdPontoID: pgtype.Int4{Int32: req.QtdPontoID, Valid: true},
|
||||
QtdPontoDecorado: pgtype.Int4{Int32: req.QtdPontoDecorado, Valid: true},
|
||||
QtdPontosLed: pgtype.Int4{Int32: req.QtdPontosLed, Valid: true},
|
||||
QtdPlataforma360: pgtype.Int4{Int32: req.QtdPlataforma360, Valid: true},
|
||||
StatusProfissionais: pgtype.Text{String: status, Valid: true},
|
||||
FotoFaltante: pgtype.Int4{Int32: req.FotoFaltante, Valid: true},
|
||||
RecepFaltante: pgtype.Int4{Int32: req.RecepFaltante, Valid: true},
|
||||
CineFaltante: pgtype.Int4{Int32: req.CineFaltante, Valid: true},
|
||||
LogisticaObservacoes: pgtype.Text{String: req.LogisticaObservacoes, Valid: req.LogisticaObservacoes != ""},
|
||||
PreVenda: pgtype.Bool{Bool: req.PreVenda, Valid: true},
|
||||
}
|
||||
return s.queries.UpdateAgenda(ctx, params)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id uuid.UUID) error {
|
||||
return s.queries.DeleteAgenda(ctx, pgtype.UUID{Bytes: id, Valid: true})
|
||||
}
|
||||
401
backend/internal/db/generated/agenda.sql.go
Normal file
401
backend/internal/db/generated/agenda.sql.go
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: agenda.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createAgenda = `-- name: CreateAgenda :one
|
||||
INSERT INTO agenda (
|
||||
fot_id,
|
||||
data_evento,
|
||||
tipo_evento_id,
|
||||
observacoes_evento,
|
||||
local_evento,
|
||||
endereco,
|
||||
horario,
|
||||
qtd_formandos,
|
||||
qtd_fotografos,
|
||||
qtd_recepcionistas,
|
||||
qtd_cinegrafistas,
|
||||
qtd_estudios,
|
||||
qtd_ponto_foto,
|
||||
qtd_ponto_id,
|
||||
qtd_ponto_decorado,
|
||||
qtd_pontos_led,
|
||||
qtd_plataforma_360,
|
||||
status_profissionais,
|
||||
foto_faltante,
|
||||
recep_faltante,
|
||||
cine_faltante,
|
||||
logistica_observacoes,
|
||||
pre_venda
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23
|
||||
) RETURNING id, fot_id, data_evento, tipo_evento_id, observacoes_evento, local_evento, endereco, horario, qtd_formandos, qtd_fotografos, qtd_recepcionistas, qtd_cinegrafistas, qtd_estudios, qtd_ponto_foto, qtd_ponto_id, qtd_ponto_decorado, qtd_pontos_led, qtd_plataforma_360, status_profissionais, foto_faltante, recep_faltante, cine_faltante, logistica_observacoes, pre_venda, criado_em, atualizado_em
|
||||
`
|
||||
|
||||
type CreateAgendaParams struct {
|
||||
FotID pgtype.UUID `json:"fot_id"`
|
||||
DataEvento pgtype.Date `json:"data_evento"`
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
ObservacoesEvento pgtype.Text `json:"observacoes_evento"`
|
||||
LocalEvento pgtype.Text `json:"local_evento"`
|
||||
Endereco pgtype.Text `json:"endereco"`
|
||||
Horario pgtype.Text `json:"horario"`
|
||||
QtdFormandos pgtype.Int4 `json:"qtd_formandos"`
|
||||
QtdFotografos pgtype.Int4 `json:"qtd_fotografos"`
|
||||
QtdRecepcionistas pgtype.Int4 `json:"qtd_recepcionistas"`
|
||||
QtdCinegrafistas pgtype.Int4 `json:"qtd_cinegrafistas"`
|
||||
QtdEstudios pgtype.Int4 `json:"qtd_estudios"`
|
||||
QtdPontoFoto pgtype.Int4 `json:"qtd_ponto_foto"`
|
||||
QtdPontoID pgtype.Int4 `json:"qtd_ponto_id"`
|
||||
QtdPontoDecorado pgtype.Int4 `json:"qtd_ponto_decorado"`
|
||||
QtdPontosLed pgtype.Int4 `json:"qtd_pontos_led"`
|
||||
QtdPlataforma360 pgtype.Int4 `json:"qtd_plataforma_360"`
|
||||
StatusProfissionais pgtype.Text `json:"status_profissionais"`
|
||||
FotoFaltante pgtype.Int4 `json:"foto_faltante"`
|
||||
RecepFaltante pgtype.Int4 `json:"recep_faltante"`
|
||||
CineFaltante pgtype.Int4 `json:"cine_faltante"`
|
||||
LogisticaObservacoes pgtype.Text `json:"logistica_observacoes"`
|
||||
PreVenda pgtype.Bool `json:"pre_venda"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateAgenda(ctx context.Context, arg CreateAgendaParams) (Agenda, error) {
|
||||
row := q.db.QueryRow(ctx, createAgenda,
|
||||
arg.FotID,
|
||||
arg.DataEvento,
|
||||
arg.TipoEventoID,
|
||||
arg.ObservacoesEvento,
|
||||
arg.LocalEvento,
|
||||
arg.Endereco,
|
||||
arg.Horario,
|
||||
arg.QtdFormandos,
|
||||
arg.QtdFotografos,
|
||||
arg.QtdRecepcionistas,
|
||||
arg.QtdCinegrafistas,
|
||||
arg.QtdEstudios,
|
||||
arg.QtdPontoFoto,
|
||||
arg.QtdPontoID,
|
||||
arg.QtdPontoDecorado,
|
||||
arg.QtdPontosLed,
|
||||
arg.QtdPlataforma360,
|
||||
arg.StatusProfissionais,
|
||||
arg.FotoFaltante,
|
||||
arg.RecepFaltante,
|
||||
arg.CineFaltante,
|
||||
arg.LogisticaObservacoes,
|
||||
arg.PreVenda,
|
||||
)
|
||||
var i Agenda
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.FotID,
|
||||
&i.DataEvento,
|
||||
&i.TipoEventoID,
|
||||
&i.ObservacoesEvento,
|
||||
&i.LocalEvento,
|
||||
&i.Endereco,
|
||||
&i.Horario,
|
||||
&i.QtdFormandos,
|
||||
&i.QtdFotografos,
|
||||
&i.QtdRecepcionistas,
|
||||
&i.QtdCinegrafistas,
|
||||
&i.QtdEstudios,
|
||||
&i.QtdPontoFoto,
|
||||
&i.QtdPontoID,
|
||||
&i.QtdPontoDecorado,
|
||||
&i.QtdPontosLed,
|
||||
&i.QtdPlataforma360,
|
||||
&i.StatusProfissionais,
|
||||
&i.FotoFaltante,
|
||||
&i.RecepFaltante,
|
||||
&i.CineFaltante,
|
||||
&i.LogisticaObservacoes,
|
||||
&i.PreVenda,
|
||||
&i.CriadoEm,
|
||||
&i.AtualizadoEm,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteAgenda = `-- name: DeleteAgenda :exec
|
||||
DELETE FROM agenda
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteAgenda(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteAgenda, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAgenda = `-- name: GetAgenda :one
|
||||
SELECT id, fot_id, data_evento, tipo_evento_id, observacoes_evento, local_evento, endereco, horario, qtd_formandos, qtd_fotografos, qtd_recepcionistas, qtd_cinegrafistas, qtd_estudios, qtd_ponto_foto, qtd_ponto_id, qtd_ponto_decorado, qtd_pontos_led, qtd_plataforma_360, status_profissionais, foto_faltante, recep_faltante, cine_faltante, logistica_observacoes, pre_venda, criado_em, atualizado_em FROM agenda
|
||||
WHERE id = $1 LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAgenda(ctx context.Context, id pgtype.UUID) (Agenda, error) {
|
||||
row := q.db.QueryRow(ctx, getAgenda, id)
|
||||
var i Agenda
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.FotID,
|
||||
&i.DataEvento,
|
||||
&i.TipoEventoID,
|
||||
&i.ObservacoesEvento,
|
||||
&i.LocalEvento,
|
||||
&i.Endereco,
|
||||
&i.Horario,
|
||||
&i.QtdFormandos,
|
||||
&i.QtdFotografos,
|
||||
&i.QtdRecepcionistas,
|
||||
&i.QtdCinegrafistas,
|
||||
&i.QtdEstudios,
|
||||
&i.QtdPontoFoto,
|
||||
&i.QtdPontoID,
|
||||
&i.QtdPontoDecorado,
|
||||
&i.QtdPontosLed,
|
||||
&i.QtdPlataforma360,
|
||||
&i.StatusProfissionais,
|
||||
&i.FotoFaltante,
|
||||
&i.RecepFaltante,
|
||||
&i.CineFaltante,
|
||||
&i.LogisticaObservacoes,
|
||||
&i.PreVenda,
|
||||
&i.CriadoEm,
|
||||
&i.AtualizadoEm,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listAgendas = `-- name: ListAgendas :many
|
||||
SELECT
|
||||
a.id, a.fot_id, a.data_evento, a.tipo_evento_id, a.observacoes_evento, a.local_evento, a.endereco, a.horario, a.qtd_formandos, a.qtd_fotografos, a.qtd_recepcionistas, a.qtd_cinegrafistas, a.qtd_estudios, a.qtd_ponto_foto, a.qtd_ponto_id, a.qtd_ponto_decorado, a.qtd_pontos_led, a.qtd_plataforma_360, a.status_profissionais, a.foto_faltante, a.recep_faltante, a.cine_faltante, a.logistica_observacoes, a.pre_venda, a.criado_em, a.atualizado_em,
|
||||
cf.fot as fot_numero,
|
||||
cf.instituicao,
|
||||
c.nome as curso_nome,
|
||||
e.nome as empresa_nome,
|
||||
af.ano_semestre,
|
||||
cf.observacoes as observacoes_fot,
|
||||
te.nome as tipo_evento_nome
|
||||
FROM agenda a
|
||||
JOIN cadastro_fot cf ON a.fot_id = cf.id
|
||||
JOIN cursos c ON cf.curso_id = c.id
|
||||
JOIN empresas e ON cf.empresa_id = e.id
|
||||
JOIN anos_formaturas af ON cf.ano_formatura_id = af.id
|
||||
JOIN tipos_eventos te ON a.tipo_evento_id = te.id
|
||||
ORDER BY a.data_evento
|
||||
`
|
||||
|
||||
type ListAgendasRow struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
FotID pgtype.UUID `json:"fot_id"`
|
||||
DataEvento pgtype.Date `json:"data_evento"`
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
ObservacoesEvento pgtype.Text `json:"observacoes_evento"`
|
||||
LocalEvento pgtype.Text `json:"local_evento"`
|
||||
Endereco pgtype.Text `json:"endereco"`
|
||||
Horario pgtype.Text `json:"horario"`
|
||||
QtdFormandos pgtype.Int4 `json:"qtd_formandos"`
|
||||
QtdFotografos pgtype.Int4 `json:"qtd_fotografos"`
|
||||
QtdRecepcionistas pgtype.Int4 `json:"qtd_recepcionistas"`
|
||||
QtdCinegrafistas pgtype.Int4 `json:"qtd_cinegrafistas"`
|
||||
QtdEstudios pgtype.Int4 `json:"qtd_estudios"`
|
||||
QtdPontoFoto pgtype.Int4 `json:"qtd_ponto_foto"`
|
||||
QtdPontoID pgtype.Int4 `json:"qtd_ponto_id"`
|
||||
QtdPontoDecorado pgtype.Int4 `json:"qtd_ponto_decorado"`
|
||||
QtdPontosLed pgtype.Int4 `json:"qtd_pontos_led"`
|
||||
QtdPlataforma360 pgtype.Int4 `json:"qtd_plataforma_360"`
|
||||
StatusProfissionais pgtype.Text `json:"status_profissionais"`
|
||||
FotoFaltante pgtype.Int4 `json:"foto_faltante"`
|
||||
RecepFaltante pgtype.Int4 `json:"recep_faltante"`
|
||||
CineFaltante pgtype.Int4 `json:"cine_faltante"`
|
||||
LogisticaObservacoes pgtype.Text `json:"logistica_observacoes"`
|
||||
PreVenda pgtype.Bool `json:"pre_venda"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
AtualizadoEm pgtype.Timestamptz `json:"atualizado_em"`
|
||||
FotNumero int32 `json:"fot_numero"`
|
||||
Instituicao pgtype.Text `json:"instituicao"`
|
||||
CursoNome string `json:"curso_nome"`
|
||||
EmpresaNome string `json:"empresa_nome"`
|
||||
AnoSemestre string `json:"ano_semestre"`
|
||||
ObservacoesFot pgtype.Text `json:"observacoes_fot"`
|
||||
TipoEventoNome string `json:"tipo_evento_nome"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListAgendas(ctx context.Context) ([]ListAgendasRow, error) {
|
||||
rows, err := q.db.Query(ctx, listAgendas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListAgendasRow
|
||||
for rows.Next() {
|
||||
var i ListAgendasRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.FotID,
|
||||
&i.DataEvento,
|
||||
&i.TipoEventoID,
|
||||
&i.ObservacoesEvento,
|
||||
&i.LocalEvento,
|
||||
&i.Endereco,
|
||||
&i.Horario,
|
||||
&i.QtdFormandos,
|
||||
&i.QtdFotografos,
|
||||
&i.QtdRecepcionistas,
|
||||
&i.QtdCinegrafistas,
|
||||
&i.QtdEstudios,
|
||||
&i.QtdPontoFoto,
|
||||
&i.QtdPontoID,
|
||||
&i.QtdPontoDecorado,
|
||||
&i.QtdPontosLed,
|
||||
&i.QtdPlataforma360,
|
||||
&i.StatusProfissionais,
|
||||
&i.FotoFaltante,
|
||||
&i.RecepFaltante,
|
||||
&i.CineFaltante,
|
||||
&i.LogisticaObservacoes,
|
||||
&i.PreVenda,
|
||||
&i.CriadoEm,
|
||||
&i.AtualizadoEm,
|
||||
&i.FotNumero,
|
||||
&i.Instituicao,
|
||||
&i.CursoNome,
|
||||
&i.EmpresaNome,
|
||||
&i.AnoSemestre,
|
||||
&i.ObservacoesFot,
|
||||
&i.TipoEventoNome,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateAgenda = `-- name: UpdateAgenda :one
|
||||
UPDATE agenda
|
||||
SET
|
||||
fot_id = $2,
|
||||
data_evento = $3,
|
||||
tipo_evento_id = $4,
|
||||
observacoes_evento = $5,
|
||||
local_evento = $6,
|
||||
endereco = $7,
|
||||
horario = $8,
|
||||
qtd_formandos = $9,
|
||||
qtd_fotografos = $10,
|
||||
qtd_recepcionistas = $11,
|
||||
qtd_cinegrafistas = $12,
|
||||
qtd_estudios = $13,
|
||||
qtd_ponto_foto = $14,
|
||||
qtd_ponto_id = $15,
|
||||
qtd_ponto_decorado = $16,
|
||||
qtd_pontos_led = $17,
|
||||
qtd_plataforma_360 = $18,
|
||||
status_profissionais = $19,
|
||||
foto_faltante = $20,
|
||||
recep_faltante = $21,
|
||||
cine_faltante = $22,
|
||||
logistica_observacoes = $23,
|
||||
pre_venda = $24,
|
||||
atualizado_em = NOW()
|
||||
WHERE id = $1
|
||||
RETURNING id, fot_id, data_evento, tipo_evento_id, observacoes_evento, local_evento, endereco, horario, qtd_formandos, qtd_fotografos, qtd_recepcionistas, qtd_cinegrafistas, qtd_estudios, qtd_ponto_foto, qtd_ponto_id, qtd_ponto_decorado, qtd_pontos_led, qtd_plataforma_360, status_profissionais, foto_faltante, recep_faltante, cine_faltante, logistica_observacoes, pre_venda, criado_em, atualizado_em
|
||||
`
|
||||
|
||||
type UpdateAgendaParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
FotID pgtype.UUID `json:"fot_id"`
|
||||
DataEvento pgtype.Date `json:"data_evento"`
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
ObservacoesEvento pgtype.Text `json:"observacoes_evento"`
|
||||
LocalEvento pgtype.Text `json:"local_evento"`
|
||||
Endereco pgtype.Text `json:"endereco"`
|
||||
Horario pgtype.Text `json:"horario"`
|
||||
QtdFormandos pgtype.Int4 `json:"qtd_formandos"`
|
||||
QtdFotografos pgtype.Int4 `json:"qtd_fotografos"`
|
||||
QtdRecepcionistas pgtype.Int4 `json:"qtd_recepcionistas"`
|
||||
QtdCinegrafistas pgtype.Int4 `json:"qtd_cinegrafistas"`
|
||||
QtdEstudios pgtype.Int4 `json:"qtd_estudios"`
|
||||
QtdPontoFoto pgtype.Int4 `json:"qtd_ponto_foto"`
|
||||
QtdPontoID pgtype.Int4 `json:"qtd_ponto_id"`
|
||||
QtdPontoDecorado pgtype.Int4 `json:"qtd_ponto_decorado"`
|
||||
QtdPontosLed pgtype.Int4 `json:"qtd_pontos_led"`
|
||||
QtdPlataforma360 pgtype.Int4 `json:"qtd_plataforma_360"`
|
||||
StatusProfissionais pgtype.Text `json:"status_profissionais"`
|
||||
FotoFaltante pgtype.Int4 `json:"foto_faltante"`
|
||||
RecepFaltante pgtype.Int4 `json:"recep_faltante"`
|
||||
CineFaltante pgtype.Int4 `json:"cine_faltante"`
|
||||
LogisticaObservacoes pgtype.Text `json:"logistica_observacoes"`
|
||||
PreVenda pgtype.Bool `json:"pre_venda"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAgenda(ctx context.Context, arg UpdateAgendaParams) (Agenda, error) {
|
||||
row := q.db.QueryRow(ctx, updateAgenda,
|
||||
arg.ID,
|
||||
arg.FotID,
|
||||
arg.DataEvento,
|
||||
arg.TipoEventoID,
|
||||
arg.ObservacoesEvento,
|
||||
arg.LocalEvento,
|
||||
arg.Endereco,
|
||||
arg.Horario,
|
||||
arg.QtdFormandos,
|
||||
arg.QtdFotografos,
|
||||
arg.QtdRecepcionistas,
|
||||
arg.QtdCinegrafistas,
|
||||
arg.QtdEstudios,
|
||||
arg.QtdPontoFoto,
|
||||
arg.QtdPontoID,
|
||||
arg.QtdPontoDecorado,
|
||||
arg.QtdPontosLed,
|
||||
arg.QtdPlataforma360,
|
||||
arg.StatusProfissionais,
|
||||
arg.FotoFaltante,
|
||||
arg.RecepFaltante,
|
||||
arg.CineFaltante,
|
||||
arg.LogisticaObservacoes,
|
||||
arg.PreVenda,
|
||||
)
|
||||
var i Agenda
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.FotID,
|
||||
&i.DataEvento,
|
||||
&i.TipoEventoID,
|
||||
&i.ObservacoesEvento,
|
||||
&i.LocalEvento,
|
||||
&i.Endereco,
|
||||
&i.Horario,
|
||||
&i.QtdFormandos,
|
||||
&i.QtdFotografos,
|
||||
&i.QtdRecepcionistas,
|
||||
&i.QtdCinegrafistas,
|
||||
&i.QtdEstudios,
|
||||
&i.QtdPontoFoto,
|
||||
&i.QtdPontoID,
|
||||
&i.QtdPontoDecorado,
|
||||
&i.QtdPontosLed,
|
||||
&i.QtdPlataforma360,
|
||||
&i.StatusProfissionais,
|
||||
&i.FotoFaltante,
|
||||
&i.RecepFaltante,
|
||||
&i.CineFaltante,
|
||||
&i.LogisticaObservacoes,
|
||||
&i.PreVenda,
|
||||
&i.CriadoEm,
|
||||
&i.AtualizadoEm,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -8,6 +8,35 @@ import (
|
|||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Agenda struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
FotID pgtype.UUID `json:"fot_id"`
|
||||
DataEvento pgtype.Date `json:"data_evento"`
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
ObservacoesEvento pgtype.Text `json:"observacoes_evento"`
|
||||
LocalEvento pgtype.Text `json:"local_evento"`
|
||||
Endereco pgtype.Text `json:"endereco"`
|
||||
Horario pgtype.Text `json:"horario"`
|
||||
QtdFormandos pgtype.Int4 `json:"qtd_formandos"`
|
||||
QtdFotografos pgtype.Int4 `json:"qtd_fotografos"`
|
||||
QtdRecepcionistas pgtype.Int4 `json:"qtd_recepcionistas"`
|
||||
QtdCinegrafistas pgtype.Int4 `json:"qtd_cinegrafistas"`
|
||||
QtdEstudios pgtype.Int4 `json:"qtd_estudios"`
|
||||
QtdPontoFoto pgtype.Int4 `json:"qtd_ponto_foto"`
|
||||
QtdPontoID pgtype.Int4 `json:"qtd_ponto_id"`
|
||||
QtdPontoDecorado pgtype.Int4 `json:"qtd_ponto_decorado"`
|
||||
QtdPontosLed pgtype.Int4 `json:"qtd_pontos_led"`
|
||||
QtdPlataforma360 pgtype.Int4 `json:"qtd_plataforma_360"`
|
||||
StatusProfissionais pgtype.Text `json:"status_profissionais"`
|
||||
FotoFaltante pgtype.Int4 `json:"foto_faltante"`
|
||||
RecepFaltante pgtype.Int4 `json:"recep_faltante"`
|
||||
CineFaltante pgtype.Int4 `json:"cine_faltante"`
|
||||
LogisticaObservacoes pgtype.Text `json:"logistica_observacoes"`
|
||||
PreVenda pgtype.Bool `json:"pre_venda"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
AtualizadoEm pgtype.Timestamptz `json:"atualizado_em"`
|
||||
}
|
||||
|
||||
type AnosFormatura struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
AnoSemestre string `json:"ano_semestre"`
|
||||
|
|
|
|||
84
backend/internal/db/queries/agenda.sql
Normal file
84
backend/internal/db/queries/agenda.sql
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
-- name: CreateAgenda :one
|
||||
INSERT INTO agenda (
|
||||
fot_id,
|
||||
data_evento,
|
||||
tipo_evento_id,
|
||||
observacoes_evento,
|
||||
local_evento,
|
||||
endereco,
|
||||
horario,
|
||||
qtd_formandos,
|
||||
qtd_fotografos,
|
||||
qtd_recepcionistas,
|
||||
qtd_cinegrafistas,
|
||||
qtd_estudios,
|
||||
qtd_ponto_foto,
|
||||
qtd_ponto_id,
|
||||
qtd_ponto_decorado,
|
||||
qtd_pontos_led,
|
||||
qtd_plataforma_360,
|
||||
status_profissionais,
|
||||
foto_faltante,
|
||||
recep_faltante,
|
||||
cine_faltante,
|
||||
logistica_observacoes,
|
||||
pre_venda
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23
|
||||
) RETURNING *;
|
||||
|
||||
-- name: GetAgenda :one
|
||||
SELECT * FROM agenda
|
||||
WHERE id = $1 LIMIT 1;
|
||||
|
||||
-- name: ListAgendas :many
|
||||
SELECT
|
||||
a.*,
|
||||
cf.fot as fot_numero,
|
||||
cf.instituicao,
|
||||
c.nome as curso_nome,
|
||||
e.nome as empresa_nome,
|
||||
af.ano_semestre,
|
||||
cf.observacoes as observacoes_fot,
|
||||
te.nome as tipo_evento_nome
|
||||
FROM agenda a
|
||||
JOIN cadastro_fot cf ON a.fot_id = cf.id
|
||||
JOIN cursos c ON cf.curso_id = c.id
|
||||
JOIN empresas e ON cf.empresa_id = e.id
|
||||
JOIN anos_formaturas af ON cf.ano_formatura_id = af.id
|
||||
JOIN tipos_eventos te ON a.tipo_evento_id = te.id
|
||||
ORDER BY a.data_evento;
|
||||
|
||||
-- name: UpdateAgenda :one
|
||||
UPDATE agenda
|
||||
SET
|
||||
fot_id = $2,
|
||||
data_evento = $3,
|
||||
tipo_evento_id = $4,
|
||||
observacoes_evento = $5,
|
||||
local_evento = $6,
|
||||
endereco = $7,
|
||||
horario = $8,
|
||||
qtd_formandos = $9,
|
||||
qtd_fotografos = $10,
|
||||
qtd_recepcionistas = $11,
|
||||
qtd_cinegrafistas = $12,
|
||||
qtd_estudios = $13,
|
||||
qtd_ponto_foto = $14,
|
||||
qtd_ponto_id = $15,
|
||||
qtd_ponto_decorado = $16,
|
||||
qtd_pontos_led = $17,
|
||||
qtd_plataforma_360 = $18,
|
||||
status_profissionais = $19,
|
||||
foto_faltante = $20,
|
||||
recep_faltante = $21,
|
||||
cine_faltante = $22,
|
||||
logistica_observacoes = $23,
|
||||
pre_venda = $24,
|
||||
atualizado_em = NOW()
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: DeleteAgenda :exec
|
||||
DELETE FROM agenda
|
||||
WHERE id = $1;
|
||||
|
|
@ -313,3 +313,32 @@ CREATE TABLE IF NOT EXISTS cadastro_clientes (
|
|||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(usuario_id)
|
||||
);
|
||||
-- Agenda Table
|
||||
CREATE TABLE IF NOT EXISTS agenda (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
fot_id UUID NOT NULL REFERENCES cadastro_fot(id) ON DELETE CASCADE,
|
||||
data_evento DATE NOT NULL,
|
||||
tipo_evento_id UUID NOT NULL REFERENCES tipos_eventos(id),
|
||||
observacoes_evento TEXT,
|
||||
local_evento VARCHAR(255),
|
||||
endereco VARCHAR(255),
|
||||
horario VARCHAR(20),
|
||||
qtd_formandos INTEGER DEFAULT 0,
|
||||
qtd_fotografos INTEGER DEFAULT 0,
|
||||
qtd_recepcionistas INTEGER DEFAULT 0,
|
||||
qtd_cinegrafistas INTEGER DEFAULT 0,
|
||||
qtd_estudios INTEGER DEFAULT 0,
|
||||
qtd_ponto_foto INTEGER DEFAULT 0,
|
||||
qtd_ponto_id INTEGER DEFAULT 0,
|
||||
qtd_ponto_decorado INTEGER DEFAULT 0,
|
||||
qtd_pontos_led INTEGER DEFAULT 0,
|
||||
qtd_plataforma_360 INTEGER DEFAULT 0,
|
||||
status_profissionais VARCHAR(20) DEFAULT 'OK', -- OK, FALTA, ERRO
|
||||
foto_faltante INTEGER DEFAULT 0,
|
||||
recep_faltante INTEGER DEFAULT 0,
|
||||
cine_faltante INTEGER DEFAULT 0,
|
||||
logistica_observacoes TEXT,
|
||||
pre_venda BOOLEAN DEFAULT FALSE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
atualizado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
|
|
|||
84
project_documentation.md
Normal file
84
project_documentation.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Documentação do Projeto Photum - Sessão de Desenvolvimento
|
||||
|
||||
Esta documentação resume todo o trabalho realizado durante a sessão atual de desenvolvimento, focada na implementação do Backend e ajustes no Frontend para o sistema Photum.
|
||||
|
||||
## 1. Visão Geral
|
||||
O objetivo principal foi fortalecer o backend em Go, implementar autenticação segura, e criar as estruturas para gerenciamento de FOT (Formandos, Organização, Turma) e Agenda de Eventos.
|
||||
|
||||
## 2. Implementações no Backend (Go + PostgreSQL)
|
||||
|
||||
### 2.1. Sistema de Autenticação e Usuários
|
||||
- **JWT & Refresh Tokens**: Implementação de autenticação baseada em tokens JWT curta duração e Refresh Tokens seguros.
|
||||
- **Hierarquia de Permissões (RBAC)**: Definição de roles padronizadas: ROLES Backend (Strings no Banco de Dados):
|
||||
|
||||
admin ⮕ Mapeado para SUPERADMIN
|
||||
empresa ⮕ Mapeado para BUSINESS_OWNER
|
||||
cliente ⮕ Mapeado para EVENT_OWNER
|
||||
profissional ⮕ Mapeado para PHOTOGRAPHER
|
||||
|
||||
admin@photum.com -> SUPERADMIN
|
||||
empresa@photum.com -> BUSINESS_OWNER
|
||||
foto@photum.com -> PHOTOGRAPHER
|
||||
- **Fluxo de Aprovação**:
|
||||
- Usuários se registram com status `ativo=false`.
|
||||
- Admin lista usuários pendentes (`/admin/users/pending`).
|
||||
- Admin aprova e define a Role (`/admin/users/:id/approve` e `/admin/users/:id/role`).
|
||||
- Bloqueio de login para usuários inativos.
|
||||
- **Dados do Usuário**: Adição de campos `Nome`, `Telefone` e `Empresa` no registro e listagens.
|
||||
|
||||
### 2.2. Tabelas Auxiliares (CRUDs)
|
||||
Criadas tabelas, Services e Handlers para as entidades básicas do sistema:
|
||||
- `cursos`
|
||||
- `empresas`
|
||||
- `anos_formaturas`
|
||||
- `tipos_eventos` (incluindo tabela de preços por função)
|
||||
- `tipos_servicos`
|
||||
- `funcoes_profissionais`
|
||||
|
||||
### 2.3. Módulo Cadastro FOT
|
||||
Responsável por vincular Turmas a Empresas e Instituições.
|
||||
- **Tabela**: `cadastro_fot` (Campos: `fot`, `empresa_id`, `curso_id`, `ano_formatura_id`, `instituicao`, `observacoes`, etc.).
|
||||
- **Backend**:
|
||||
- Endpoint `POST /api/cadastro-fot`: Criação com verificação de FOT duplicado.
|
||||
- Endpoint `GET /api/cadastro-fot`: Listagem com _joins_ para trazer nomes de Empresa, Curso, etc.
|
||||
- **Integração**: Conectado ao `CourseManagement.tsx` no frontend.
|
||||
|
||||
### 2.4. Módulo Agenda
|
||||
Responsável pelo agendamento de eventos vinculados a um FOT.
|
||||
- **Tabela**: `agenda` criada com uma estrutura normalizada, mas com campos específicos de evento.
|
||||
- Vinculada a `cadastro_fot` via `fot_id`.
|
||||
- Campos de dados do evento: `data_evento`, `local_evento`, `horario`, etc.
|
||||
- Campos de quantitativos: `qtd_formandos`, `qtd_fotografos`, `qtd_recepcionistas`, etc.
|
||||
- Campos de controle: `status_profissionais`, `foto_faltante`, `pre_venda`, etc.
|
||||
- **Backend**:
|
||||
- Arquivos gerados via SQLC (`internal/db/generated/agenda.sql.go`).
|
||||
- Service (`internal/agenda/service.go`) e Handler (`internal/agenda/handler.go`) implementados.
|
||||
- Rotas registradas em `cmd/api/main.go` sob `/api/agenda`.
|
||||
|
||||
### 2.5. Decisões Técnicas Backend
|
||||
- **Framework**: Gin Gonic.
|
||||
- **Database**: PostgreSQL com driver `pgx/v5`.
|
||||
- **Geração de Código**: Utilização do `sqlc` para gerar código Go type-safe a partir de queries SQL puras.
|
||||
- **Estrutura**: Padrão `internal/domain` (Service/Handler/Repository isolados).
|
||||
|
||||
## 3. Implementações no Frontend (React/Next.js)
|
||||
|
||||
### 3.1. Autenticação e Sessão
|
||||
- **AuthContext**: Melhoria na persistência de sessão. O frontend valida o token ao carregar e mantêm o usuário logado.
|
||||
- **Logout**: Implementada função de logout que chama o backend e limpa o estado local.
|
||||
- **UserApproval**: Interface para aprovação de usuários pendentes, exibindo Nome, E-mail e Empresa.
|
||||
|
||||
### 3.2. Gerenciamento de FOT (`CourseManagement.tsx`)
|
||||
- **Listagem**: Atualizada para consumir `/api/cadastro-fot` em vez de dados mockados.
|
||||
- **Formulário de Criação (`FotForm.tsx`)**:
|
||||
- Modal para criar novo FOT.
|
||||
- Dropdowns (Selects) conectados dinamicamente às APIs `/api/empresas`, `/api/cursos`, `/api/anos-formaturas`.
|
||||
- Validação e envio dos dados para o backend.
|
||||
|
||||
### 3.3. API Service
|
||||
- **`apiService.ts`**: Centralização das chamadas HTTP. Adicionadas funções para buscar cursos, anos de formatura, criar FOT, etc.
|
||||
|
||||
## 4. Próximos Passos Sugeridos
|
||||
1. **Frontend Agenda**: Criar a interface para visualizar e editar a Agenda (`Calendar` ou `List View`), consumindo os endpoints `/api/agenda` já criados.
|
||||
2. **Validações Avançadas**: Implementar regras de negócio mais complexas no backend (ex: conflito de horários).
|
||||
3. **Relatórios**: Gerar PDFs ou Excels baseados nos dados de FOT e Agenda.
|
||||
Loading…
Reference in a new issue