package services import ( "net/http" "strconv" "time" "wm-backend/global" "wm-backend/internal/models" "wm-backend/internal/models/requests" "wm-backend/internal/models/responses" "wm-backend/internal/repositories" "wm-backend/pkg/helper" "wm-backend/response" "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" ) // InvoiceCreate creates a new invoice. // // @Summary Create a new invoice // @Description Create a new invoice with the provided details // @Tags invoice // @Accept json // @Produce json // @Param body body requests.CreateInvoiceRequest true "Invoice request body" // @Success 201 {object} response.SuccessResponse{data=responses.CreateInvoiceResponse} // @Failure 400 {object} response.ErrorResponse // @Failure 500 {object} response.ErrorResponse // @Router /v1/invoices [post] func InvoiceCreate(c *gin.Context) error { requestBody := requests.CreateInvoiceRequest{} if helper.IsShouldBindJSON(c, &requestBody) { return nil } invoiceModel := &models.Invoice{ Type: requestBody.Type, Status: requestBody.Status, InvoiceConfigID: requestBody.InvoiceConfigID, TotalItems: requestBody.TotalItems, Note: requestBody.Note, CreatedBy: requestBody.CreatedBy, ApprovedBy: requestBody.ApprovedBy, CreatedAt: time.Now(), } invoice, err := repositories.CreateInvoice(c.Request.Context(), global.Queries, *invoiceModel) if err != nil { log.Error().Err(err).Msg("Failed to create invoice") response.InternalServerError(c, http.StatusInternalServerError, "Failed to create invoice") return nil } response.Created(c, "Invoice created successfully", &responses.CreateInvoiceResponse{ ID: invoice.ID, InvoiceCode: invoice.InvoiceCode, }) return nil } // InvoiceGetByID retrieves a single invoice by its ID. // // @Summary Get invoice by ID // @Description Retrieve a single invoice using its unique identifier // @Tags invoice // @Accept json // @Produce json // @Param id path int true "Invoice ID" // @Success 200 {object} response.SuccessResponse{data=models.Invoice} // @Failure 400 {object} response.ErrorResponse // @Failure 404 {object} response.ErrorResponse // @Failure 500 {object} response.ErrorResponse // @Router /v1/invoices/{id} [get] func InvoiceGetByID(c *gin.Context) error { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { response.BadRequestError(c, http.StatusBadRequest, "Invalid ID") return nil } invoice, err := repositories.GetInvoiceByID(c.Request.Context(), global.Queries, id) if err != nil { log.Error().Err(err).Msgf("Failed to get invoice by ID: %d", id) response.NotFoundError(c, http.StatusNotFound, "Invoice not found") return nil } response.Ok(c, "Success", invoice) return nil } // InvoiceList retrieves all invoices. // // @Summary List all invoices // @Description Retrieve a list of all invoices ordered by creation date // @Tags invoice // @Accept json // @Produce json // @Success 200 {object} response.SuccessResponse{data=[]models.Invoice} // @Failure 500 {object} response.ErrorResponse // @Router /v1/invoices [get] func InvoiceList(c *gin.Context) error { invoices, err := repositories.ListInvoices(c.Request.Context(), global.Queries) if err != nil { response.InternalServerError(c, http.StatusInternalServerError, "Failed to list invoices") return nil } response.Ok(c, "Success", invoices) return nil } // InvoiceUpdate updates an existing invoice by its ID. // // @Summary Update invoice // @Description Update an existing invoice by its ID. Only non-empty fields will be updated. // @Tags invoice // @Accept json // @Produce json // @Param id path int true "Invoice ID" // @Param body body requests.UpdateInvoiceRequest true "Invoice request body" // @Success 200 {object} response.SuccessResponse{data=responses.UpdateInvoiceResponse} // @Failure 400 {object} response.ErrorResponse // @Failure 404 {object} response.ErrorResponse // @Failure 500 {object} response.ErrorResponse // @Router /v1/invoices/{id} [put] func InvoiceUpdate(c *gin.Context) error { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { response.BadRequestError(c, http.StatusBadRequest, "Invalid ID") return nil } requestBody := requests.UpdateInvoiceRequest{} if helper.IsShouldBindJSON(c, &requestBody) { return nil } existing, err := repositories.GetInvoiceByID(c.Request.Context(), global.Queries, id) if err != nil { response.NotFoundError(c, http.StatusNotFound, "Invoice not found") return nil } if requestBody.Type != nil { existing.Type = *requestBody.Type } if requestBody.Status != nil { existing.Status = *requestBody.Status } if requestBody.InvoiceConfigID != nil { existing.InvoiceConfigID = *requestBody.InvoiceConfigID } if requestBody.TotalItems != nil { existing.TotalItems = *requestBody.TotalItems } if requestBody.Note != "" { existing.Note = requestBody.Note } existing.UpdatedAt = time.Now() invoice, err := repositories.UpdateInvoice(c.Request.Context(), global.Queries, existing) if err != nil { log.Error().Err(err).Msgf("Failed to update invoice with ID: %d", id) response.InternalServerError(c, http.StatusInternalServerError, "Failed to update invoice") return nil } response.Ok(c, "Invoice updated successfully", &responses.UpdateInvoiceResponse{ ID: invoice.ID, InvoiceCode: invoice.InvoiceCode, Type: invoice.Type, Status: invoice.Status, InvoiceConfigID: invoice.InvoiceConfigID, TotalItems: invoice.TotalItems, Note: invoice.Note, }) return nil } // InvoiceDelete deletes an invoice by its ID. // // @Summary Delete invoice // @Description Delete an invoice by its unique identifier // @Tags invoice // @Accept json // @Produce json // @Param id path int true "Invoice ID" // @Success 200 {object} response.SuccessResponse // @Failure 400 {object} response.ErrorResponse // @Failure 500 {object} response.ErrorResponse // @Router /v1/invoices/{id} [delete] func InvoiceDelete(c *gin.Context) error { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { response.BadRequestError(c, http.StatusBadRequest, "Invalid ID") return nil } rowsAffected, err := repositories.DeleteInvoice(c.Request.Context(), global.Queries, id) if err != nil { log.Error().Err(err).Msgf("Failed to delete invoice with ID: %d", id) response.InternalServerError(c, http.StatusInternalServerError, "Failed to delete invoice") return nil } if rowsAffected == 0 { response.NotFoundError(c, http.StatusNotFound, "Invoice not found") return nil } response.Ok(c, "Delete Success", nil) return nil }