feat(api): Implementado novas tabelas ,refatorado a autenticação e aprimorado a documentação Swagger
- Implementado CRUDs para: cursos, empresas, anos_formaturas, tipos_servicos, tipos_eventos - Implementado lógica de precificação de eventos (precos_tipos_eventos) - Refatorado a autenticação: Simplificar o payload de cadastro/login (somente e-mail/senha), função padrão 'profissional' - Corrigido o middleware de autenticação: Resolvido a incompatibilidade de tipo UUID vs String (corrigir erro 500) - Aprimorado o Swagger: Adicionado structs nomeados, validação de duplicatas (409 Conflict) e segurança BearerAuth - Atualizar o esquema do banco de dados: Adicionar tabelas e restrições
This commit is contained in:
parent
f89e1386f7
commit
7f1d4144db
29 changed files with 4416 additions and 152 deletions
|
|
@ -3,11 +3,16 @@ package main
|
|||
import (
|
||||
"log"
|
||||
|
||||
"photum-backend/internal/anos_formaturas"
|
||||
"photum-backend/internal/auth"
|
||||
"photum-backend/internal/config"
|
||||
"photum-backend/internal/cursos"
|
||||
"photum-backend/internal/db"
|
||||
"photum-backend/internal/empresas"
|
||||
"photum-backend/internal/funcoes"
|
||||
"photum-backend/internal/profissionais"
|
||||
"photum-backend/internal/tipos_eventos"
|
||||
"photum-backend/internal/tipos_servicos"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
|
|
@ -45,11 +50,21 @@ func main() {
|
|||
profissionaisService := profissionais.NewService(queries)
|
||||
authService := auth.NewService(queries, profissionaisService, cfg)
|
||||
funcoesService := funcoes.NewService(queries)
|
||||
cursosService := cursos.NewService(queries)
|
||||
empresasService := empresas.NewService(queries)
|
||||
anosFormaturasService := anos_formaturas.NewService(queries)
|
||||
tiposServicosService := tipos_servicos.NewService(queries)
|
||||
tiposEventosService := tipos_eventos.NewService(queries)
|
||||
|
||||
// Initialize handlers
|
||||
authHandler := auth.NewHandler(authService)
|
||||
profissionaisHandler := profissionais.NewHandler(profissionaisService)
|
||||
funcoesHandler := funcoes.NewHandler(funcoesService)
|
||||
cursosHandler := cursos.NewHandler(cursosService)
|
||||
empresasHandler := empresas.NewHandler(empresasService)
|
||||
anosFormaturasHandler := anos_formaturas.NewHandler(anosFormaturasService)
|
||||
tiposServicosHandler := tipos_servicos.NewHandler(tiposServicosService)
|
||||
tiposEventosHandler := tipos_eventos.NewHandler(tiposEventosService)
|
||||
|
||||
r := gin.Default()
|
||||
|
||||
|
|
@ -65,8 +80,14 @@ func main() {
|
|||
authGroup.POST("/logout", authHandler.Logout)
|
||||
}
|
||||
|
||||
// Public API Routes
|
||||
// Public API Routes (Data Lists)
|
||||
r.GET("/api/funcoes", funcoesHandler.List)
|
||||
r.GET("/api/cursos", cursosHandler.List)
|
||||
r.GET("/api/empresas", empresasHandler.List)
|
||||
r.GET("/api/anos-formaturas", anosFormaturasHandler.List)
|
||||
r.GET("/api/tipos-servicos", tiposServicosHandler.List)
|
||||
r.GET("/api/tipos-eventos", tiposEventosHandler.List)
|
||||
r.GET("/api/tipos-eventos/:id/precos", tiposEventosHandler.ListPrices)
|
||||
|
||||
// Protected Routes
|
||||
api := r.Group("/api")
|
||||
|
|
@ -94,10 +115,29 @@ func main() {
|
|||
funcoesGroup := api.Group("/funcoes")
|
||||
{
|
||||
funcoesGroup.POST("", funcoesHandler.Create)
|
||||
// GET is now public
|
||||
funcoesGroup.PUT("/:id", funcoesHandler.Update)
|
||||
funcoesGroup.DELETE("/:id", funcoesHandler.Delete)
|
||||
}
|
||||
|
||||
// protected CRUD (create/update/delete)
|
||||
api.POST("/cursos", cursosHandler.Create)
|
||||
api.PUT("/cursos/:id", cursosHandler.Update)
|
||||
api.DELETE("/cursos/:id", cursosHandler.Delete)
|
||||
|
||||
api.POST("/empresas", empresasHandler.Create)
|
||||
api.PUT("/empresas/:id", empresasHandler.Update)
|
||||
api.DELETE("/empresas/:id", empresasHandler.Delete)
|
||||
|
||||
api.POST("/anos-formaturas", anosFormaturasHandler.Create)
|
||||
api.PUT("/anos-formaturas/:id", anosFormaturasHandler.Update)
|
||||
api.DELETE("/anos-formaturas/:id", anosFormaturasHandler.Delete)
|
||||
|
||||
api.POST("/tipos-servicos", tiposServicosHandler.Create)
|
||||
api.PUT("/tipos-servicos/:id", tiposServicosHandler.Update)
|
||||
api.DELETE("/tipos-servicos/:id", tiposServicosHandler.Delete)
|
||||
|
||||
api.POST("/tipos-eventos", tiposEventosHandler.Create)
|
||||
api.POST("/tipos-eventos/precos", tiposEventosHandler.SetPrice)
|
||||
}
|
||||
|
||||
log.Printf("Server running on port %s", cfg.AppPort)
|
||||
|
|
|
|||
1005
backend/docs/docs.go
1005
backend/docs/docs.go
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +1,26 @@
|
|||
basePath: /
|
||||
definitions:
|
||||
auth.loginRequest:
|
||||
anos_formaturas.AnoFormaturaResponse:
|
||||
properties:
|
||||
ano_semestre:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
type: object
|
||||
anos_formaturas.CreateAnoFormaturaRequest:
|
||||
properties:
|
||||
ano_semestre:
|
||||
example: "2029.1"
|
||||
type: string
|
||||
required:
|
||||
- ano_semestre
|
||||
type: object
|
||||
auth.authRequest:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
senha:
|
||||
minLength: 6
|
||||
type: string
|
||||
required:
|
||||
- email
|
||||
|
|
@ -20,25 +36,6 @@ definitions:
|
|||
user:
|
||||
$ref: '#/definitions/auth.userResponse'
|
||||
type: object
|
||||
auth.registerRequest:
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
profissional_data:
|
||||
$ref: '#/definitions/profissionais.CreateProfissionalInput'
|
||||
role:
|
||||
enum:
|
||||
- profissional
|
||||
- empresa
|
||||
type: string
|
||||
senha:
|
||||
minLength: 6
|
||||
type: string
|
||||
required:
|
||||
- email
|
||||
- role
|
||||
- senha
|
||||
type: object
|
||||
auth.userResponse:
|
||||
properties:
|
||||
email:
|
||||
|
|
@ -48,6 +45,41 @@ definitions:
|
|||
role:
|
||||
type: string
|
||||
type: object
|
||||
cursos.CreateCursoRequest:
|
||||
properties:
|
||||
nome:
|
||||
type: string
|
||||
required:
|
||||
- nome
|
||||
type: object
|
||||
cursos.CursoResponse:
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
nome:
|
||||
type: string
|
||||
type: object
|
||||
empresas.CreateEmpresaRequest:
|
||||
properties:
|
||||
nome:
|
||||
type: string
|
||||
required:
|
||||
- nome
|
||||
type: object
|
||||
empresas.EmpresaResponse:
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
nome:
|
||||
type: string
|
||||
type: object
|
||||
funcoes.CreateFuncaoRequest:
|
||||
properties:
|
||||
nome:
|
||||
type: string
|
||||
required:
|
||||
- nome
|
||||
type: object
|
||||
funcoes.FuncaoResponse:
|
||||
properties:
|
||||
id:
|
||||
|
|
@ -209,6 +241,56 @@ definitions:
|
|||
whatsapp:
|
||||
type: string
|
||||
type: object
|
||||
tipos_eventos.CreateEventoRequest:
|
||||
properties:
|
||||
nome:
|
||||
type: string
|
||||
required:
|
||||
- nome
|
||||
type: object
|
||||
tipos_eventos.EventoResponse:
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
nome:
|
||||
type: string
|
||||
type: object
|
||||
tipos_eventos.PrecoResponse:
|
||||
properties:
|
||||
funcao_nome:
|
||||
type: string
|
||||
funcao_profissional_id:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
tipo_evento_id:
|
||||
type: string
|
||||
valor:
|
||||
type: number
|
||||
type: object
|
||||
tipos_eventos.PriceInput:
|
||||
properties:
|
||||
funcao_profissional_id:
|
||||
type: string
|
||||
tipo_evento_id:
|
||||
type: string
|
||||
valor:
|
||||
type: number
|
||||
type: object
|
||||
tipos_servicos.CreateTipoServicoRequest:
|
||||
properties:
|
||||
nome:
|
||||
type: string
|
||||
required:
|
||||
- nome
|
||||
type: object
|
||||
tipos_servicos.TipoServicoResponse:
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
nome:
|
||||
type: string
|
||||
type: object
|
||||
host: localhost:8080
|
||||
info:
|
||||
contact:
|
||||
|
|
@ -223,6 +305,303 @@ info:
|
|||
title: Photum Backend API
|
||||
version: "1.0"
|
||||
paths:
|
||||
/api/anos-formaturas:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/anos_formaturas.AnoFormaturaResponse'
|
||||
type: array
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List all graduation years
|
||||
tags:
|
||||
- anos_formaturas
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Ano Semestre
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/anos_formaturas.CreateAnoFormaturaRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
$ref: '#/definitions/anos_formaturas.AnoFormaturaResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Create a new graduation year
|
||||
tags:
|
||||
- anos_formaturas
|
||||
/api/anos-formaturas/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Delete a graduation year
|
||||
tags:
|
||||
- anos_formaturas
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Ano Semestre
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/anos_formaturas.CreateAnoFormaturaRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/anos_formaturas.AnoFormaturaResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Update a graduation year
|
||||
tags:
|
||||
- anos_formaturas
|
||||
/api/cursos:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/cursos.CursoResponse'
|
||||
type: array
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List all courses
|
||||
tags:
|
||||
- cursos
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Curso Name
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/cursos.CreateCursoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
$ref: '#/definitions/cursos.CursoResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Create a new course
|
||||
tags:
|
||||
- cursos
|
||||
/api/cursos/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Curso ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Delete a course
|
||||
tags:
|
||||
- cursos
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Curso ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Curso Name
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/cursos.CreateCursoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/cursos.CursoResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Update a course
|
||||
tags:
|
||||
- cursos
|
||||
/api/empresas:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/empresas.EmpresaResponse'
|
||||
type: array
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List all companies
|
||||
tags:
|
||||
- empresas
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Empresa Name
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/empresas.CreateEmpresaRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
$ref: '#/definitions/empresas.EmpresaResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Create a new company
|
||||
tags:
|
||||
- empresas
|
||||
/api/empresas/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Empresa ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Delete a company
|
||||
tags:
|
||||
- empresas
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Empresa ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Empresa Name
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/empresas.CreateEmpresaRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/empresas.EmpresaResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Update a company
|
||||
tags:
|
||||
- empresas
|
||||
/api/funcoes:
|
||||
get:
|
||||
consumes:
|
||||
|
|
@ -243,8 +622,6 @@ paths:
|
|||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List functions
|
||||
tags:
|
||||
- funcoes
|
||||
|
|
@ -258,9 +635,7 @@ paths:
|
|||
name: request
|
||||
required: true
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
$ref: '#/definitions/funcoes.CreateFuncaoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
|
@ -274,6 +649,12 @@ paths:
|
|||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
|
|
@ -337,9 +718,7 @@ paths:
|
|||
name: request
|
||||
required: true
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
$ref: '#/definitions/funcoes.CreateFuncaoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
|
@ -353,6 +732,12 @@ paths:
|
|||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
|
|
@ -541,6 +926,194 @@ paths:
|
|||
summary: Update profissional
|
||||
tags:
|
||||
- profissionais
|
||||
/api/tipos-eventos:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/tipos_eventos.EventoResponse'
|
||||
type: array
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List all event types
|
||||
tags:
|
||||
- tipos_eventos
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Nome
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_eventos.CreateEventoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_eventos.EventoResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Create a new event type
|
||||
tags:
|
||||
- tipos_eventos
|
||||
/api/tipos-eventos/{id}/precos:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Event ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/tipos_eventos.PrecoResponse'
|
||||
type: array
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List prices for an event
|
||||
tags:
|
||||
- tipos_eventos
|
||||
/api/tipos-eventos/precos:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Price Input
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_eventos.PriceInput'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Set price for an event function
|
||||
tags:
|
||||
- tipos_eventos
|
||||
/api/tipos-servicos:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/tipos_servicos.TipoServicoResponse'
|
||||
type: array
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: List all service types
|
||||
tags:
|
||||
- tipos_servicos
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: Nome
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_servicos.CreateTipoServicoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_servicos.TipoServicoResponse'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Create a new service type
|
||||
tags:
|
||||
- tipos_servicos
|
||||
/api/tipos-servicos/{id}:
|
||||
delete:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Delete a service type
|
||||
tags:
|
||||
- tipos_servicos
|
||||
put:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Nome
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_servicos.CreateTipoServicoRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/tipos_servicos.TipoServicoResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Update a service type
|
||||
tags:
|
||||
- tipos_servicos
|
||||
/auth/login:
|
||||
post:
|
||||
consumes:
|
||||
|
|
@ -552,7 +1125,7 @@ paths:
|
|||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/auth.loginRequest'
|
||||
$ref: '#/definitions/auth.authRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
|
@ -630,14 +1203,15 @@ paths:
|
|||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Register a new user with optional professional profile
|
||||
description: Register a new user (defaults to 'profissional' role) with email
|
||||
and password
|
||||
parameters:
|
||||
- description: Register Request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/auth.registerRequest'
|
||||
$ref: '#/definitions/auth.authRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
|
|
|||
137
backend/internal/anos_formaturas/handler.go
Normal file
137
backend/internal/anos_formaturas/handler.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
package anos_formaturas
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewHandler(service *Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
type AnoFormaturaResponse struct {
|
||||
ID string `json:"id"`
|
||||
AnoSemestre string `json:"ano_semestre"`
|
||||
}
|
||||
|
||||
type CreateAnoFormaturaRequest struct {
|
||||
AnoSemestre string `json:"ano_semestre" binding:"required" example:"2029.1"`
|
||||
}
|
||||
|
||||
func toResponse(a generated.AnosFormatura) AnoFormaturaResponse {
|
||||
return AnoFormaturaResponse{
|
||||
ID: uuid.UUID(a.ID.Bytes).String(),
|
||||
AnoSemestre: a.AnoSemestre,
|
||||
}
|
||||
}
|
||||
|
||||
// Create godoc
|
||||
// @Summary Create a new graduation year
|
||||
// @Tags anos_formaturas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body CreateAnoFormaturaRequest true "Ano Semestre"
|
||||
// @Success 201 {object} AnoFormaturaResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/anos-formaturas [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateAnoFormaturaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
ano, err := h.service.Create(c.Request.Context(), req.AnoSemestre)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Ano/Semestre already exists"})
|
||||
return
|
||||
}
|
||||
if strings.Contains(err.Error(), "invalid format") {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, toResponse(*ano))
|
||||
}
|
||||
|
||||
// List godoc
|
||||
// @Summary List all graduation years
|
||||
// @Tags anos_formaturas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {array} AnoFormaturaResponse
|
||||
// @Router /api/anos-formaturas [get]
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
anos, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var response []AnoFormaturaResponse
|
||||
for _, ano := range anos {
|
||||
response = append(response, toResponse(ano))
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Update godoc
|
||||
// @Summary Update a graduation year
|
||||
// @Tags anos_formaturas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "ID"
|
||||
// @Param request body CreateAnoFormaturaRequest true "Ano Semestre"
|
||||
// @Success 200 {object} AnoFormaturaResponse
|
||||
// @Router /api/anos-formaturas/{id} [put]
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var req CreateAnoFormaturaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
ano, err := h.service.Update(c.Request.Context(), id, req.AnoSemestre)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, toResponse(*ano))
|
||||
}
|
||||
|
||||
// Delete godoc
|
||||
// @Summary Delete a graduation year
|
||||
// @Tags anos_formaturas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "ID"
|
||||
// @Success 204 {object} nil
|
||||
// @Router /api/anos-formaturas/{id} [delete]
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
80
backend/internal/anos_formaturas/service.go
Normal file
80
backend/internal/anos_formaturas/service.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package anos_formaturas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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, anoSemestre string) (*generated.AnosFormatura, error) {
|
||||
// Validate format YYYY.S
|
||||
matched, _ := regexp.MatchString(`^\d{4}\.[1-2]$`, anoSemestre)
|
||||
if !matched {
|
||||
return nil, errors.New("invalid format. Expected YYYY.1 or YYYY.2")
|
||||
}
|
||||
|
||||
ano, err := s.queries.CreateAnoFormatura(ctx, anoSemestre)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ano, nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context) ([]generated.AnosFormatura, error) {
|
||||
return s.queries.ListAnosFormaturas(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetByID(ctx context.Context, id string) (*generated.AnosFormatura, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
ano, err := s.queries.GetAnoFormaturaByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ano, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id, anoSemestre string) (*generated.AnosFormatura, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
|
||||
// Validate format YYYY.S
|
||||
matched, _ := regexp.MatchString(`^\d{4}\.[1-2]$`, anoSemestre)
|
||||
if !matched {
|
||||
return nil, errors.New("invalid format. Expected YYYY.1 or YYYY.2")
|
||||
}
|
||||
|
||||
ano, err := s.queries.UpdateAnoFormatura(ctx, generated.UpdateAnoFormaturaParams{
|
||||
ID: pgtype.UUID{Bytes: uuidVal, Valid: true},
|
||||
AnoSemestre: anoSemestre,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ano, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id string) error {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return errors.New("invalid id")
|
||||
}
|
||||
return s.queries.DeleteAnoFormatura(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package auth
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"photum-backend/internal/profissionais"
|
||||
|
||||
|
|
@ -17,38 +18,39 @@ func NewHandler(service *Service) *Handler {
|
|||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
type registerRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Senha string `json:"senha" binding:"required,min=6"`
|
||||
Role string `json:"role" binding:"required,oneof=profissional empresa"`
|
||||
ProfissionalData *profissionais.CreateProfissionalInput `json:"profissional_data"`
|
||||
type authRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Senha string `json:"senha" binding:"required,min=6"`
|
||||
}
|
||||
|
||||
// Register godoc
|
||||
// @Summary Register a new user
|
||||
// @Description Register a new user with optional professional profile
|
||||
// @Description Register a new user (defaults to 'profissional' role) with email and password
|
||||
// @Tags auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body registerRequest true "Register Request"
|
||||
// @Param request body authRequest true "Register Request"
|
||||
// @Success 201 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /auth/register [post]
|
||||
func (h *Handler) Register(c *gin.Context) {
|
||||
var req registerRequest
|
||||
var req authRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if req.Role == "profissional" && req.ProfissionalData == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "profissional_data is required for role 'profissional'"})
|
||||
return
|
||||
}
|
||||
// Default simplified registration: Role="profissional", No professional data yet
|
||||
role := "profissional"
|
||||
var profData *profissionais.CreateProfissionalInput = nil
|
||||
|
||||
_, err := h.service.Register(c.Request.Context(), req.Email, req.Senha, req.Role, req.ProfissionalData)
|
||||
_, err := h.service.Register(c.Request.Context(), req.Email, req.Senha, role, profData)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "email already registered"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
|
@ -56,11 +58,6 @@ func (h *Handler) Register(c *gin.Context) {
|
|||
c.JSON(http.StatusCreated, gin.H{"message": "user created"})
|
||||
}
|
||||
|
||||
type loginRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Senha string `json:"senha" binding:"required"`
|
||||
}
|
||||
|
||||
type loginResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresAt string `json:"expires_at"`
|
||||
|
|
@ -80,13 +77,13 @@ type userResponse struct {
|
|||
// @Tags auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body loginRequest true "Login Request"
|
||||
// @Param request body authRequest true "Login Request"
|
||||
// @Success 200 {object} loginResponse
|
||||
// @Failure 401 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /auth/login [post]
|
||||
func (h *Handler) Login(c *gin.Context) {
|
||||
var req loginRequest
|
||||
var req authRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
|
|
@ -94,7 +91,7 @@ func (h *Handler) Login(c *gin.Context) {
|
|||
|
||||
tokenPair, user, profData, err := h.service.Login(c.Request.Context(), req.Email, req.Senha)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"})
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +107,7 @@ func (h *Handler) Login(c *gin.Context) {
|
|||
|
||||
resp := loginResponse{
|
||||
AccessToken: tokenPair.AccessToken,
|
||||
ExpiresAt: "2025-...",
|
||||
ExpiresAt: "2025-...", // logic to calculate if needed, or remove field
|
||||
User: userResponse{
|
||||
ID: uuid.UUID(user.ID.Bytes).String(),
|
||||
Email: user.Email,
|
||||
|
|
@ -131,11 +128,6 @@ func (h *Handler) Login(c *gin.Context) {
|
|||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// Refresh and Logout handlers should be kept or restored if they were lost.
|
||||
// I will assume they are needed and add them back in a subsequent edit if missing,
|
||||
// or include them here if I can fit them.
|
||||
// The previous content had them. I'll add them to be safe.
|
||||
|
||||
// Refresh godoc
|
||||
// @Summary Refresh access token
|
||||
// @Description Get a new access token using a valid refresh token
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func AuthMiddleware(cfg *config.Config) gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
c.Set("userID", claims.UserID)
|
||||
c.Set("userID", claims.UserID.String())
|
||||
c.Set("role", claims.Role)
|
||||
c.Next()
|
||||
}
|
||||
|
|
|
|||
133
backend/internal/cursos/handler.go
Normal file
133
backend/internal/cursos/handler.go
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
package cursos
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewHandler(service *Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
type CursoResponse struct {
|
||||
ID string `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
type CreateCursoRequest struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
|
||||
func toResponse(c generated.Curso) CursoResponse {
|
||||
return CursoResponse{
|
||||
ID: uuid.UUID(c.ID.Bytes).String(),
|
||||
Nome: c.Nome,
|
||||
}
|
||||
}
|
||||
|
||||
// Create godoc
|
||||
// @Summary Create a new course
|
||||
// @Tags cursos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body CreateCursoRequest true "Curso Name"
|
||||
// @Success 201 {object} CursoResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/cursos [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateCursoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
curso, err := h.service.Create(c.Request.Context(), req.Nome)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Curso already exists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, toResponse(*curso))
|
||||
}
|
||||
|
||||
// List godoc
|
||||
// @Summary List all courses
|
||||
// @Tags cursos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {array} CursoResponse
|
||||
// @Router /api/cursos [get]
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
cursos, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var response []CursoResponse
|
||||
for _, curso := range cursos {
|
||||
response = append(response, toResponse(curso))
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Update godoc
|
||||
// @Summary Update a course
|
||||
// @Tags cursos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "Curso ID"
|
||||
// @Param request body CreateCursoRequest true "Curso Name"
|
||||
// @Success 200 {object} CursoResponse
|
||||
// @Router /api/cursos/{id} [put]
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var req CreateCursoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
curso, err := h.service.Update(c.Request.Context(), id, req.Nome)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, toResponse(*curso))
|
||||
}
|
||||
|
||||
// Delete godoc
|
||||
// @Summary Delete a course
|
||||
// @Tags cursos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "Curso ID"
|
||||
// @Success 204 {object} nil
|
||||
// @Router /api/cursos/{id} [delete]
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
67
backend/internal/cursos/service.go
Normal file
67
backend/internal/cursos/service.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package cursos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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, nome string) (*generated.Curso, error) {
|
||||
curso, err := s.queries.CreateCurso(ctx, nome)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &curso, nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context) ([]generated.Curso, error) {
|
||||
return s.queries.ListCursos(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetByID(ctx context.Context, id string) (*generated.Curso, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
curso, err := s.queries.GetCursoByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &curso, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id, nome string) (*generated.Curso, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
|
||||
curso, err := s.queries.UpdateCurso(ctx, generated.UpdateCursoParams{
|
||||
ID: pgtype.UUID{Bytes: uuidVal, Valid: true},
|
||||
Nome: nome,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &curso, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id string) error {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return errors.New("invalid id")
|
||||
}
|
||||
return s.queries.DeleteCurso(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
}
|
||||
83
backend/internal/db/generated/anos_formaturas.sql.go
Normal file
83
backend/internal/db/generated/anos_formaturas.sql.go
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: anos_formaturas.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createAnoFormatura = `-- name: CreateAnoFormatura :one
|
||||
INSERT INTO anos_formaturas (ano_semestre) VALUES ($1) RETURNING id, ano_semestre, criado_em
|
||||
`
|
||||
|
||||
func (q *Queries) CreateAnoFormatura(ctx context.Context, anoSemestre string) (AnosFormatura, error) {
|
||||
row := q.db.QueryRow(ctx, createAnoFormatura, anoSemestre)
|
||||
var i AnosFormatura
|
||||
err := row.Scan(&i.ID, &i.AnoSemestre, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteAnoFormatura = `-- name: DeleteAnoFormatura :exec
|
||||
DELETE FROM anos_formaturas WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteAnoFormatura(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteAnoFormatura, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAnoFormaturaByID = `-- name: GetAnoFormaturaByID :one
|
||||
SELECT id, ano_semestre, criado_em FROM anos_formaturas WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAnoFormaturaByID(ctx context.Context, id pgtype.UUID) (AnosFormatura, error) {
|
||||
row := q.db.QueryRow(ctx, getAnoFormaturaByID, id)
|
||||
var i AnosFormatura
|
||||
err := row.Scan(&i.ID, &i.AnoSemestre, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listAnosFormaturas = `-- name: ListAnosFormaturas :many
|
||||
SELECT id, ano_semestre, criado_em FROM anos_formaturas ORDER BY ano_semestre
|
||||
`
|
||||
|
||||
func (q *Queries) ListAnosFormaturas(ctx context.Context) ([]AnosFormatura, error) {
|
||||
rows, err := q.db.Query(ctx, listAnosFormaturas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []AnosFormatura
|
||||
for rows.Next() {
|
||||
var i AnosFormatura
|
||||
if err := rows.Scan(&i.ID, &i.AnoSemestre, &i.CriadoEm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateAnoFormatura = `-- name: UpdateAnoFormatura :one
|
||||
UPDATE anos_formaturas SET ano_semestre = $2 WHERE id = $1 RETURNING id, ano_semestre, criado_em
|
||||
`
|
||||
|
||||
type UpdateAnoFormaturaParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
AnoSemestre string `json:"ano_semestre"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAnoFormatura(ctx context.Context, arg UpdateAnoFormaturaParams) (AnosFormatura, error) {
|
||||
row := q.db.QueryRow(ctx, updateAnoFormatura, arg.ID, arg.AnoSemestre)
|
||||
var i AnosFormatura
|
||||
err := row.Scan(&i.ID, &i.AnoSemestre, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
83
backend/internal/db/generated/cursos.sql.go
Normal file
83
backend/internal/db/generated/cursos.sql.go
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: cursos.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createCurso = `-- name: CreateCurso :one
|
||||
INSERT INTO cursos (nome) VALUES ($1) RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
func (q *Queries) CreateCurso(ctx context.Context, nome string) (Curso, error) {
|
||||
row := q.db.QueryRow(ctx, createCurso, nome)
|
||||
var i Curso
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteCurso = `-- name: DeleteCurso :exec
|
||||
DELETE FROM cursos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteCurso(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteCurso, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getCursoByID = `-- name: GetCursoByID :one
|
||||
SELECT id, nome, criado_em FROM cursos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetCursoByID(ctx context.Context, id pgtype.UUID) (Curso, error) {
|
||||
row := q.db.QueryRow(ctx, getCursoByID, id)
|
||||
var i Curso
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listCursos = `-- name: ListCursos :many
|
||||
SELECT id, nome, criado_em FROM cursos ORDER BY nome
|
||||
`
|
||||
|
||||
func (q *Queries) ListCursos(ctx context.Context) ([]Curso, error) {
|
||||
rows, err := q.db.Query(ctx, listCursos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Curso
|
||||
for rows.Next() {
|
||||
var i Curso
|
||||
if err := rows.Scan(&i.ID, &i.Nome, &i.CriadoEm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateCurso = `-- name: UpdateCurso :one
|
||||
UPDATE cursos SET nome = $2 WHERE id = $1 RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
type UpdateCursoParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCurso(ctx context.Context, arg UpdateCursoParams) (Curso, error) {
|
||||
row := q.db.QueryRow(ctx, updateCurso, arg.ID, arg.Nome)
|
||||
var i Curso
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
83
backend/internal/db/generated/empresas.sql.go
Normal file
83
backend/internal/db/generated/empresas.sql.go
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: empresas.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createEmpresa = `-- name: CreateEmpresa :one
|
||||
INSERT INTO empresas (nome) VALUES ($1) RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
func (q *Queries) CreateEmpresa(ctx context.Context, nome string) (Empresa, error) {
|
||||
row := q.db.QueryRow(ctx, createEmpresa, nome)
|
||||
var i Empresa
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteEmpresa = `-- name: DeleteEmpresa :exec
|
||||
DELETE FROM empresas WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteEmpresa(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteEmpresa, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getEmpresaByID = `-- name: GetEmpresaByID :one
|
||||
SELECT id, nome, criado_em FROM empresas WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetEmpresaByID(ctx context.Context, id pgtype.UUID) (Empresa, error) {
|
||||
row := q.db.QueryRow(ctx, getEmpresaByID, id)
|
||||
var i Empresa
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listEmpresas = `-- name: ListEmpresas :many
|
||||
SELECT id, nome, criado_em FROM empresas ORDER BY nome
|
||||
`
|
||||
|
||||
func (q *Queries) ListEmpresas(ctx context.Context) ([]Empresa, error) {
|
||||
rows, err := q.db.Query(ctx, listEmpresas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Empresa
|
||||
for rows.Next() {
|
||||
var i Empresa
|
||||
if err := rows.Scan(&i.ID, &i.Nome, &i.CriadoEm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateEmpresa = `-- name: UpdateEmpresa :one
|
||||
UPDATE empresas SET nome = $2 WHERE id = $1 RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
type UpdateEmpresaParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateEmpresa(ctx context.Context, arg UpdateEmpresaParams) (Empresa, error) {
|
||||
row := q.db.QueryRow(ctx, updateEmpresa, arg.ID, arg.Nome)
|
||||
var i Empresa
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -8,6 +8,12 @@ import (
|
|||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type AnosFormatura struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
AnoSemestre string `json:"ano_semestre"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type CadastroProfissionai struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UsuarioID pgtype.UUID `json:"usuario_id"`
|
||||
|
|
@ -38,6 +44,18 @@ type CadastroProfissionai struct {
|
|||
AtualizadoEm pgtype.Timestamptz `json:"atualizado_em"`
|
||||
}
|
||||
|
||||
type Curso struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type Empresa struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type FuncoesProfissionai struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
|
|
@ -45,6 +63,14 @@ type FuncoesProfissionai struct {
|
|||
AtualizadoEm pgtype.Timestamptz `json:"atualizado_em"`
|
||||
}
|
||||
|
||||
type PrecosTiposEvento struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
FuncaoProfissionalID pgtype.UUID `json:"funcao_profissional_id"`
|
||||
Valor pgtype.Numeric `json:"valor"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type RefreshToken struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UsuarioID pgtype.UUID `json:"usuario_id"`
|
||||
|
|
@ -56,6 +82,18 @@ type RefreshToken struct {
|
|||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type TiposEvento struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type TiposServico struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
}
|
||||
|
||||
type Usuario struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
|
|
|
|||
184
backend/internal/db/generated/tipos_eventos.sql.go
Normal file
184
backend/internal/db/generated/tipos_eventos.sql.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: tipos_eventos.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createPrecoEvento = `-- name: CreatePrecoEvento :one
|
||||
INSERT INTO precos_tipos_eventos (tipo_evento_id, funcao_profissional_id, valor)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (tipo_evento_id, funcao_profissional_id) DO UPDATE
|
||||
SET valor = $3
|
||||
RETURNING id, tipo_evento_id, funcao_profissional_id, valor, criado_em
|
||||
`
|
||||
|
||||
type CreatePrecoEventoParams struct {
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
FuncaoProfissionalID pgtype.UUID `json:"funcao_profissional_id"`
|
||||
Valor pgtype.Numeric `json:"valor"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePrecoEvento(ctx context.Context, arg CreatePrecoEventoParams) (PrecosTiposEvento, error) {
|
||||
row := q.db.QueryRow(ctx, createPrecoEvento, arg.TipoEventoID, arg.FuncaoProfissionalID, arg.Valor)
|
||||
var i PrecosTiposEvento
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TipoEventoID,
|
||||
&i.FuncaoProfissionalID,
|
||||
&i.Valor,
|
||||
&i.CriadoEm,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createTipoEvento = `-- name: CreateTipoEvento :one
|
||||
INSERT INTO tipos_eventos (nome) VALUES ($1) RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
func (q *Queries) CreateTipoEvento(ctx context.Context, nome string) (TiposEvento, error) {
|
||||
row := q.db.QueryRow(ctx, createTipoEvento, nome)
|
||||
var i TiposEvento
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deletePreco = `-- name: DeletePreco :exec
|
||||
DELETE FROM precos_tipos_eventos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeletePreco(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deletePreco, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteTipoEvento = `-- name: DeleteTipoEvento :exec
|
||||
DELETE FROM tipos_eventos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteTipoEvento(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteTipoEvento, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getPreco = `-- name: GetPreco :one
|
||||
SELECT id, tipo_evento_id, funcao_profissional_id, valor, criado_em FROM precos_tipos_eventos WHERE tipo_evento_id = $1 AND funcao_profissional_id = $2
|
||||
`
|
||||
|
||||
type GetPrecoParams struct {
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
FuncaoProfissionalID pgtype.UUID `json:"funcao_profissional_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetPreco(ctx context.Context, arg GetPrecoParams) (PrecosTiposEvento, error) {
|
||||
row := q.db.QueryRow(ctx, getPreco, arg.TipoEventoID, arg.FuncaoProfissionalID)
|
||||
var i PrecosTiposEvento
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TipoEventoID,
|
||||
&i.FuncaoProfissionalID,
|
||||
&i.Valor,
|
||||
&i.CriadoEm,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTipoEventoByID = `-- name: GetTipoEventoByID :one
|
||||
SELECT id, nome, criado_em FROM tipos_eventos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTipoEventoByID(ctx context.Context, id pgtype.UUID) (TiposEvento, error) {
|
||||
row := q.db.QueryRow(ctx, getTipoEventoByID, id)
|
||||
var i TiposEvento
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listPrecosByEventoID = `-- name: ListPrecosByEventoID :many
|
||||
SELECT p.id, p.tipo_evento_id, p.funcao_profissional_id, p.valor, p.criado_em, f.nome as funcao_nome
|
||||
FROM precos_tipos_eventos p
|
||||
JOIN funcoes_profissionais f ON p.funcao_profissional_id = f.id
|
||||
WHERE p.tipo_evento_id = $1
|
||||
`
|
||||
|
||||
type ListPrecosByEventoIDRow struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
TipoEventoID pgtype.UUID `json:"tipo_evento_id"`
|
||||
FuncaoProfissionalID pgtype.UUID `json:"funcao_profissional_id"`
|
||||
Valor pgtype.Numeric `json:"valor"`
|
||||
CriadoEm pgtype.Timestamptz `json:"criado_em"`
|
||||
FuncaoNome string `json:"funcao_nome"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListPrecosByEventoID(ctx context.Context, tipoEventoID pgtype.UUID) ([]ListPrecosByEventoIDRow, error) {
|
||||
rows, err := q.db.Query(ctx, listPrecosByEventoID, tipoEventoID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListPrecosByEventoIDRow
|
||||
for rows.Next() {
|
||||
var i ListPrecosByEventoIDRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.TipoEventoID,
|
||||
&i.FuncaoProfissionalID,
|
||||
&i.Valor,
|
||||
&i.CriadoEm,
|
||||
&i.FuncaoNome,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listTiposEventos = `-- name: ListTiposEventos :many
|
||||
SELECT id, nome, criado_em FROM tipos_eventos ORDER BY nome
|
||||
`
|
||||
|
||||
func (q *Queries) ListTiposEventos(ctx context.Context) ([]TiposEvento, error) {
|
||||
rows, err := q.db.Query(ctx, listTiposEventos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []TiposEvento
|
||||
for rows.Next() {
|
||||
var i TiposEvento
|
||||
if err := rows.Scan(&i.ID, &i.Nome, &i.CriadoEm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateTipoEvento = `-- name: UpdateTipoEvento :one
|
||||
UPDATE tipos_eventos SET nome = $2 WHERE id = $1 RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
type UpdateTipoEventoParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTipoEvento(ctx context.Context, arg UpdateTipoEventoParams) (TiposEvento, error) {
|
||||
row := q.db.QueryRow(ctx, updateTipoEvento, arg.ID, arg.Nome)
|
||||
var i TiposEvento
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
83
backend/internal/db/generated/tipos_servicos.sql.go
Normal file
83
backend/internal/db/generated/tipos_servicos.sql.go
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: tipos_servicos.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createTipoServico = `-- name: CreateTipoServico :one
|
||||
INSERT INTO tipos_servicos (nome) VALUES ($1) RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
func (q *Queries) CreateTipoServico(ctx context.Context, nome string) (TiposServico, error) {
|
||||
row := q.db.QueryRow(ctx, createTipoServico, nome)
|
||||
var i TiposServico
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const deleteTipoServico = `-- name: DeleteTipoServico :exec
|
||||
DELETE FROM tipos_servicos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteTipoServico(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteTipoServico, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getTipoServicoByID = `-- name: GetTipoServicoByID :one
|
||||
SELECT id, nome, criado_em FROM tipos_servicos WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTipoServicoByID(ctx context.Context, id pgtype.UUID) (TiposServico, error) {
|
||||
row := q.db.QueryRow(ctx, getTipoServicoByID, id)
|
||||
var i TiposServico
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listTiposServicos = `-- name: ListTiposServicos :many
|
||||
SELECT id, nome, criado_em FROM tipos_servicos ORDER BY nome
|
||||
`
|
||||
|
||||
func (q *Queries) ListTiposServicos(ctx context.Context) ([]TiposServico, error) {
|
||||
rows, err := q.db.Query(ctx, listTiposServicos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []TiposServico
|
||||
for rows.Next() {
|
||||
var i TiposServico
|
||||
if err := rows.Scan(&i.ID, &i.Nome, &i.CriadoEm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateTipoServico = `-- name: UpdateTipoServico :one
|
||||
UPDATE tipos_servicos SET nome = $2 WHERE id = $1 RETURNING id, nome, criado_em
|
||||
`
|
||||
|
||||
type UpdateTipoServicoParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateTipoServico(ctx context.Context, arg UpdateTipoServicoParams) (TiposServico, error) {
|
||||
row := q.db.QueryRow(ctx, updateTipoServico, arg.ID, arg.Nome)
|
||||
var i TiposServico
|
||||
err := row.Scan(&i.ID, &i.Nome, &i.CriadoEm)
|
||||
return i, err
|
||||
}
|
||||
14
backend/internal/db/queries/anos_formaturas.sql
Normal file
14
backend/internal/db/queries/anos_formaturas.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-- name: CreateAnoFormatura :one
|
||||
INSERT INTO anos_formaturas (ano_semestre) VALUES ($1) RETURNING *;
|
||||
|
||||
-- name: ListAnosFormaturas :many
|
||||
SELECT * FROM anos_formaturas ORDER BY ano_semestre;
|
||||
|
||||
-- name: GetAnoFormaturaByID :one
|
||||
SELECT * FROM anos_formaturas WHERE id = $1;
|
||||
|
||||
-- name: UpdateAnoFormatura :one
|
||||
UPDATE anos_formaturas SET ano_semestre = $2 WHERE id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteAnoFormatura :exec
|
||||
DELETE FROM anos_formaturas WHERE id = $1;
|
||||
14
backend/internal/db/queries/cursos.sql
Normal file
14
backend/internal/db/queries/cursos.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-- name: CreateCurso :one
|
||||
INSERT INTO cursos (nome) VALUES ($1) RETURNING *;
|
||||
|
||||
-- name: ListCursos :many
|
||||
SELECT * FROM cursos ORDER BY nome;
|
||||
|
||||
-- name: GetCursoByID :one
|
||||
SELECT * FROM cursos WHERE id = $1;
|
||||
|
||||
-- name: UpdateCurso :one
|
||||
UPDATE cursos SET nome = $2 WHERE id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteCurso :exec
|
||||
DELETE FROM cursos WHERE id = $1;
|
||||
14
backend/internal/db/queries/empresas.sql
Normal file
14
backend/internal/db/queries/empresas.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-- name: CreateEmpresa :one
|
||||
INSERT INTO empresas (nome) VALUES ($1) RETURNING *;
|
||||
|
||||
-- name: ListEmpresas :many
|
||||
SELECT * FROM empresas ORDER BY nome;
|
||||
|
||||
-- name: GetEmpresaByID :one
|
||||
SELECT * FROM empresas WHERE id = $1;
|
||||
|
||||
-- name: UpdateEmpresa :one
|
||||
UPDATE empresas SET nome = $2 WHERE id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteEmpresa :exec
|
||||
DELETE FROM empresas WHERE id = $1;
|
||||
33
backend/internal/db/queries/tipos_eventos.sql
Normal file
33
backend/internal/db/queries/tipos_eventos.sql
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
-- name: CreateTipoEvento :one
|
||||
INSERT INTO tipos_eventos (nome) VALUES ($1) RETURNING *;
|
||||
|
||||
-- name: ListTiposEventos :many
|
||||
SELECT * FROM tipos_eventos ORDER BY nome;
|
||||
|
||||
-- name: GetTipoEventoByID :one
|
||||
SELECT * FROM tipos_eventos WHERE id = $1;
|
||||
|
||||
-- name: UpdateTipoEvento :one
|
||||
UPDATE tipos_eventos SET nome = $2 WHERE id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteTipoEvento :exec
|
||||
DELETE FROM tipos_eventos WHERE id = $1;
|
||||
|
||||
-- name: CreatePrecoEvento :one
|
||||
INSERT INTO precos_tipos_eventos (tipo_evento_id, funcao_profissional_id, valor)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (tipo_evento_id, funcao_profissional_id) DO UPDATE
|
||||
SET valor = $3
|
||||
RETURNING *;
|
||||
|
||||
-- name: ListPrecosByEventoID :many
|
||||
SELECT p.*, f.nome as funcao_nome
|
||||
FROM precos_tipos_eventos p
|
||||
JOIN funcoes_profissionais f ON p.funcao_profissional_id = f.id
|
||||
WHERE p.tipo_evento_id = $1;
|
||||
|
||||
-- name: GetPreco :one
|
||||
SELECT * FROM precos_tipos_eventos WHERE tipo_evento_id = $1 AND funcao_profissional_id = $2;
|
||||
|
||||
-- name: DeletePreco :exec
|
||||
DELETE FROM precos_tipos_eventos WHERE id = $1;
|
||||
14
backend/internal/db/queries/tipos_servicos.sql
Normal file
14
backend/internal/db/queries/tipos_servicos.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-- name: CreateTipoServico :one
|
||||
INSERT INTO tipos_servicos (nome) VALUES ($1) RETURNING *;
|
||||
|
||||
-- name: ListTiposServicos :many
|
||||
SELECT * FROM tipos_servicos ORDER BY nome;
|
||||
|
||||
-- name: GetTipoServicoByID :one
|
||||
SELECT * FROM tipos_servicos WHERE id = $1;
|
||||
|
||||
-- name: UpdateTipoServico :one
|
||||
UPDATE tipos_servicos SET nome = $2 WHERE id = $1 RETURNING *;
|
||||
|
||||
-- name: DeleteTipoServico :exec
|
||||
DELETE FROM tipos_servicos WHERE id = $1;
|
||||
|
|
@ -64,3 +64,83 @@ CREATE TABLE refresh_tokens (
|
|||
revogado BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Cursos Table
|
||||
CREATE TABLE cursos (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
nome VARCHAR(100) UNIQUE NOT NULL,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO cursos (nome) VALUES
|
||||
('Administração Empresas'), ('Agronomia'), ('Arquitetura / Urbanismo'), ('Biomedicina'), ('Comunicação'), ('Contábeis'),
|
||||
('Direito'), ('Economia'), ('Educação Física'), ('EFI I/EFI II'), ('EI/EFI'), ('EF II/EM'), ('EFI(5º ano)'), ('EFII'),
|
||||
('EI'), ('EM'), ('EM / TEC'), ('Enfermagem'), ('Eng. Ambiental'), ('Eng. Elétrica'), ('Engenharia'), ('Estética'),
|
||||
('Farmácia'), ('Fisioterapia'), ('Gastronomia'), ('Historia'), ('Jornalismo'), ('Med. Veterinária'), ('Medicina'),
|
||||
('Nutrição'), ('Odontologia'), ('Outro'), ('Pedagogia'), ('Publicidade'), ('Superior Diversos'), ('Tec. Diversos'),
|
||||
('Termomecânica'), ('Unificados'), ('Tec. Enfermagem'), ('Quimica'), ('EFI / EF II / EM'), ('Psicologia'),
|
||||
('Terapia Ocupacinal'), ('R.I');
|
||||
|
||||
-- Empresas Table
|
||||
CREATE TABLE empresas (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
nome VARCHAR(100) UNIQUE NOT NULL,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO empresas (nome) VALUES
|
||||
('Arte Formaturas'), ('JR Formaturas'), ('Perfil'), ('Photum'), ('Populi Formaturas'), ('Prime'), ('Smart'), ('Viva SP'),
|
||||
('Antares'), ('Forcamp'), ('PNI'), ('Fábio Ribeiro'), ('Told - B2_(CAMPINAS)'), ('Told - B2_(RECIFE)'),
|
||||
('NOVO - Told - B2_(SP)'), ('NOVO - Told - RUB_(SP)'), ('NOVO - TOLD'), ('Alpha Digital'), ('Golden'), ('Festa da Beca'),
|
||||
('Ponta Eventos'), ('Toy SP'), ('MVP Formaturas'), ('RUB');
|
||||
|
||||
-- Anos Formaturas Table
|
||||
CREATE TABLE anos_formaturas (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
ano_semestre VARCHAR(20) UNIQUE NOT NULL, -- Ex: 2019.2
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO anos_formaturas (ano_semestre) VALUES
|
||||
('2019.2'), ('2020.1'), ('2020.2'), ('2021.1'), ('2021.2'), ('2022.1'), ('2022.2'), ('2023.1'), ('2023.2'),
|
||||
('2024.1'), ('2024.2'), ('2025.1'), ('2025.2'), ('2026.1'), ('2026.2'), ('2027.1'), ('2027.2'), ('2028.1'),
|
||||
('2028.2'), ('2029.1'), ('2029.2');
|
||||
|
||||
-- Tipos Servicos Table
|
||||
CREATE TABLE tipos_servicos (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
nome VARCHAR(50) UNIQUE NOT NULL,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO tipos_servicos (nome) VALUES
|
||||
('Fotógrafo'), ('Recepcionista'), ('Cinegrafista'), ('Coordenação'), ('Ponto de Foto'), ('Ponto de ID'), ('Estúdio'),
|
||||
('Outro'), ('Controle');
|
||||
|
||||
-- Tipos Eventos Table
|
||||
CREATE TABLE tipos_eventos (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
nome VARCHAR(100) UNIQUE NOT NULL,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO tipos_eventos (nome) VALUES
|
||||
('Identificação'), ('Baile'), ('Colação'), ('Col/Baile (mesmo local)'), ('Col/Baile (local diferente)'), ('Missa / Culto'),
|
||||
('Churrasco'), ('Trote'), ('Outro'), ('Balada'), ('Jantar'), ('Festa Junina'), ('Colação Oficial'), ('Family Day'),
|
||||
('Refeição'), ('Estudio ID e Family Day'), ('Estudio Colação / Baile');
|
||||
|
||||
-- Precos Tipos Eventos Table (Junction Table for Pricing)
|
||||
CREATE TABLE precos_tipos_eventos (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
tipo_evento_id UUID REFERENCES tipos_eventos(id) ON DELETE CASCADE,
|
||||
funcao_profissional_id UUID REFERENCES funcoes_profissionais(id) ON DELETE CASCADE,
|
||||
valor NUMERIC(10,2) NOT NULL DEFAULT 0.00,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(tipo_evento_id, funcao_profissional_id)
|
||||
);
|
||||
|
||||
-- Initial Pricing Seed (Examples based on image, requires joining IDs which makes raw SQL insert hard without known UUIDs.
|
||||
-- For simplicity in schema.sql, we'll skip complex dynamic inserts.
|
||||
-- The user can populate via API or we can write a more complex PL/pgSQL block if absolutely necessary,
|
||||
-- but usually schema.sql is structure + static data. Dynamic pricing is better handled via admin or separate migration script.
|
||||
-- Leaving table empty for now, or adding a comment.)
|
||||
|
|
|
|||
133
backend/internal/empresas/handler.go
Normal file
133
backend/internal/empresas/handler.go
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
package empresas
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewHandler(service *Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
type EmpresaResponse struct {
|
||||
ID string `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
type CreateEmpresaRequest struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
|
||||
func toResponse(e generated.Empresa) EmpresaResponse {
|
||||
return EmpresaResponse{
|
||||
ID: uuid.UUID(e.ID.Bytes).String(),
|
||||
Nome: e.Nome,
|
||||
}
|
||||
}
|
||||
|
||||
// Create godoc
|
||||
// @Summary Create a new company
|
||||
// @Tags empresas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body CreateEmpresaRequest true "Empresa Name"
|
||||
// @Success 201 {object} EmpresaResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/empresas [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateEmpresaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
empresa, err := h.service.Create(c.Request.Context(), req.Nome)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Empresa already exists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, toResponse(*empresa))
|
||||
}
|
||||
|
||||
// List godoc
|
||||
// @Summary List all companies
|
||||
// @Tags empresas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {array} EmpresaResponse
|
||||
// @Router /api/empresas [get]
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
empresas, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var response []EmpresaResponse
|
||||
for _, empresa := range empresas {
|
||||
response = append(response, toResponse(empresa))
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Update godoc
|
||||
// @Summary Update a company
|
||||
// @Tags empresas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "Empresa ID"
|
||||
// @Param request body CreateEmpresaRequest true "Empresa Name"
|
||||
// @Success 200 {object} EmpresaResponse
|
||||
// @Router /api/empresas/{id} [put]
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var req CreateEmpresaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
empresa, err := h.service.Update(c.Request.Context(), id, req.Nome)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, toResponse(*empresa))
|
||||
}
|
||||
|
||||
// Delete godoc
|
||||
// @Summary Delete a company
|
||||
// @Tags empresas
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "Empresa ID"
|
||||
// @Success 204 {object} nil
|
||||
// @Router /api/empresas/{id} [delete]
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
67
backend/internal/empresas/service.go
Normal file
67
backend/internal/empresas/service.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package empresas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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, nome string) (*generated.Empresa, error) {
|
||||
empresa, err := s.queries.CreateEmpresa(ctx, nome)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &empresa, nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context) ([]generated.Empresa, error) {
|
||||
return s.queries.ListEmpresas(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetByID(ctx context.Context, id string) (*generated.Empresa, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
empresa, err := s.queries.GetEmpresaByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &empresa, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id, nome string) (*generated.Empresa, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
|
||||
empresa, err := s.queries.UpdateEmpresa(ctx, generated.UpdateEmpresaParams{
|
||||
ID: pgtype.UUID{Bytes: uuidVal, Valid: true},
|
||||
Nome: nome,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &empresa, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id string) error {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return errors.New("invalid id")
|
||||
}
|
||||
return s.queries.DeleteEmpresa(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package funcoes
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
|
|
@ -22,6 +23,10 @@ type FuncaoResponse struct {
|
|||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
type CreateFuncaoRequest struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
|
||||
func toResponse(f generated.FuncoesProfissionai) FuncaoResponse {
|
||||
return FuncaoResponse{
|
||||
ID: uuid.UUID(f.ID.Bytes).String(),
|
||||
|
|
@ -36,15 +41,14 @@ func toResponse(f generated.FuncoesProfissionai) FuncaoResponse {
|
|||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body map[string]string true "Create Function Request"
|
||||
// @Param request body CreateFuncaoRequest true "Create Function Request"
|
||||
// @Success 201 {object} FuncaoResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/funcoes [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
var req CreateFuncaoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
|
|
@ -52,6 +56,10 @@ func (h *Handler) Create(c *gin.Context) {
|
|||
|
||||
funcao, err := h.service.Create(c.Request.Context(), req.Nome)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Funcao already exists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
|
@ -65,7 +73,6 @@ func (h *Handler) Create(c *gin.Context) {
|
|||
// @Tags funcoes
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {array} FuncaoResponse
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/funcoes [get]
|
||||
|
|
@ -92,16 +99,15 @@ func (h *Handler) List(c *gin.Context) {
|
|||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "Function ID"
|
||||
// @Param request body map[string]string true "Update Function Request"
|
||||
// @Param request body CreateFuncaoRequest true "Update Function Request"
|
||||
// @Success 200 {object} FuncaoResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/funcoes/{id} [put]
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var req struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
var req CreateFuncaoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
|
|
@ -109,6 +115,10 @@ func (h *Handler) Update(c *gin.Context) {
|
|||
|
||||
funcao, err := h.service.Update(c.Request.Context(), id, req.Nome)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Funcao already exists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
|
|
|||
150
backend/internal/tipos_eventos/handler.go
Normal file
150
backend/internal/tipos_eventos/handler.go
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
package tipos_eventos
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewHandler(service *Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
type EventoResponse struct {
|
||||
ID string `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
type PrecoResponse struct {
|
||||
ID string `json:"id"`
|
||||
TipoEventoID string `json:"tipo_evento_id"`
|
||||
FuncaoProfissionalID string `json:"funcao_profissional_id"`
|
||||
FuncaoNome string `json:"funcao_nome"`
|
||||
Valor float64 `json:"valor"`
|
||||
}
|
||||
|
||||
func toEventoResponse(e generated.TiposEvento) EventoResponse {
|
||||
return EventoResponse{
|
||||
ID: uuid.UUID(e.ID.Bytes).String(),
|
||||
Nome: e.Nome,
|
||||
}
|
||||
}
|
||||
|
||||
func fromPgNumeric(n pgtype.Numeric) float64 {
|
||||
f, _ := n.Float64Value()
|
||||
return f.Float64
|
||||
}
|
||||
|
||||
type CreateEventoRequest struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
|
||||
// Create godoc
|
||||
// @Summary Create a new event type
|
||||
// @Tags tipos_eventos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body CreateEventoRequest true "Nome"
|
||||
// @Success 201 {object} EventoResponse
|
||||
// @Router /api/tipos-eventos [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateEventoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
event, err := h.service.Create(c.Request.Context(), req.Nome)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, toEventoResponse(*event))
|
||||
}
|
||||
|
||||
// List godoc
|
||||
// @Summary List all event types
|
||||
// @Tags tipos_eventos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {array} EventoResponse
|
||||
// @Router /api/tipos-eventos [get]
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
events, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var response []EventoResponse
|
||||
for _, e := range events {
|
||||
response = append(response, toEventoResponse(e))
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// SetPrice godoc
|
||||
// @Summary Set price for an event function
|
||||
// @Tags tipos_eventos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body PriceInput true "Price Input"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Router /api/tipos-eventos/precos [post]
|
||||
func (h *Handler) SetPrice(c *gin.Context) {
|
||||
var req PriceInput
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
_, err := h.service.SetPrice(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "price set"})
|
||||
}
|
||||
|
||||
// ListPrices godoc
|
||||
// @Summary List prices for an event
|
||||
// @Tags tipos_eventos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "Event ID"
|
||||
// @Success 200 {array} PrecoResponse
|
||||
// @Router /api/tipos-eventos/{id}/precos [get]
|
||||
func (h *Handler) ListPrices(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
prices, err := h.service.ListPrices(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var response []PrecoResponse
|
||||
for _, p := range prices {
|
||||
response = append(response, PrecoResponse{
|
||||
ID: uuid.UUID(p.ID.Bytes).String(),
|
||||
TipoEventoID: uuid.UUID(p.TipoEventoID.Bytes).String(),
|
||||
FuncaoProfissionalID: uuid.UUID(p.FuncaoProfissionalID.Bytes).String(),
|
||||
FuncaoNome: p.FuncaoNome,
|
||||
Valor: fromPgNumeric(p.Valor),
|
||||
})
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
112
backend/internal/tipos_eventos/service.go
Normal file
112
backend/internal/tipos_eventos/service.go
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package tipos_eventos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
queries *generated.Queries
|
||||
}
|
||||
|
||||
func NewService(queries *generated.Queries) *Service {
|
||||
return &Service{queries: queries}
|
||||
}
|
||||
|
||||
// Event CRUD
|
||||
|
||||
func (s *Service) Create(ctx context.Context, nome string) (*generated.TiposEvento, error) {
|
||||
event, err := s.queries.CreateTipoEvento(ctx, nome)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context) ([]generated.TiposEvento, error) {
|
||||
return s.queries.ListTiposEventos(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetByID(ctx context.Context, id string) (*generated.TiposEvento, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
event, err := s.queries.GetTipoEventoByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id, nome string) (*generated.TiposEvento, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
event, err := s.queries.UpdateTipoEvento(ctx, generated.UpdateTipoEventoParams{
|
||||
ID: pgtype.UUID{Bytes: uuidVal, Valid: true},
|
||||
Nome: nome,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &event, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id string) error {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return errors.New("invalid id")
|
||||
}
|
||||
return s.queries.DeleteTipoEvento(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
}
|
||||
|
||||
// Pricing Logic
|
||||
|
||||
type PriceInput struct {
|
||||
TipoEventoID string `json:"tipo_evento_id"`
|
||||
FuncaoProfissionalID string `json:"funcao_profissional_id"`
|
||||
Valor float64 `json:"valor"`
|
||||
}
|
||||
|
||||
func (s *Service) SetPrice(ctx context.Context, input PriceInput) (*generated.PrecosTiposEvento, error) {
|
||||
eventoUUID, err := uuid.Parse(input.TipoEventoID)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid tipo_evento_id")
|
||||
}
|
||||
funcaoUUID, err := uuid.Parse(input.FuncaoProfissionalID)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid funcao_profissional_id")
|
||||
}
|
||||
|
||||
precio, err := s.queries.CreatePrecoEvento(ctx, generated.CreatePrecoEventoParams{
|
||||
TipoEventoID: pgtype.UUID{Bytes: eventoUUID, Valid: true},
|
||||
FuncaoProfissionalID: pgtype.UUID{Bytes: funcaoUUID, Valid: true},
|
||||
Valor: toPgNumeric(input.Valor),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &precio, nil
|
||||
}
|
||||
|
||||
func (s *Service) ListPrices(ctx context.Context, eventoID string) ([]generated.ListPrecosByEventoIDRow, error) {
|
||||
eventoUUID, err := uuid.Parse(eventoID)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid evento_id")
|
||||
}
|
||||
return s.queries.ListPrecosByEventoID(ctx, pgtype.UUID{Bytes: eventoUUID, Valid: true})
|
||||
}
|
||||
|
||||
// Helper (Assuming user doesn't have it in shared utils or similar)
|
||||
func toPgNumeric(f float64) pgtype.Numeric {
|
||||
var n pgtype.Numeric
|
||||
n.Scan(f)
|
||||
return n
|
||||
}
|
||||
133
backend/internal/tipos_servicos/handler.go
Normal file
133
backend/internal/tipos_servicos/handler.go
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
package tipos_servicos
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewHandler(service *Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
type TipoServicoResponse struct {
|
||||
ID string `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
}
|
||||
|
||||
type CreateTipoServicoRequest struct {
|
||||
Nome string `json:"nome" binding:"required"`
|
||||
}
|
||||
|
||||
func toResponse(t generated.TiposServico) TipoServicoResponse {
|
||||
return TipoServicoResponse{
|
||||
ID: uuid.UUID(t.ID.Bytes).String(),
|
||||
Nome: t.Nome,
|
||||
}
|
||||
}
|
||||
|
||||
// Create godoc
|
||||
// @Summary Create a new service type
|
||||
// @Tags tipos_servicos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param request body CreateTipoServicoRequest true "Nome"
|
||||
// @Success 201 {object} TipoServicoResponse
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Router /api/tipos-servicos [post]
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
var req CreateTipoServicoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
tipo, err := h.service.Create(c.Request.Context(), req.Nome)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Tipo de Servico already exists"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, toResponse(*tipo))
|
||||
}
|
||||
|
||||
// List godoc
|
||||
// @Summary List all service types
|
||||
// @Tags tipos_servicos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {array} TipoServicoResponse
|
||||
// @Router /api/tipos-servicos [get]
|
||||
func (h *Handler) List(c *gin.Context) {
|
||||
tipos, err := h.service.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var response []TipoServicoResponse
|
||||
for _, tipo := range tipos {
|
||||
response = append(response, toResponse(tipo))
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// Update godoc
|
||||
// @Summary Update a service type
|
||||
// @Tags tipos_servicos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "ID"
|
||||
// @Param request body CreateTipoServicoRequest true "Nome"
|
||||
// @Success 200 {object} TipoServicoResponse
|
||||
// @Router /api/tipos-servicos/{id} [put]
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var req CreateTipoServicoRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
tipo, err := h.service.Update(c.Request.Context(), id, req.Nome)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, toResponse(*tipo))
|
||||
}
|
||||
|
||||
// Delete godoc
|
||||
// @Summary Delete a service type
|
||||
// @Tags tipos_servicos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "ID"
|
||||
// @Success 204 {object} nil
|
||||
// @Router /api/tipos-servicos/{id} [delete]
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if err := h.service.Delete(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
67
backend/internal/tipos_servicos/service.go
Normal file
67
backend/internal/tipos_servicos/service.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package tipos_servicos
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"photum-backend/internal/db/generated"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"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, nome string) (*generated.TiposServico, error) {
|
||||
tipo, err := s.queries.CreateTipoServico(ctx, nome)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tipo, nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context) ([]generated.TiposServico, error) {
|
||||
return s.queries.ListTiposServicos(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) GetByID(ctx context.Context, id string) (*generated.TiposServico, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
tipo, err := s.queries.GetTipoServicoByID(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tipo, nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id, nome string) (*generated.TiposServico, error) {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid id")
|
||||
}
|
||||
|
||||
tipo, err := s.queries.UpdateTipoServico(ctx, generated.UpdateTipoServicoParams{
|
||||
ID: pgtype.UUID{Bytes: uuidVal, Valid: true},
|
||||
Nome: nome,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tipo, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id string) error {
|
||||
uuidVal, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
return errors.New("invalid id")
|
||||
}
|
||||
return s.queries.DeleteTipoServico(ctx, pgtype.UUID{Bytes: uuidVal, Valid: true})
|
||||
}
|
||||
Loading…
Reference in a new issue