316 lines
9 KiB
Go
316 lines
9 KiB
Go
package logistica
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Handler struct {
|
|
service *Service
|
|
}
|
|
|
|
func NewHandler(service *Service) *Handler {
|
|
return &Handler{service: service}
|
|
}
|
|
|
|
// CreateCarro
|
|
func (h *Handler) CreateCarro(c *gin.Context) {
|
|
var req CreateCarroInput
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
carro, err := h.service.CreateCarro(c.Request.Context(), req)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"id": uuid.UUID(carro.ID.Bytes).String()})
|
|
}
|
|
|
|
// ListCarros
|
|
func (h *Handler) ListCarros(c *gin.Context) {
|
|
agendaID := c.Query("agenda_id")
|
|
if agendaID == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "agenda_id is required"})
|
|
return
|
|
}
|
|
|
|
carros, err := h.service.ListCarros(c.Request.Context(), agendaID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Fetch passengers for each car? Or let frontend do it on demand?
|
|
// For main list, efficient to just list cars, or maybe passengers embedded.
|
|
// For simplicity, let's embed passengers if possible, but list returns row.
|
|
// We will return list of cars. The frontend can fetch passengers per car or we should use a transaction/composite query.
|
|
// MVP: Check if we can just return the cars now.
|
|
|
|
resp := make([]map[string]interface{}, len(carros))
|
|
for i, car := range carros {
|
|
var driverName string
|
|
// Logic: if system driver name exists, use it. Else use custom name.
|
|
if car.MotoristaNomeSistema.String != "" {
|
|
driverName = car.MotoristaNomeSistema.String
|
|
} else {
|
|
driverName = car.NomeMotorista.String
|
|
}
|
|
|
|
var avatar string
|
|
if car.MotoristaAvatar.Valid {
|
|
avatar = car.MotoristaAvatar.String
|
|
}
|
|
|
|
resp[i] = map[string]interface{}{
|
|
"id": uuid.UUID(car.ID.Bytes).String(),
|
|
"agenda_id": uuid.UUID(car.AgendaID.Bytes).String(),
|
|
"driver_id": uuid.UUID(car.MotoristaID.Bytes).String(), // May be empty UUID or nil representation
|
|
"driver_name": driverName,
|
|
"driver_avatar": avatar,
|
|
"arrival_time": car.HorarioChegada.String,
|
|
"notes": car.Observacoes.String,
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, resp)
|
|
}
|
|
|
|
// DeleteCarro
|
|
func (h *Handler) DeleteCarro(c *gin.Context) {
|
|
id := c.Param("id")
|
|
if id == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
|
|
return
|
|
}
|
|
if err := h.service.DeleteCarro(c.Request.Context(), id); err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"message": "deleted"})
|
|
}
|
|
|
|
// UpdateCarro
|
|
func (h *Handler) UpdateCarro(c *gin.Context) {
|
|
id := c.Param("id")
|
|
var req UpdateCarroInput
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
_, err := h.service.UpdateCarro(c.Request.Context(), id, req)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"message": "updated"})
|
|
}
|
|
|
|
// Passengers
|
|
type AddPassengerInput struct {
|
|
ProfissionalID string `json:"profissional_id"`
|
|
}
|
|
|
|
func (h *Handler) AddPassenger(c *gin.Context) {
|
|
carID := c.Param("id")
|
|
var req AddPassengerInput
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
err := h.service.AddPassageiro(c.Request.Context(), carID, req.ProfissionalID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"message": "passenger added"})
|
|
}
|
|
|
|
func (h *Handler) RemovePassenger(c *gin.Context) {
|
|
carID := c.Param("id")
|
|
profID := c.Param("profID")
|
|
err := h.service.RemovePassageiro(c.Request.Context(), carID, profID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"message": "passenger removed"})
|
|
}
|
|
|
|
func (h *Handler) ListPassengers(c *gin.Context) {
|
|
carID := c.Param("id")
|
|
passengers, err := h.service.ListPassageiros(c.Request.Context(), carID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
resp := make([]map[string]interface{}, len(passengers))
|
|
for i, p := range passengers {
|
|
resp[i] = map[string]interface{}{
|
|
"id": uuid.UUID(p.ID.Bytes).String(),
|
|
"profissional_id": uuid.UUID(p.ProfissionalID.Bytes).String(),
|
|
"name": p.Nome,
|
|
"avatar_url": p.AvatarUrl.String,
|
|
"role": p.FuncaoNome.String,
|
|
}
|
|
}
|
|
c.JSON(http.StatusOK, resp)
|
|
}
|
|
|
|
// ---- LOGISTICA DAILY INVITATIONS & PROFESSIONALS LIST ---- //
|
|
|
|
func (h *Handler) ListProfissionaisDisponiveis(c *gin.Context) {
|
|
var query ListDisponiveisInput
|
|
if err := c.ShouldBindQuery(&query); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
regiao := c.GetString("regiao")
|
|
res, err := h.service.ListProfissionaisDisponiveisLogistica(c.Request.Context(), query, regiao)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
formatted := make([]map[string]interface{}, len(res.Data))
|
|
for i, r := range res.Data {
|
|
formatted[i] = map[string]interface{}{
|
|
"id": uuid.UUID(r.ID.Bytes).String(),
|
|
"nome": r.Nome,
|
|
"role": r.FuncaoNome.String,
|
|
"avatar_url": r.AvatarUrl.String,
|
|
"whatsapp": r.Whatsapp.String,
|
|
"cidade": r.Cidade.String,
|
|
"carro_disponivel": r.CarroDisponivel.Bool,
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"data": formatted,
|
|
"total": res.Total,
|
|
"page": res.Page,
|
|
"total_pages": res.TotalPages,
|
|
})
|
|
}
|
|
|
|
func (h *Handler) CreateConvite(c *gin.Context) {
|
|
var req CreateConviteInput
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
regiao := c.GetString("regiao")
|
|
convite, err := h.service.CreateConviteDiario(c.Request.Context(), req, regiao)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"id": uuid.UUID(convite.ID.Bytes).String()})
|
|
}
|
|
|
|
// Get Invitations for logged professional
|
|
func (h *Handler) ListConvitesProfissional(c *gin.Context) {
|
|
// For MVP: Let the frontend send the prof ID or use a dedicated endpoint where frontend provides it.
|
|
// Actually frontend can provide ?prof_id=...
|
|
|
|
pID := c.Query("prof_id")
|
|
if pID == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "prof_id is required"})
|
|
return
|
|
}
|
|
|
|
convites, err := h.service.ListConvitesDoProfissional(c.Request.Context(), pID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Format response nicely
|
|
resp := make([]map[string]interface{}, len(convites))
|
|
for i, c := range convites {
|
|
// convert time.Time to YYYY-MM-DD
|
|
var dateStr string
|
|
if c.Data.Valid {
|
|
dateStr = c.Data.Time.Format("2006-01-02")
|
|
}
|
|
|
|
resp[i] = map[string]interface{}{
|
|
"id": uuid.UUID(c.ID.Bytes).String(),
|
|
"profissional_id": uuid.UUID(c.ProfissionalID.Bytes).String(),
|
|
"data": dateStr,
|
|
"status": c.Status.String,
|
|
"motivo_rejeicao": c.MotivoRejeicao.String,
|
|
"criado_em": c.CriadoEm.Time.Format("2006-01-02T15:04:05Z07:00"),
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, resp)
|
|
}
|
|
|
|
// Respond to an invitation
|
|
func (h *Handler) ResponderConvite(c *gin.Context) {
|
|
conviteID := c.Param("id")
|
|
if conviteID == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
|
|
return
|
|
}
|
|
|
|
var req ResponderConviteInput
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
convite, err := h.service.ResponderConvite(c.Request.Context(), conviteID, req)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"status": convite.Status.String})
|
|
}
|
|
|
|
// Get Invitations by Date for Logistics Manager
|
|
func (h *Handler) ListConvitesPorData(c *gin.Context) {
|
|
dataStr := c.Query("data")
|
|
if dataStr == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "data is required"})
|
|
return
|
|
}
|
|
|
|
regiao := c.GetString("regiao")
|
|
convites, err := h.service.ListConvitesPorData(c.Request.Context(), dataStr, regiao)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Format response
|
|
resp := make([]map[string]interface{}, len(convites))
|
|
for i, conv := range convites {
|
|
var dateStr string
|
|
if conv.Data.Valid {
|
|
dateStr = conv.Data.Time.Format("2006-01-02")
|
|
}
|
|
|
|
resp[i] = map[string]interface{}{
|
|
"id": uuid.UUID(conv.ID.Bytes).String(),
|
|
"profissional_id": uuid.UUID(conv.ProfissionalID.Bytes).String(),
|
|
"data": dateStr,
|
|
"status": conv.Status.String,
|
|
"motivo_rejeicao": conv.MotivoRejeicao.String,
|
|
"criado_em": conv.CriadoEm.Time.Format("2006-01-02T15:04:05Z07:00"),
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, resp)
|
|
}
|