Added Printjobs
This commit is contained in:
@@ -17,6 +17,7 @@ func NewHandler() http.Handler {
|
||||
items := store.NewItemStore("")
|
||||
configs := store.NewConfigurationStore("")
|
||||
orders := store.NewOrderStore("")
|
||||
printJobs := store.NewPrintJobStore("")
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("GET /health", health)
|
||||
@@ -32,6 +33,7 @@ func NewHandler() http.Handler {
|
||||
mux.HandleFunc("GET /items/{id}/svg", serveItemSVG(items))
|
||||
registerConfigurationRoutes(mux, configs, plates, items)
|
||||
registerOrderRoutes(mux, orders)
|
||||
registerPrintJobRoutes(mux, printJobs, configs, plates, items, orders)
|
||||
return withCORS(mux)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"printer.backend/internal/model"
|
||||
"printer.backend/internal/printjob"
|
||||
"printer.backend/internal/store"
|
||||
)
|
||||
|
||||
func registerPrintJobRoutes(
|
||||
mux *http.ServeMux,
|
||||
jobs *store.PrintJobStore,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) {
|
||||
mux.HandleFunc("GET /print-jobs", listPrintJobs(jobs, configs, plates, items, orders))
|
||||
mux.HandleFunc("POST /print-jobs", savePrintJob(jobs, configs, orders))
|
||||
mux.HandleFunc("GET /print-jobs/{id}", getPrintJob(jobs, configs, plates, items, orders))
|
||||
mux.HandleFunc("PUT /print-jobs/{id}", updatePrintJob(jobs, configs, orders))
|
||||
mux.HandleFunc("DELETE /print-jobs/{id}", deletePrintJob(jobs))
|
||||
mux.HandleFunc("GET /print-jobs/{id}/summary", printJobSummary(jobs, configs, plates, items, orders))
|
||||
mux.HandleFunc("GET /print-jobs/{id}/pdf", printJobPDF(jobs, configs, plates, items, orders))
|
||||
}
|
||||
|
||||
type printJobResponse struct {
|
||||
model.PrintJob
|
||||
Summary *model.PrintJobSummary `json:"summary,omitempty"`
|
||||
}
|
||||
|
||||
type savePrintJobRequest struct {
|
||||
Name string `json:"name"`
|
||||
ConfigurationID string `json:"configuration_id"`
|
||||
OrderIDs []string `json:"order_ids"`
|
||||
}
|
||||
|
||||
func listPrintJobs(
|
||||
jobs *store.PrintJobStore,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, _ *http.Request) {
|
||||
list, err := jobs.List()
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if list == nil {
|
||||
list = []model.PrintJob{}
|
||||
}
|
||||
out := make([]printJobResponse, 0, len(list))
|
||||
for _, j := range list {
|
||||
out = append(out, printJobResponseFor(j, configs, plates, items, orders))
|
||||
}
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
}
|
||||
|
||||
func savePrintJob(jobs *store.PrintJobStore, configs *store.ConfigurationStore, orders *store.OrderStore) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req savePrintJobRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if err := validatePrintJobRequest(req, configs, orders); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
j := model.PrintJob{
|
||||
Name: req.Name,
|
||||
ConfigurationID: req.ConfigurationID,
|
||||
OrderIDs: req.OrderIDs,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
saved, err := jobs.Save(j)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusCreated, saved)
|
||||
}
|
||||
}
|
||||
|
||||
func getPrintJob(
|
||||
jobs *store.PrintJobStore,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
j, err := jobs.Get(r.PathValue("id"))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, printJobResponseFor(j, configs, plates, items, orders))
|
||||
}
|
||||
}
|
||||
|
||||
func updatePrintJob(jobs *store.PrintJobStore, configs *store.ConfigurationStore, orders *store.OrderStore) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
var req savePrintJobRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if err := validatePrintJobRequest(req, configs, orders); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
j := model.PrintJob{
|
||||
Name: req.Name,
|
||||
ConfigurationID: req.ConfigurationID,
|
||||
OrderIDs: req.OrderIDs,
|
||||
}
|
||||
saved, err := jobs.Update(id, j)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, saved)
|
||||
}
|
||||
}
|
||||
|
||||
func deletePrintJob(jobs *store.PrintJobStore) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := jobs.Delete(r.PathValue("id")); err != nil {
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
func printJobSummary(
|
||||
jobs *store.PrintJobStore,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
j, err := jobs.Get(r.PathValue("id"))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
summary, err := buildPrintJobSummary(j, configs, plates, items, orders)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, summary)
|
||||
}
|
||||
}
|
||||
|
||||
func printJobPDF(
|
||||
jobs *store.PrintJobStore,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
j, err := jobs.Get(r.PathValue("id"))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
pdf, summary, err := printjob.RenderPDF(j, configs, plates, items, orders)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if summary.ImageOverflow {
|
||||
w.Header().Set("X-Print-Job-Warning", summary.Warning)
|
||||
}
|
||||
name := j.Name
|
||||
if name == "" {
|
||||
name = "print-job-" + j.ID[:8]
|
||||
}
|
||||
servePDF(w, pdf, sanitizeFilename(name)+".pdf")
|
||||
}
|
||||
}
|
||||
|
||||
func validatePrintJobRequest(req savePrintJobRequest, configs *store.ConfigurationStore, orders *store.OrderStore) error {
|
||||
if req.ConfigurationID == "" {
|
||||
return errors.New("configuration_id is required")
|
||||
}
|
||||
if _, err := configs.Get(req.ConfigurationID); err != nil {
|
||||
return errors.New("configuration not found: " + req.ConfigurationID)
|
||||
}
|
||||
if len(req.OrderIDs) == 0 {
|
||||
return errors.New("at least one order_id is required")
|
||||
}
|
||||
for _, id := range req.OrderIDs {
|
||||
if _, err := orders.Get(id); err != nil {
|
||||
return errors.New("order not found: " + id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printJobResponseFor(
|
||||
j model.PrintJob,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) printJobResponse {
|
||||
resp := printJobResponse{PrintJob: j}
|
||||
if summary, err := buildPrintJobSummary(j, configs, plates, items, orders); err == nil {
|
||||
resp.Summary = &summary
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func buildPrintJobSummary(
|
||||
j model.PrintJob,
|
||||
configs *store.ConfigurationStore,
|
||||
plates *store.PlateStore,
|
||||
items *store.ItemStore,
|
||||
orders *store.OrderStore,
|
||||
) (model.PrintJobSummary, error) {
|
||||
cfg, err := configs.Get(j.ConfigurationID)
|
||||
if err != nil {
|
||||
return model.PrintJobSummary{}, err
|
||||
}
|
||||
preview, err := buildPreview(plates, items, cfg.PlateID, cfg.ItemID, cfg.SpacingMM)
|
||||
if err != nil {
|
||||
return model.PrintJobSummary{}, err
|
||||
}
|
||||
orderList := make([]model.Order, 0, len(j.OrderIDs))
|
||||
for _, id := range j.OrderIDs {
|
||||
o, err := orders.Get(id)
|
||||
if err != nil {
|
||||
return model.PrintJobSummary{}, err
|
||||
}
|
||||
orderList = append(orderList, o)
|
||||
}
|
||||
return printjob.Summary(orderList, preview), nil
|
||||
}
|
||||
Reference in New Issue
Block a user