Files
workorders/internal/api/handlers/attachment.go
T

108 lines
2.9 KiB
Go

package handlers
import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
"workorders/internal/config"
"workorders/internal/model"
)
type AttachmentHandler struct {
db *sqlx.DB
cfg *config.Config
}
func NewAttachmentHandler(db *sqlx.DB, cfg *config.Config) *AttachmentHandler {
return &AttachmentHandler{db: db, cfg: cfg}
}
func (h *AttachmentHandler) List(w http.ResponseWriter, r *http.Request) {
woID, err := intParam(r, "id")
if err != nil {
respondError(w, http.StatusBadRequest, "invalid id")
return
}
var atts []model.Attachment
if err := h.db.Select(&atts, `SELECT * FROM wo_attachments WHERE wo_id=@p1 ORDER BY uploaded_at`, woID); err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
return
}
for i := range atts {
atts[i].URL = "/uploads/" + atts[i].FilePath
}
respond(w, http.StatusOK, atts)
}
func (h *AttachmentHandler) Upload(w http.ResponseWriter, r *http.Request) {
woID, err := intParam(r, "id")
if err != nil {
respondError(w, http.StatusBadRequest, "invalid id")
return
}
user := userFromCtx(r)
if err := r.ParseMultipartForm(32 << 20); err != nil {
respondError(w, http.StatusBadRequest, "parse form failed")
return
}
file, header, err := r.FormFile("file")
if err != nil {
respondError(w, http.StatusBadRequest, "missing file")
return
}
defer file.Close()
ext := filepath.Ext(header.Filename)
fname := uuid.New().String() + ext
relPath := fmt.Sprintf("%d/%s", woID, fname)
absPath := filepath.Join(h.cfg.UploadPath, relPath)
if err := os.MkdirAll(filepath.Dir(absPath), 0755); err != nil {
respondError(w, http.StatusInternalServerError, "storage error")
return
}
dst, err := os.Create(absPath)
if err != nil {
respondError(w, http.StatusInternalServerError, "storage error")
return
}
defer dst.Close()
size, _ := io.Copy(dst, file)
var aid int
err = h.db.QueryRow(`
INSERT INTO wo_attachments (wo_id,file_name,file_path,file_type,file_size,caption,phase,uploaded_by)
OUTPUT INSERTED.id VALUES (@p1,@p2,@p3,@p4,@p5,@p6,@p7,@p8)`,
woID, header.Filename, relPath, header.Header.Get("Content-Type"),
size, r.FormValue("caption"), r.FormValue("phase"), user.Email,
).Scan(&aid)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
return
}
respond(w, http.StatusCreated, map[string]any{
"id": aid,
"url": "/uploads/" + relPath,
})
}
func (h *AttachmentHandler) Delete(w http.ResponseWriter, r *http.Request) {
aid, err := intParam(r, "aid")
if err != nil {
respondError(w, http.StatusBadRequest, "invalid aid")
return
}
var att model.Attachment
if err := h.db.Get(&att, `SELECT * FROM wo_attachments WHERE id=@p1`, aid); err == nil {
os.Remove(filepath.Join(h.cfg.UploadPath, att.FilePath))
}
h.db.Exec(`DELETE FROM wo_attachments WHERE id=@p1`, aid)
respond(w, http.StatusOK, map[string]any{"deleted": aid})
}