135 lines
4.0 KiB
Go
135 lines
4.0 KiB
Go
package document
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"production/internal/auth"
|
|
"production/internal/authz"
|
|
"production/internal/doctemplates"
|
|
"production/internal/pdfgen"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
type batchItem struct {
|
|
model, color, price string
|
|
}
|
|
|
|
type batchClient struct {
|
|
id string
|
|
createdAt time.Time
|
|
client pdfgen.Client
|
|
items []batchItem
|
|
}
|
|
|
|
func (h *Handler) loadBatch(ctx context.Context, batchID string) (batchClient, error) {
|
|
var bc batchClient
|
|
var clientEmail, clientINN, clientKPP, clientCompanyAddress *string
|
|
|
|
err := h.db.QueryRow(ctx, `
|
|
SELECT cb.id, cb.created_at,
|
|
cl.type, cl.name, cl.phone, cl.email, cl.inn, cl.kpp, cl.company_address
|
|
FROM cartridge_batches cb JOIN clients cl ON cl.id = cb.client_id
|
|
WHERE cb.id = $1::uuid`, batchID,
|
|
).Scan(&bc.id, &bc.createdAt, &bc.client.Type, &bc.client.Name, &bc.client.Phone,
|
|
&clientEmail, &clientINN, &clientKPP, &clientCompanyAddress)
|
|
if err != nil {
|
|
return bc, err
|
|
}
|
|
bc.client.Email = deref(clientEmail)
|
|
bc.client.INN = deref(clientINN)
|
|
bc.client.KPP = deref(clientKPP)
|
|
bc.client.CompanyAddress = deref(clientCompanyAddress)
|
|
|
|
rows, err := h.db.Query(ctx,
|
|
`SELECT model, color, price::text FROM cartridge_items WHERE batch_id = $1::uuid ORDER BY position`, batchID)
|
|
if err != nil {
|
|
return bc, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var it batchItem
|
|
var price *string
|
|
if err := rows.Scan(&it.model, &it.color, &price); err != nil {
|
|
return bc, err
|
|
}
|
|
it.price = deref(price)
|
|
bc.items = append(bc.items, it)
|
|
}
|
|
return bc, rows.Err()
|
|
}
|
|
|
|
func cartridgeItemName(model, color string) string {
|
|
return fmt.Sprintf("Заправка картриджа %s (%s)", model, color)
|
|
}
|
|
|
|
func (h *Handler) BatchInvoice(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
ctx := context.Background()
|
|
if err := authz.CheckBatchAccess(ctx, h.db, id, auth.StaffPermissions(c), auth.StaffID(c)); err != nil {
|
|
return err
|
|
}
|
|
bc, err := h.loadBatch(ctx, id)
|
|
if err != nil {
|
|
return h.notFoundOr500(c, "cartridge batch", id, err)
|
|
}
|
|
business, err := h.loadBusiness(ctx)
|
|
if err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
|
|
}
|
|
blocks, err := doctemplates.Fetch(ctx, h.db, doctemplates.KindInvoice)
|
|
if err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
|
|
}
|
|
|
|
items := make([]pdfgen.LineItem, len(bc.items))
|
|
for i, it := range bc.items {
|
|
items[i] = pdfgen.LineItem{Name: cartridgeItemName(it.model, it.color), Qty: 1, Price: it.price}
|
|
}
|
|
|
|
doc := pdfgen.InvoiceDoc{ID: bc.id, CreatedAt: bc.createdAt, Items: items}
|
|
pdfBytes, err := pdfgen.GenerateInvoice(business, bc.client, doc, blocks)
|
|
return h.servePDF(c, "invoice", bc.id, pdfBytes, err)
|
|
}
|
|
|
|
func (h *Handler) BatchAct(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
ctx := context.Background()
|
|
if err := authz.CheckBatchAccess(ctx, h.db, id, auth.StaffPermissions(c), auth.StaffID(c)); err != nil {
|
|
return err
|
|
}
|
|
bc, err := h.loadBatch(ctx, id)
|
|
if err != nil {
|
|
return h.notFoundOr500(c, "cartridge batch", id, err)
|
|
}
|
|
business, err := h.loadBusiness(ctx)
|
|
if err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
|
|
}
|
|
blocks, err := doctemplates.Fetch(ctx, h.db, doctemplates.KindAct)
|
|
if err != nil {
|
|
return c.Status(500).JSON(fiber.Map{"error": "internal error"})
|
|
}
|
|
|
|
lines := make([]string, len(bc.items))
|
|
priceLines := make([]pdfgen.LineItem, len(bc.items))
|
|
for i, it := range bc.items {
|
|
lines[i] = fmt.Sprintf("%d. %s", i+1, cartridgeItemName(it.model, it.color))
|
|
priceLines[i] = pdfgen.LineItem{Price: it.price}
|
|
}
|
|
|
|
doc := pdfgen.ActDoc{
|
|
ID: bc.id,
|
|
CreatedAt: bc.createdAt,
|
|
IntroLine: fmt.Sprintf("Исполнитель произвёл заправку/восстановление картриджей (%d шт.):", len(bc.items)),
|
|
WorkSummary: strings.Join(lines, "\n"),
|
|
Total: sumLineItemPrices(priceLines),
|
|
}
|
|
pdfBytes, err := pdfgen.GenerateAct(business, bc.client, doc, blocks)
|
|
return h.servePDF(c, "act", bc.id, pdfBytes, err)
|
|
}
|