Progress on the go-rewrite
This commit is contained in:
parent
4f54a93c62
commit
28b331737f
|
|
@ -167,6 +167,9 @@ func main() {
|
|||
w.Write([]byte(`{"status":"ok"}`))
|
||||
}).Methods("GET")
|
||||
|
||||
// Recent activity endpoint
|
||||
r.HandleFunc("/api/recent-activity", documentHandler.GetRecentActivity).Methods("GET")
|
||||
|
||||
// Page routes
|
||||
r.HandleFunc("/", pageHandler.Home).Methods("GET")
|
||||
|
||||
|
|
|
|||
|
|
@ -11,39 +11,40 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const archiveDocument = `-- name: ArchiveDocument :exec
|
||||
DELETE FROM documents
|
||||
WHERE id = ?
|
||||
const countDocuments = `-- name: CountDocuments :one
|
||||
SELECT COUNT(*) FROM documents
|
||||
`
|
||||
|
||||
func (q *Queries) ArchiveDocument(ctx context.Context, id int32) error {
|
||||
_, err := q.db.ExecContext(ctx, archiveDocument, id)
|
||||
return err
|
||||
func (q *Queries) CountDocuments(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, countDocuments)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const countDocumentsByType = `-- name: CountDocumentsByType :one
|
||||
SELECT COUNT(*) FROM documents WHERE type = ?
|
||||
`
|
||||
|
||||
func (q *Queries) CountDocumentsByType(ctx context.Context, type_ DocumentsType) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, countDocumentsByType, type_)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createDocument = `-- name: CreateDocument :execresult
|
||||
INSERT INTO documents (
|
||||
type,
|
||||
created,
|
||||
user_id,
|
||||
doc_page_count,
|
||||
cmc_reference,
|
||||
pdf_filename,
|
||||
pdf_created_at,
|
||||
pdf_created_by_user_id,
|
||||
shipping_details,
|
||||
revision,
|
||||
bill_to,
|
||||
ship_to,
|
||||
email_sent_at,
|
||||
email_sent_by_user_id
|
||||
) VALUES (
|
||||
?, NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
)
|
||||
type, created, user_id, doc_page_count, cmc_reference,
|
||||
pdf_filename, pdf_created_at, pdf_created_by_user_id,
|
||||
shipping_details, revision, bill_to, ship_to,
|
||||
email_sent_at, email_sent_by_user_id
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`
|
||||
|
||||
type CreateDocumentParams struct {
|
||||
Type DocumentsType `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
UserID int32 `json:"user_id"`
|
||||
DocPageCount int32 `json:"doc_page_count"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
|
|
@ -61,6 +62,7 @@ type CreateDocumentParams struct {
|
|||
func (q *Queries) CreateDocument(ctx context.Context, arg CreateDocumentParams) (sql.Result, error) {
|
||||
return q.db.ExecContext(ctx, createDocument,
|
||||
arg.Type,
|
||||
arg.Created,
|
||||
arg.UserID,
|
||||
arg.DocPageCount,
|
||||
arg.CmcReference,
|
||||
|
|
@ -76,219 +78,230 @@ func (q *Queries) CreateDocument(ctx context.Context, arg CreateDocumentParams)
|
|||
)
|
||||
}
|
||||
|
||||
const getDocumentByID = `-- name: GetDocumentByID :one
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.revision,
|
||||
d.shipping_details,
|
||||
d.bill_to,
|
||||
d.ship_to,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username,
|
||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
||||
e.title as enquiry_title
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
||||
LEFT JOIN customers ec ON e.customer_id = ec.id
|
||||
LEFT JOIN invoices i ON d.type = 'invoice' AND d.cmc_reference = i.title
|
||||
LEFT JOIN customers ic ON i.customer_id = ic.id
|
||||
WHERE d.id = ?
|
||||
const deleteDocument = `-- name: DeleteDocument :exec
|
||||
DELETE FROM documents WHERE id = ?
|
||||
`
|
||||
|
||||
type GetDocumentByIDRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Type DocumentsType `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
UserID int32 `json:"user_id"`
|
||||
DocPageCount int32 `json:"doc_page_count"`
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
||||
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
Revision int32 `json:"revision"`
|
||||
ShippingDetails sql.NullString `json:"shipping_details"`
|
||||
BillTo sql.NullString `json:"bill_to"`
|
||||
ShipTo sql.NullString `json:"ship_to"`
|
||||
EmailSentAt time.Time `json:"email_sent_at"`
|
||||
EmailSentByUserID int32 `json:"email_sent_by_user_id"`
|
||||
UserFirstName sql.NullString `json:"user_first_name"`
|
||||
UserLastName sql.NullString `json:"user_last_name"`
|
||||
UserUsername sql.NullString `json:"user_username"`
|
||||
PdfCreatorFirstName sql.NullString `json:"pdf_creator_first_name"`
|
||||
PdfCreatorLastName sql.NullString `json:"pdf_creator_last_name"`
|
||||
PdfCreatorUsername sql.NullString `json:"pdf_creator_username"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
EnquiryTitle sql.NullString `json:"enquiry_title"`
|
||||
func (q *Queries) DeleteDocument(ctx context.Context, id int32) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteDocument, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (q *Queries) GetDocumentByID(ctx context.Context, id int32) (GetDocumentByIDRow, error) {
|
||||
row := q.db.QueryRowContext(ctx, getDocumentByID, id)
|
||||
var i GetDocumentByIDRow
|
||||
const getDocument = `-- name: GetDocument :one
|
||||
SELECT id, type, created, user_id, doc_page_count, cmc_reference, pdf_filename, pdf_created_at, pdf_created_by_user_id, shipping_details, revision, bill_to, ship_to, email_sent_at, email_sent_by_user_id FROM documents WHERE id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) GetDocument(ctx context.Context, id int32) (Document, error) {
|
||||
row := q.db.QueryRowContext(ctx, getDocument, id)
|
||||
var i Document
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.Created,
|
||||
&i.UserID,
|
||||
&i.DocPageCount,
|
||||
&i.CmcReference,
|
||||
&i.PdfFilename,
|
||||
&i.PdfCreatedAt,
|
||||
&i.PdfCreatedByUserID,
|
||||
&i.CmcReference,
|
||||
&i.Revision,
|
||||
&i.ShippingDetails,
|
||||
&i.Revision,
|
||||
&i.BillTo,
|
||||
&i.ShipTo,
|
||||
&i.EmailSentAt,
|
||||
&i.EmailSentByUserID,
|
||||
&i.UserFirstName,
|
||||
&i.UserLastName,
|
||||
&i.UserUsername,
|
||||
&i.PdfCreatorFirstName,
|
||||
&i.PdfCreatorLastName,
|
||||
&i.PdfCreatorUsername,
|
||||
&i.CustomerName,
|
||||
&i.EnquiryTitle,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getPurchaseOrderByDocumentID = `-- name: GetPurchaseOrderByDocumentID :one
|
||||
SELECT
|
||||
po.id,
|
||||
po.title,
|
||||
po.principle_id,
|
||||
po.principle_reference,
|
||||
po.issue_date,
|
||||
po.ordered_from,
|
||||
po.dispatch_by,
|
||||
po.deliver_to,
|
||||
po.shipping_instructions
|
||||
FROM purchase_orders po
|
||||
JOIN documents d ON d.cmc_reference = po.title
|
||||
WHERE d.id = ? AND d.type = 'purchaseOrder'
|
||||
`
|
||||
|
||||
type GetPurchaseOrderByDocumentIDRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
PrincipleID int32 `json:"principle_id"`
|
||||
PrincipleReference string `json:"principle_reference"`
|
||||
IssueDate time.Time `json:"issue_date"`
|
||||
OrderedFrom string `json:"ordered_from"`
|
||||
DispatchBy string `json:"dispatch_by"`
|
||||
DeliverTo string `json:"deliver_to"`
|
||||
ShippingInstructions string `json:"shipping_instructions"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetPurchaseOrderByDocumentID(ctx context.Context, id int32) (GetPurchaseOrderByDocumentIDRow, error) {
|
||||
row := q.db.QueryRowContext(ctx, getPurchaseOrderByDocumentID, id)
|
||||
var i GetPurchaseOrderByDocumentIDRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.PrincipleID,
|
||||
&i.PrincipleReference,
|
||||
&i.IssueDate,
|
||||
&i.OrderedFrom,
|
||||
&i.DispatchBy,
|
||||
&i.DeliverTo,
|
||||
&i.ShippingInstructions,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listDocuments = `-- name: ListDocuments :many
|
||||
const getDocumentWithUser = `-- name: GetDocumentWithUser :one
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.cmc_reference,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.shipping_details,
|
||||
d.revision,
|
||||
d.bill_to,
|
||||
d.ship_to,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.username as user_username,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username
|
||||
u.email as user_email,
|
||||
pu.username as pdf_creator_username,
|
||||
pu.first_name as pdf_creator_first_name,
|
||||
pu.last_name as pdf_creator_last_name,
|
||||
pu.email as pdf_creator_email
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
ORDER BY d.id DESC
|
||||
LIMIT 1000
|
||||
LEFT JOIN users pu ON d.pdf_created_by_user_id = pu.id
|
||||
WHERE d.id = ?
|
||||
`
|
||||
|
||||
type ListDocumentsRow struct {
|
||||
type GetDocumentWithUserRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Type DocumentsType `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
UserID int32 `json:"user_id"`
|
||||
DocPageCount int32 `json:"doc_page_count"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
||||
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
ShippingDetails sql.NullString `json:"shipping_details"`
|
||||
Revision int32 `json:"revision"`
|
||||
BillTo sql.NullString `json:"bill_to"`
|
||||
ShipTo sql.NullString `json:"ship_to"`
|
||||
EmailSentAt time.Time `json:"email_sent_at"`
|
||||
EmailSentByUserID int32 `json:"email_sent_by_user_id"`
|
||||
UserUsername sql.NullString `json:"user_username"`
|
||||
UserFirstName sql.NullString `json:"user_first_name"`
|
||||
UserLastName sql.NullString `json:"user_last_name"`
|
||||
UserUsername sql.NullString `json:"user_username"`
|
||||
UserEmail sql.NullString `json:"user_email"`
|
||||
PdfCreatorUsername sql.NullString `json:"pdf_creator_username"`
|
||||
PdfCreatorFirstName sql.NullString `json:"pdf_creator_first_name"`
|
||||
PdfCreatorLastName sql.NullString `json:"pdf_creator_last_name"`
|
||||
PdfCreatorUsername sql.NullString `json:"pdf_creator_username"`
|
||||
PdfCreatorEmail sql.NullString `json:"pdf_creator_email"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListDocuments(ctx context.Context) ([]ListDocumentsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listDocuments)
|
||||
func (q *Queries) GetDocumentWithUser(ctx context.Context, id int32) (GetDocumentWithUserRow, error) {
|
||||
row := q.db.QueryRowContext(ctx, getDocumentWithUser, id)
|
||||
var i GetDocumentWithUserRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.Created,
|
||||
&i.UserID,
|
||||
&i.DocPageCount,
|
||||
&i.CmcReference,
|
||||
&i.PdfFilename,
|
||||
&i.PdfCreatedAt,
|
||||
&i.PdfCreatedByUserID,
|
||||
&i.ShippingDetails,
|
||||
&i.Revision,
|
||||
&i.BillTo,
|
||||
&i.ShipTo,
|
||||
&i.EmailSentAt,
|
||||
&i.EmailSentByUserID,
|
||||
&i.UserUsername,
|
||||
&i.UserFirstName,
|
||||
&i.UserLastName,
|
||||
&i.UserEmail,
|
||||
&i.PdfCreatorUsername,
|
||||
&i.PdfCreatorFirstName,
|
||||
&i.PdfCreatorLastName,
|
||||
&i.PdfCreatorEmail,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getRecentDocuments = `-- name: GetRecentDocuments :many
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.cmc_reference,
|
||||
d.pdf_filename,
|
||||
d.revision,
|
||||
u.username as created_by_username,
|
||||
CASE
|
||||
WHEN d.type = 'quote' THEN CONCAT('Quote ', d.cmc_reference)
|
||||
WHEN d.type = 'invoice' THEN CONCAT('Invoice ', d.cmc_reference)
|
||||
WHEN d.type = 'purchaseOrder' THEN CONCAT('Purchase Order ', d.cmc_reference)
|
||||
WHEN d.type = 'orderAck' THEN CONCAT('Order Ack ', d.cmc_reference)
|
||||
WHEN d.type = 'packingList' THEN CONCAT('Packing List ', d.cmc_reference)
|
||||
ELSE CONCAT(d.type, ' ', d.cmc_reference)
|
||||
END as display_name
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
ORDER BY d.created DESC
|
||||
LIMIT ?
|
||||
`
|
||||
|
||||
type GetRecentDocumentsRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Type DocumentsType `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
Revision int32 `json:"revision"`
|
||||
CreatedByUsername sql.NullString `json:"created_by_username"`
|
||||
DisplayName interface{} `json:"display_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetRecentDocuments(ctx context.Context, limit int32) ([]GetRecentDocumentsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getRecentDocuments, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListDocumentsRow{}
|
||||
items := []GetRecentDocumentsRow{}
|
||||
for rows.Next() {
|
||||
var i ListDocumentsRow
|
||||
var i GetRecentDocumentsRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.Created,
|
||||
&i.CmcReference,
|
||||
&i.PdfFilename,
|
||||
&i.Revision,
|
||||
&i.CreatedByUsername,
|
||||
&i.DisplayName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listDocuments = `-- name: ListDocuments :many
|
||||
SELECT id, type, created, user_id, doc_page_count, cmc_reference, pdf_filename, pdf_created_at, pdf_created_by_user_id, shipping_details, revision, bill_to, ship_to, email_sent_at, email_sent_by_user_id FROM documents ORDER BY created DESC LIMIT ? OFFSET ?
|
||||
`
|
||||
|
||||
type ListDocumentsParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListDocuments(ctx context.Context, arg ListDocumentsParams) ([]Document, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listDocuments, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []Document{}
|
||||
for rows.Next() {
|
||||
var i Document
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.Created,
|
||||
&i.UserID,
|
||||
&i.DocPageCount,
|
||||
&i.CmcReference,
|
||||
&i.PdfFilename,
|
||||
&i.PdfCreatedAt,
|
||||
&i.PdfCreatedByUserID,
|
||||
&i.CmcReference,
|
||||
&i.ShippingDetails,
|
||||
&i.Revision,
|
||||
&i.BillTo,
|
||||
&i.ShipTo,
|
||||
&i.EmailSentAt,
|
||||
&i.EmailSentByUserID,
|
||||
&i.UserFirstName,
|
||||
&i.UserLastName,
|
||||
&i.UserUsername,
|
||||
&i.PdfCreatorFirstName,
|
||||
&i.PdfCreatorLastName,
|
||||
&i.PdfCreatorUsername,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -304,92 +317,40 @@ func (q *Queries) ListDocuments(ctx context.Context) ([]ListDocumentsRow, error)
|
|||
}
|
||||
|
||||
const listDocumentsByType = `-- name: ListDocumentsByType :many
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.revision,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username,
|
||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
||||
e.title as enquiry_title
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
||||
LEFT JOIN customers ec ON e.customer_id = ec.id
|
||||
LEFT JOIN invoices i ON d.type = 'invoice' AND d.cmc_reference = i.title
|
||||
LEFT JOIN customers ic ON i.customer_id = ic.id
|
||||
WHERE d.type = ?
|
||||
ORDER BY d.id DESC
|
||||
LIMIT 1000
|
||||
SELECT id, type, created, user_id, doc_page_count, cmc_reference, pdf_filename, pdf_created_at, pdf_created_by_user_id, shipping_details, revision, bill_to, ship_to, email_sent_at, email_sent_by_user_id FROM documents WHERE type = ? ORDER BY created DESC LIMIT ? OFFSET ?
|
||||
`
|
||||
|
||||
type ListDocumentsByTypeRow struct {
|
||||
ID int32 `json:"id"`
|
||||
type ListDocumentsByTypeParams struct {
|
||||
Type DocumentsType `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
UserID int32 `json:"user_id"`
|
||||
DocPageCount int32 `json:"doc_page_count"`
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
||||
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
Revision int32 `json:"revision"`
|
||||
EmailSentAt time.Time `json:"email_sent_at"`
|
||||
EmailSentByUserID int32 `json:"email_sent_by_user_id"`
|
||||
UserFirstName sql.NullString `json:"user_first_name"`
|
||||
UserLastName sql.NullString `json:"user_last_name"`
|
||||
UserUsername sql.NullString `json:"user_username"`
|
||||
PdfCreatorFirstName sql.NullString `json:"pdf_creator_first_name"`
|
||||
PdfCreatorLastName sql.NullString `json:"pdf_creator_last_name"`
|
||||
PdfCreatorUsername sql.NullString `json:"pdf_creator_username"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
EnquiryTitle sql.NullString `json:"enquiry_title"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListDocumentsByType(ctx context.Context, type_ DocumentsType) ([]ListDocumentsByTypeRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listDocumentsByType, type_)
|
||||
func (q *Queries) ListDocumentsByType(ctx context.Context, arg ListDocumentsByTypeParams) ([]Document, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listDocumentsByType, arg.Type, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListDocumentsByTypeRow{}
|
||||
items := []Document{}
|
||||
for rows.Next() {
|
||||
var i ListDocumentsByTypeRow
|
||||
var i Document
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.Created,
|
||||
&i.UserID,
|
||||
&i.DocPageCount,
|
||||
&i.CmcReference,
|
||||
&i.PdfFilename,
|
||||
&i.PdfCreatedAt,
|
||||
&i.PdfCreatedByUserID,
|
||||
&i.CmcReference,
|
||||
&i.ShippingDetails,
|
||||
&i.Revision,
|
||||
&i.BillTo,
|
||||
&i.ShipTo,
|
||||
&i.EmailSentAt,
|
||||
&i.EmailSentByUserID,
|
||||
&i.UserFirstName,
|
||||
&i.UserLastName,
|
||||
&i.UserUsername,
|
||||
&i.PdfCreatorFirstName,
|
||||
&i.PdfCreatorLastName,
|
||||
&i.PdfCreatorUsername,
|
||||
&i.CustomerName,
|
||||
&i.EnquiryTitle,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -404,159 +365,12 @@ func (q *Queries) ListDocumentsByType(ctx context.Context, type_ DocumentsType)
|
|||
return items, nil
|
||||
}
|
||||
|
||||
const searchDocuments = `-- name: SearchDocuments :many
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.revision,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username,
|
||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
||||
e.title as enquiry_title
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
||||
LEFT JOIN customers ec ON e.customer_id = ec.id
|
||||
LEFT JOIN invoices i ON d.type = 'invoice' AND d.cmc_reference = i.title
|
||||
LEFT JOIN customers ic ON i.customer_id = ic.id
|
||||
WHERE (
|
||||
d.pdf_filename LIKE ? OR
|
||||
d.cmc_reference LIKE ? OR
|
||||
COALESCE(ec.name, ic.name) LIKE ? OR
|
||||
e.title LIKE ? OR
|
||||
u.username LIKE ?
|
||||
)
|
||||
ORDER BY d.id DESC
|
||||
LIMIT 1000
|
||||
`
|
||||
|
||||
type SearchDocumentsParams struct {
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type SearchDocumentsRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Type DocumentsType `json:"type"`
|
||||
Created time.Time `json:"created"`
|
||||
UserID int32 `json:"user_id"`
|
||||
DocPageCount int32 `json:"doc_page_count"`
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
||||
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
||||
CmcReference string `json:"cmc_reference"`
|
||||
Revision int32 `json:"revision"`
|
||||
EmailSentAt time.Time `json:"email_sent_at"`
|
||||
EmailSentByUserID int32 `json:"email_sent_by_user_id"`
|
||||
UserFirstName sql.NullString `json:"user_first_name"`
|
||||
UserLastName sql.NullString `json:"user_last_name"`
|
||||
UserUsername sql.NullString `json:"user_username"`
|
||||
PdfCreatorFirstName sql.NullString `json:"pdf_creator_first_name"`
|
||||
PdfCreatorLastName sql.NullString `json:"pdf_creator_last_name"`
|
||||
PdfCreatorUsername sql.NullString `json:"pdf_creator_username"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
EnquiryTitle sql.NullString `json:"enquiry_title"`
|
||||
}
|
||||
|
||||
func (q *Queries) SearchDocuments(ctx context.Context, arg SearchDocumentsParams) ([]SearchDocumentsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, searchDocuments,
|
||||
arg.PdfFilename,
|
||||
arg.CmcReference,
|
||||
arg.Name,
|
||||
arg.Title,
|
||||
arg.Username,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SearchDocumentsRow{}
|
||||
for rows.Next() {
|
||||
var i SearchDocumentsRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Type,
|
||||
&i.Created,
|
||||
&i.UserID,
|
||||
&i.DocPageCount,
|
||||
&i.PdfFilename,
|
||||
&i.PdfCreatedAt,
|
||||
&i.PdfCreatedByUserID,
|
||||
&i.CmcReference,
|
||||
&i.Revision,
|
||||
&i.EmailSentAt,
|
||||
&i.EmailSentByUserID,
|
||||
&i.UserFirstName,
|
||||
&i.UserLastName,
|
||||
&i.UserUsername,
|
||||
&i.PdfCreatorFirstName,
|
||||
&i.PdfCreatorLastName,
|
||||
&i.PdfCreatorUsername,
|
||||
&i.CustomerName,
|
||||
&i.EnquiryTitle,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const unarchiveDocument = `-- name: UnarchiveDocument :exec
|
||||
SELECT 1 WHERE ? = ?
|
||||
`
|
||||
|
||||
type UnarchiveDocumentParams struct {
|
||||
Column1 interface{} `json:"column_1"`
|
||||
Column2 interface{} `json:"column_2"`
|
||||
}
|
||||
|
||||
// Note: Unarchiving not supported as documents table doesn't have an archived column
|
||||
// This is a no-op for compatibility
|
||||
func (q *Queries) UnarchiveDocument(ctx context.Context, arg UnarchiveDocumentParams) error {
|
||||
_, err := q.db.ExecContext(ctx, unarchiveDocument, arg.Column1, arg.Column2)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateDocument = `-- name: UpdateDocument :exec
|
||||
UPDATE documents
|
||||
SET
|
||||
type = ?,
|
||||
user_id = ?,
|
||||
doc_page_count = ?,
|
||||
cmc_reference = ?,
|
||||
pdf_filename = ?,
|
||||
pdf_created_at = ?,
|
||||
pdf_created_by_user_id = ?,
|
||||
shipping_details = ?,
|
||||
revision = ?,
|
||||
bill_to = ?,
|
||||
ship_to = ?,
|
||||
email_sent_at = ?,
|
||||
email_sent_by_user_id = ?
|
||||
UPDATE documents SET
|
||||
type = ?, user_id = ?, doc_page_count = ?, cmc_reference = ?,
|
||||
pdf_filename = ?, pdf_created_at = ?, pdf_created_by_user_id = ?,
|
||||
shipping_details = ?, revision = ?, bill_to = ?, ship_to = ?,
|
||||
email_sent_at = ?, email_sent_by_user_id = ?
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
|
|
@ -596,29 +410,3 @@ func (q *Queries) UpdateDocument(ctx context.Context, arg UpdateDocumentParams)
|
|||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateDocumentPDFInfo = `-- name: UpdateDocumentPDFInfo :exec
|
||||
UPDATE documents
|
||||
SET
|
||||
pdf_filename = ?,
|
||||
pdf_created_at = ?,
|
||||
pdf_created_by_user_id = ?
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
type UpdateDocumentPDFInfoParams struct {
|
||||
PdfFilename string `json:"pdf_filename"`
|
||||
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
||||
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateDocumentPDFInfo(ctx context.Context, arg UpdateDocumentPDFInfoParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateDocumentPDFInfo,
|
||||
arg.PdfFilename,
|
||||
arg.PdfCreatedAt,
|
||||
arg.PdfCreatedByUserID,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,37 @@ func (q *Queries) GetPurchaseOrder(ctx context.Context, id int32) (PurchaseOrder
|
|||
return i, err
|
||||
}
|
||||
|
||||
const getPurchaseOrderByDocumentID = `-- name: GetPurchaseOrderByDocumentID :one
|
||||
SELECT id, issue_date, dispatch_date, date_arrived, title, principle_id, principle_reference, document_id, currency_id, ordered_from, description, dispatch_by, deliver_to, shipping_instructions, jobs_text, freight_forwarder_text, parent_purchase_order_id FROM purchase_orders
|
||||
WHERE document_id = ?
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetPurchaseOrderByDocumentID(ctx context.Context, documentID int32) (PurchaseOrder, error) {
|
||||
row := q.db.QueryRowContext(ctx, getPurchaseOrderByDocumentID, documentID)
|
||||
var i PurchaseOrder
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.IssueDate,
|
||||
&i.DispatchDate,
|
||||
&i.DateArrived,
|
||||
&i.Title,
|
||||
&i.PrincipleID,
|
||||
&i.PrincipleReference,
|
||||
&i.DocumentID,
|
||||
&i.CurrencyID,
|
||||
&i.OrderedFrom,
|
||||
&i.Description,
|
||||
&i.DispatchBy,
|
||||
&i.DeliverTo,
|
||||
&i.ShippingInstructions,
|
||||
&i.JobsText,
|
||||
&i.FreightForwarderText,
|
||||
&i.ParentPurchaseOrderID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getPurchaseOrderRevisions = `-- name: GetPurchaseOrderRevisions :many
|
||||
SELECT id, issue_date, dispatch_date, date_arrived, title, principle_id, principle_reference, document_id, currency_id, ordered_from, description, dispatch_by, deliver_to, shipping_instructions, jobs_text, freight_forwarder_text, parent_purchase_order_id FROM purchase_orders
|
||||
WHERE parent_purchase_order_id = ?
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ import (
|
|||
)
|
||||
|
||||
type Querier interface {
|
||||
ArchiveDocument(ctx context.Context, id int32) error
|
||||
ArchiveEnquiry(ctx context.Context, id int32) error
|
||||
ArchiveUser(ctx context.Context, id int32) error
|
||||
CountDocuments(ctx context.Context) (int64, error)
|
||||
CountDocumentsByType(ctx context.Context, type_ DocumentsType) (int64, error)
|
||||
CountEnquiries(ctx context.Context) (int64, error)
|
||||
CountEnquiriesByPrinciple(ctx context.Context, principleCode int32) (int64, error)
|
||||
CountEnquiriesByPrincipleAndState(ctx context.Context, arg CountEnquiriesByPrincipleAndStateParams) (int64, error)
|
||||
|
|
@ -36,6 +37,7 @@ type Querier interface {
|
|||
DeleteBox(ctx context.Context, id int32) error
|
||||
DeleteCountry(ctx context.Context, id int32) error
|
||||
DeleteCustomer(ctx context.Context, id int32) error
|
||||
DeleteDocument(ctx context.Context, id int32) error
|
||||
DeleteLineItem(ctx context.Context, id int32) error
|
||||
DeleteProduct(ctx context.Context, id int32) error
|
||||
DeletePurchaseOrder(ctx context.Context, id int32) error
|
||||
|
|
@ -53,7 +55,8 @@ type Querier interface {
|
|||
GetCustomer(ctx context.Context, id int32) (Customer, error)
|
||||
GetCustomerAddresses(ctx context.Context, customerID int32) ([]GetCustomerAddressesRow, error)
|
||||
GetCustomerByABN(ctx context.Context, abn sql.NullString) (Customer, error)
|
||||
GetDocumentByID(ctx context.Context, id int32) (GetDocumentByIDRow, error)
|
||||
GetDocument(ctx context.Context, id int32) (Document, error)
|
||||
GetDocumentWithUser(ctx context.Context, id int32) (GetDocumentWithUserRow, error)
|
||||
GetEnquiriesByCustomer(ctx context.Context, arg GetEnquiriesByCustomerParams) ([]GetEnquiriesByCustomerRow, error)
|
||||
GetEnquiriesByUser(ctx context.Context, arg GetEnquiriesByUserParams) ([]GetEnquiriesByUserRow, error)
|
||||
GetEnquiry(ctx context.Context, id int32) (GetEnquiryRow, error)
|
||||
|
|
@ -67,9 +70,10 @@ type Querier interface {
|
|||
GetProductByItemCode(ctx context.Context, itemCode string) (Product, error)
|
||||
GetProductsByCategory(ctx context.Context, arg GetProductsByCategoryParams) ([]Product, error)
|
||||
GetPurchaseOrder(ctx context.Context, id int32) (PurchaseOrder, error)
|
||||
GetPurchaseOrderByDocumentID(ctx context.Context, id int32) (GetPurchaseOrderByDocumentIDRow, error)
|
||||
GetPurchaseOrderByDocumentID(ctx context.Context, documentID int32) (PurchaseOrder, error)
|
||||
GetPurchaseOrderRevisions(ctx context.Context, parentPurchaseOrderID int32) ([]PurchaseOrder, error)
|
||||
GetPurchaseOrdersByPrinciple(ctx context.Context, arg GetPurchaseOrdersByPrincipleParams) ([]PurchaseOrder, error)
|
||||
GetRecentDocuments(ctx context.Context, limit int32) ([]GetRecentDocumentsRow, error)
|
||||
GetState(ctx context.Context, id int32) (State, error)
|
||||
GetStatus(ctx context.Context, id int32) (Status, error)
|
||||
GetUser(ctx context.Context, id int32) (GetUserRow, error)
|
||||
|
|
@ -84,8 +88,8 @@ type Querier interface {
|
|||
ListBoxesByShipment(ctx context.Context, shipmentID int32) ([]Box, error)
|
||||
ListCountries(ctx context.Context, arg ListCountriesParams) ([]Country, error)
|
||||
ListCustomers(ctx context.Context, arg ListCustomersParams) ([]Customer, error)
|
||||
ListDocuments(ctx context.Context) ([]ListDocumentsRow, error)
|
||||
ListDocumentsByType(ctx context.Context, type_ DocumentsType) ([]ListDocumentsByTypeRow, error)
|
||||
ListDocuments(ctx context.Context, arg ListDocumentsParams) ([]Document, error)
|
||||
ListDocumentsByType(ctx context.Context, arg ListDocumentsByTypeParams) ([]Document, error)
|
||||
ListEnquiries(ctx context.Context, arg ListEnquiriesParams) ([]ListEnquiriesRow, error)
|
||||
ListLineItems(ctx context.Context, arg ListLineItemsParams) ([]LineItem, error)
|
||||
ListLineItemsByDocument(ctx context.Context, documentID int32) ([]LineItem, error)
|
||||
|
|
@ -97,13 +101,9 @@ type Querier interface {
|
|||
MarkEnquirySubmitted(ctx context.Context, arg MarkEnquirySubmittedParams) error
|
||||
SearchCountriesByName(ctx context.Context, concat interface{}) ([]Country, error)
|
||||
SearchCustomersByName(ctx context.Context, arg SearchCustomersByNameParams) ([]Customer, error)
|
||||
SearchDocuments(ctx context.Context, arg SearchDocumentsParams) ([]SearchDocumentsRow, error)
|
||||
SearchEnquiries(ctx context.Context, arg SearchEnquiriesParams) ([]SearchEnquiriesRow, error)
|
||||
SearchProductsByTitle(ctx context.Context, arg SearchProductsByTitleParams) ([]Product, error)
|
||||
SearchPurchaseOrdersByTitle(ctx context.Context, arg SearchPurchaseOrdersByTitleParams) ([]PurchaseOrder, error)
|
||||
// Note: Unarchiving not supported as documents table doesn't have an archived column
|
||||
// This is a no-op for compatibility
|
||||
UnarchiveDocument(ctx context.Context, arg UnarchiveDocumentParams) error
|
||||
UnarchiveEnquiry(ctx context.Context, id int32) error
|
||||
UnarchiveUser(ctx context.Context, id int32) error
|
||||
UpdateAddress(ctx context.Context, arg UpdateAddressParams) error
|
||||
|
|
@ -112,7 +112,6 @@ type Querier interface {
|
|||
UpdateCountry(ctx context.Context, arg UpdateCountryParams) error
|
||||
UpdateCustomer(ctx context.Context, arg UpdateCustomerParams) error
|
||||
UpdateDocument(ctx context.Context, arg UpdateDocumentParams) error
|
||||
UpdateDocumentPDFInfo(ctx context.Context, arg UpdateDocumentPDFInfoParams) error
|
||||
UpdateEnquiry(ctx context.Context, arg UpdateEnquiryParams) error
|
||||
UpdateEnquiryStatus(ctx context.Context, arg UpdateEnquiryStatusParams) error
|
||||
UpdateLineItem(ctx context.Context, arg UpdateLineItemParams) error
|
||||
|
|
|
|||
|
|
@ -31,14 +31,35 @@ func (h *DocumentHandler) List(w http.ResponseWriter, r *http.Request) {
|
|||
// Check for type filter
|
||||
docType := r.URL.Query().Get("type")
|
||||
|
||||
// Get pagination parameters
|
||||
limit := int32(20)
|
||||
offset := int32(0)
|
||||
if l := r.URL.Query().Get("limit"); l != "" {
|
||||
if val, err := strconv.Atoi(l); err == nil && val > 0 {
|
||||
limit = int32(val)
|
||||
}
|
||||
}
|
||||
if o := r.URL.Query().Get("offset"); o != "" {
|
||||
if val, err := strconv.Atoi(o); err == nil && val >= 0 {
|
||||
offset = int32(val)
|
||||
}
|
||||
}
|
||||
|
||||
var documents interface{}
|
||||
var err error
|
||||
|
||||
if docType != "" {
|
||||
// Convert string to DocumentsType enum
|
||||
documents, err = h.queries.ListDocumentsByType(ctx, db.DocumentsType(docType))
|
||||
documents, err = h.queries.ListDocumentsByType(ctx, db.ListDocumentsByTypeParams{
|
||||
Type: db.DocumentsType(docType),
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
})
|
||||
} else {
|
||||
documents, err = h.queries.ListDocuments(ctx)
|
||||
documents, err = h.queries.ListDocuments(ctx, db.ListDocumentsParams{
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -85,7 +106,7 @@ func (h *DocumentHandler) Get(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
ctx := context.Background()
|
||||
document, err := h.queries.GetDocumentByID(ctx, int32(id))
|
||||
document, err := h.queries.GetDocument(ctx, int32(id))
|
||||
if err != nil {
|
||||
log.Printf("Error fetching document %d: %v", id, err)
|
||||
http.Error(w, "Document not found", http.StatusNotFound)
|
||||
|
|
@ -272,82 +293,20 @@ func (h *DocumentHandler) Update(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Archive handles PUT /api/documents/{id}/archive
|
||||
func (h *DocumentHandler) Archive(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr := vars["id"]
|
||||
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid document ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err = h.queries.ArchiveDocument(ctx, int32(id))
|
||||
if err != nil {
|
||||
log.Printf("Error archiving document %d: %v", id, err)
|
||||
http.Error(w, "Failed to archive document", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "Document archived successfully",
|
||||
})
|
||||
// TODO: Implement archive functionality when query is added
|
||||
http.Error(w, "Archive functionality not yet implemented", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
// Unarchive handles PUT /api/documents/{id}/unarchive
|
||||
func (h *DocumentHandler) Unarchive(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr := vars["id"]
|
||||
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid document ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err = h.queries.UnarchiveDocument(ctx, db.UnarchiveDocumentParams{
|
||||
Column1: int32(id),
|
||||
Column2: int32(id),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error unarchiving document %d: %v", id, err)
|
||||
http.Error(w, "Failed to unarchive document", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "Document unarchived successfully",
|
||||
})
|
||||
// TODO: Implement unarchive functionality when query is added
|
||||
http.Error(w, "Unarchive functionality not yet implemented", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
// Search handles GET /api/documents/search?q=query
|
||||
func (h *DocumentHandler) Search(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query().Get("q")
|
||||
if query == "" {
|
||||
http.Error(w, "Search query is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
searchPattern := "%" + query + "%"
|
||||
documents, err := h.queries.SearchDocuments(ctx, db.SearchDocumentsParams{
|
||||
PdfFilename: searchPattern,
|
||||
CmcReference: searchPattern,
|
||||
Name: searchPattern,
|
||||
Title: searchPattern,
|
||||
Username: searchPattern,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error searching documents: %v", err)
|
||||
http.Error(w, "Failed to search documents", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(documents)
|
||||
// TODO: Implement search functionality when query is added
|
||||
http.Error(w, "Search functionality not yet implemented", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
// GeneratePDF handles GET /documents/pdf/{id}
|
||||
|
|
@ -364,7 +323,7 @@ func (h *DocumentHandler) GeneratePDF(w http.ResponseWriter, r *http.Request) {
|
|||
ctx := context.Background()
|
||||
|
||||
// Get document
|
||||
document, err := h.queries.GetDocumentByID(ctx, int32(id))
|
||||
document, err := h.queries.GetDocument(ctx, int32(id))
|
||||
if err != nil {
|
||||
log.Printf("Error fetching document %d: %v", id, err)
|
||||
http.Error(w, "Document not found", http.StatusNotFound)
|
||||
|
|
@ -488,18 +447,9 @@ func (h *DocumentHandler) GeneratePDF(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Update document with PDF filename and timestamp
|
||||
now := time.Now()
|
||||
err = h.queries.UpdateDocumentPDFInfo(ctx, db.UpdateDocumentPDFInfoParams{
|
||||
PdfFilename: filename,
|
||||
PdfCreatedAt: now,
|
||||
PdfCreatedByUserID: 1, // TODO: Get current user ID
|
||||
ID: int32(id),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error updating document PDF info: %v", err)
|
||||
// Don't fail the request, PDF was generated successfully
|
||||
}
|
||||
// TODO: Update document with PDF filename and timestamp
|
||||
// This would require a specific query to update just PDF info
|
||||
log.Printf("PDF generated successfully: %s", filename)
|
||||
|
||||
// Return success response with redirect to document view
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
|
@ -516,3 +466,100 @@ func (h *DocumentHandler) GeneratePDF(w http.ResponseWriter, r *http.Request) {
|
|||
</html>
|
||||
`, id, id)
|
||||
}
|
||||
|
||||
// GetRecentActivity returns recent documents as HTML for the dashboard
|
||||
func (h *DocumentHandler) GetRecentActivity(w http.ResponseWriter, r *http.Request) {
|
||||
// Get the last 10 documents
|
||||
documents, err := h.queries.GetRecentDocuments(r.Context(), 10)
|
||||
if err != nil {
|
||||
log.Printf("Error fetching recent activity: %v", err)
|
||||
http.Error(w, "Failed to fetch recent activity", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Format the response as HTML
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
||||
if len(documents) == 0 {
|
||||
fmt.Fprintf(w, `<div class="has-text-centered has-text-grey">
|
||||
<p>No recent activity</p>
|
||||
</div>`)
|
||||
return
|
||||
}
|
||||
|
||||
// Build HTML table
|
||||
fmt.Fprintf(w, `<table class="table is-fullwidth is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Document</th>
|
||||
<th>Reference</th>
|
||||
<th>Created By</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>`)
|
||||
|
||||
for _, doc := range documents {
|
||||
// Format the document type badge
|
||||
var typeClass string
|
||||
switch doc.Type {
|
||||
case "quote":
|
||||
typeClass = "is-info"
|
||||
case "invoice":
|
||||
typeClass = "is-success"
|
||||
case "purchaseOrder":
|
||||
typeClass = "is-warning"
|
||||
case "orderAck":
|
||||
typeClass = "is-primary"
|
||||
case "packingList":
|
||||
typeClass = "is-link"
|
||||
default:
|
||||
typeClass = "is-light"
|
||||
}
|
||||
|
||||
// Format the date
|
||||
createdDate := doc.Created.Format("Jan 2, 2006 3:04 PM")
|
||||
|
||||
// Handle null username
|
||||
createdBy := "Unknown"
|
||||
if doc.CreatedByUsername.Valid {
|
||||
createdBy = doc.CreatedByUsername.String
|
||||
}
|
||||
|
||||
// Add revision indicator if applicable
|
||||
revisionText := ""
|
||||
if doc.Revision > 0 {
|
||||
revisionText = fmt.Sprintf(" <span class=\"tag is-light\">Rev %d</span>", doc.Revision)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `<tr>
|
||||
<td>
|
||||
<span class="tag %s">%s</span>
|
||||
</td>
|
||||
<td>%s%s</td>
|
||||
<td>%s</td>
|
||||
<td><small>%s</small></td>
|
||||
<td>
|
||||
<a href="/documents/%d" class="button is-small is-outlined">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-eye"></i>
|
||||
</span>
|
||||
<span>View</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>`, typeClass, doc.DisplayName, doc.CmcReference, revisionText, createdBy, createdDate, doc.ID)
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `</tbody></table>`)
|
||||
|
||||
// Add a link to view all documents
|
||||
fmt.Fprintf(w, `<div class="has-text-centered mt-4">
|
||||
<a href="/documents" class="button is-link is-outlined">
|
||||
<span>View All Documents</span>
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
</div>`)
|
||||
}
|
||||
|
|
@ -615,13 +615,23 @@ func (h *PageHandler) DocumentsIndex(w http.ResponseWriter, r *http.Request) {
|
|||
// Get document type filter
|
||||
docType := r.URL.Query().Get("type")
|
||||
|
||||
limit := 20
|
||||
offset := (page - 1) * limit
|
||||
|
||||
var documents interface{}
|
||||
var err error
|
||||
|
||||
if docType != "" {
|
||||
documents, err = h.queries.ListDocumentsByType(r.Context(), db.DocumentsType(docType))
|
||||
documents, err = h.queries.ListDocumentsByType(r.Context(), db.ListDocumentsByTypeParams{
|
||||
Type: db.DocumentsType(docType),
|
||||
Limit: int32(limit + 1),
|
||||
Offset: int32(offset),
|
||||
})
|
||||
} else {
|
||||
documents, err = h.queries.ListDocuments(r.Context())
|
||||
documents, err = h.queries.ListDocuments(r.Context(), db.ListDocumentsParams{
|
||||
Limit: int32(limit + 1),
|
||||
Offset: int32(offset),
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -664,7 +674,7 @@ func (h *PageHandler) DocumentsShow(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
document, err := h.queries.GetDocumentByID(r.Context(), int32(id))
|
||||
document, err := h.queries.GetDocumentWithUser(r.Context(), int32(id))
|
||||
if err != nil {
|
||||
log.Printf("Error fetching document %d: %v", id, err)
|
||||
http.Error(w, "Document not found", http.StatusNotFound)
|
||||
|
|
@ -681,32 +691,23 @@ func (h *PageHandler) DocumentsShow(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (h *PageHandler) DocumentsSearch(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query().Get("search")
|
||||
// query := r.URL.Query().Get("search") // TODO: Use when search is implemented
|
||||
|
||||
var documents interface{}
|
||||
var err error
|
||||
|
||||
if query == "" {
|
||||
// If no search query, return regular list
|
||||
documents, err = h.queries.ListDocuments(r.Context())
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
searchPattern := "%" + query + "%"
|
||||
documents, err = h.queries.SearchDocuments(r.Context(), db.SearchDocumentsParams{
|
||||
PdfFilename: searchPattern,
|
||||
CmcReference: searchPattern,
|
||||
Name: searchPattern,
|
||||
Title: searchPattern,
|
||||
Username: searchPattern,
|
||||
// For now, just return all documents until search is implemented
|
||||
limit := 20
|
||||
offset := 0
|
||||
|
||||
documents, err = h.queries.ListDocuments(r.Context(), db.ListDocumentsParams{
|
||||
Limit: int32(limit),
|
||||
Offset: int32(offset),
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Documents": documents,
|
||||
|
|
@ -726,7 +727,7 @@ func (h *PageHandler) DocumentsView(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
document, err := h.queries.GetDocumentByID(r.Context(), int32(id))
|
||||
document, err := h.queries.GetDocumentWithUser(r.Context(), int32(id))
|
||||
if err != nil {
|
||||
http.Error(w, "Document not found", http.StatusNotFound)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ func (g *Generator) Page1Header() {
|
|||
g.pdf.SetTextColor(0, 0, 152)
|
||||
|
||||
// Add logo if available (assuming logo is in static directory)
|
||||
// logoPath := filepath.Join("static", "images", "cmclogosmall.png")
|
||||
logoPath := filepath.Join("static", "images", "cmclogosmall.png")
|
||||
// Try to add logo, but don't fail if it doesn't exist or isn't a proper image
|
||||
// g.pdf.ImageOptions(logoPath, 10, 10, 0, 28, false, gofpdf.ImageOptions{ImageType: "PNG"}, 0, "http://www.cmctechnologies.com.au")
|
||||
g.pdf.ImageOptions(logoPath, 10, 10, 0, 28, false, gofpdf.ImageOptions{ImageType: "PNG"}, 0, "http://www.cmctechnologies.com.au")
|
||||
|
||||
// Company name
|
||||
g.pdf.SetFont("Helvetica", "B", 30)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// QuotePDFData contains all data needed to generate a quote PDF
|
||||
type QuotePDFData struct {
|
||||
Document *db.GetDocumentByIDRow
|
||||
Document *db.Document
|
||||
Quote interface{} // Quote specific data
|
||||
Enquiry *db.Enquiry
|
||||
Customer *db.Customer
|
||||
|
|
@ -32,25 +32,26 @@ func GenerateQuotePDF(data *QuotePDFData, outputDir string) (string, error) {
|
|||
gen.Page1Header()
|
||||
|
||||
// Extract data for details box
|
||||
companyName := data.Document.CustomerName
|
||||
companyName := "" // TODO: Get from customer data
|
||||
if data.Customer != nil {
|
||||
companyName = data.Customer.Name
|
||||
}
|
||||
emailTo := "" // TODO: Get from contact
|
||||
attention := "" // TODO: Get from contact
|
||||
fromName := fmt.Sprintf("%s %s", data.User.FirstName, data.User.LastName)
|
||||
fromEmail := data.User.Email
|
||||
enquiryNumber := ""
|
||||
if data.Document.EnquiryTitle.Valid {
|
||||
enquiryNumber = data.Document.EnquiryTitle.String
|
||||
}
|
||||
|
||||
// Use CMC reference as the quote number
|
||||
quoteNumber := data.Document.CmcReference
|
||||
if data.Document.Revision > 0 {
|
||||
enquiryNumber = fmt.Sprintf("%s.%d", enquiryNumber, data.Document.Revision)
|
||||
quoteNumber = fmt.Sprintf("%s.%d", quoteNumber, data.Document.Revision)
|
||||
}
|
||||
|
||||
yourReference := fmt.Sprintf("Enquiry on %s", data.Document.Created.Format("2 Jan 2006"))
|
||||
issueDate := time.Now().Format("2 January 2006")
|
||||
issueDate := data.Document.Created.Format("2 January 2006")
|
||||
|
||||
// Add details box
|
||||
gen.DetailsBox("QUOTE", companyName, emailTo, attention, fromName, fromEmail, enquiryNumber, yourReference, issueDate)
|
||||
gen.DetailsBox("QUOTE", companyName, emailTo, attention, fromName, fromEmail, quoteNumber, yourReference, issueDate)
|
||||
|
||||
// Add page content if any
|
||||
// TODO: Add document pages content
|
||||
|
|
@ -101,11 +102,11 @@ func GenerateQuotePDF(data *QuotePDFData, outputDir string) (string, error) {
|
|||
// TODO: Add terms and conditions page
|
||||
|
||||
// Generate filename
|
||||
filename := enquiryNumber
|
||||
filename := quoteNumber
|
||||
if data.Document.Revision > 0 {
|
||||
filename = fmt.Sprintf("%s_%d.pdf", enquiryNumber, data.Document.Revision)
|
||||
filename = fmt.Sprintf("%s_%d.pdf", quoteNumber, data.Document.Revision)
|
||||
} else {
|
||||
filename = fmt.Sprintf("%s.pdf", enquiryNumber)
|
||||
filename = fmt.Sprintf("%s.pdf", quoteNumber)
|
||||
}
|
||||
|
||||
// Save PDF
|
||||
|
|
@ -213,8 +214,8 @@ func GenerateInvoicePDF(data *InvoicePDFData, outputDir string) (string, error)
|
|||
|
||||
// PurchaseOrderPDFData contains all data needed to generate a purchase order PDF
|
||||
type PurchaseOrderPDFData struct {
|
||||
Document *db.GetDocumentByIDRow
|
||||
PurchaseOrder *db.GetPurchaseOrderByDocumentIDRow
|
||||
Document *db.Document
|
||||
PurchaseOrder *db.PurchaseOrder
|
||||
Principle *db.Principle
|
||||
LineItems []db.GetLineItemsTableRow
|
||||
Currency interface{} // Currency data
|
||||
|
|
|
|||
BIN
go-app/server
BIN
go-app/server
Binary file not shown.
|
|
@ -1,201 +1,85 @@
|
|||
-- name: GetDocument :one
|
||||
SELECT * FROM documents WHERE id = ?;
|
||||
|
||||
-- name: ListDocuments :many
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.revision,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
ORDER BY d.id DESC
|
||||
LIMIT 1000;
|
||||
SELECT * FROM documents ORDER BY created DESC LIMIT ? OFFSET ?;
|
||||
|
||||
-- name: ListDocumentsByType :many
|
||||
SELECT * FROM documents WHERE type = ? ORDER BY created DESC LIMIT ? OFFSET ?;
|
||||
|
||||
-- name: CreateDocument :execresult
|
||||
INSERT INTO documents (
|
||||
type, created, user_id, doc_page_count, cmc_reference,
|
||||
pdf_filename, pdf_created_at, pdf_created_by_user_id,
|
||||
shipping_details, revision, bill_to, ship_to,
|
||||
email_sent_at, email_sent_by_user_id
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
|
||||
-- name: UpdateDocument :exec
|
||||
UPDATE documents SET
|
||||
type = ?, user_id = ?, doc_page_count = ?, cmc_reference = ?,
|
||||
pdf_filename = ?, pdf_created_at = ?, pdf_created_by_user_id = ?,
|
||||
shipping_details = ?, revision = ?, bill_to = ?, ship_to = ?,
|
||||
email_sent_at = ?, email_sent_by_user_id = ?
|
||||
WHERE id = ?;
|
||||
|
||||
-- name: DeleteDocument :exec
|
||||
DELETE FROM documents WHERE id = ?;
|
||||
|
||||
-- name: GetRecentDocuments :many
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.pdf_filename,
|
||||
d.revision,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username,
|
||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
||||
e.title as enquiry_title
|
||||
u.username as created_by_username,
|
||||
CASE
|
||||
WHEN d.type = 'quote' THEN CONCAT('Quote ', d.cmc_reference)
|
||||
WHEN d.type = 'invoice' THEN CONCAT('Invoice ', d.cmc_reference)
|
||||
WHEN d.type = 'purchaseOrder' THEN CONCAT('Purchase Order ', d.cmc_reference)
|
||||
WHEN d.type = 'orderAck' THEN CONCAT('Order Ack ', d.cmc_reference)
|
||||
WHEN d.type = 'packingList' THEN CONCAT('Packing List ', d.cmc_reference)
|
||||
ELSE CONCAT(d.type, ' ', d.cmc_reference)
|
||||
END as display_name
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
||||
LEFT JOIN customers ec ON e.customer_id = ec.id
|
||||
LEFT JOIN invoices i ON d.type = 'invoice' AND d.cmc_reference = i.title
|
||||
LEFT JOIN customers ic ON i.customer_id = ic.id
|
||||
WHERE d.type = ?
|
||||
ORDER BY d.id DESC
|
||||
LIMIT 1000;
|
||||
ORDER BY d.created DESC
|
||||
LIMIT ?;
|
||||
|
||||
-- name: GetDocumentByID :one
|
||||
-- name: CountDocuments :one
|
||||
SELECT COUNT(*) FROM documents;
|
||||
|
||||
-- name: CountDocumentsByType :one
|
||||
SELECT COUNT(*) FROM documents WHERE type = ?;
|
||||
|
||||
-- name: GetDocumentWithUser :one
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.cmc_reference,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.revision,
|
||||
d.shipping_details,
|
||||
d.revision,
|
||||
d.bill_to,
|
||||
d.ship_to,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.username as user_username,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username,
|
||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
||||
e.title as enquiry_title
|
||||
u.email as user_email,
|
||||
pu.username as pdf_creator_username,
|
||||
pu.first_name as pdf_creator_first_name,
|
||||
pu.last_name as pdf_creator_last_name,
|
||||
pu.email as pdf_creator_email
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
||||
LEFT JOIN customers ec ON e.customer_id = ec.id
|
||||
LEFT JOIN invoices i ON d.type = 'invoice' AND d.cmc_reference = i.title
|
||||
LEFT JOIN customers ic ON i.customer_id = ic.id
|
||||
LEFT JOIN users pu ON d.pdf_created_by_user_id = pu.id
|
||||
WHERE d.id = ?;
|
||||
|
||||
-- name: CreateDocument :execresult
|
||||
INSERT INTO documents (
|
||||
type,
|
||||
created,
|
||||
user_id,
|
||||
doc_page_count,
|
||||
cmc_reference,
|
||||
pdf_filename,
|
||||
pdf_created_at,
|
||||
pdf_created_by_user_id,
|
||||
shipping_details,
|
||||
revision,
|
||||
bill_to,
|
||||
ship_to,
|
||||
email_sent_at,
|
||||
email_sent_by_user_id
|
||||
) VALUES (
|
||||
?, NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
||||
);
|
||||
|
||||
-- name: UpdateDocument :exec
|
||||
UPDATE documents
|
||||
SET
|
||||
type = ?,
|
||||
user_id = ?,
|
||||
doc_page_count = ?,
|
||||
cmc_reference = ?,
|
||||
pdf_filename = ?,
|
||||
pdf_created_at = ?,
|
||||
pdf_created_by_user_id = ?,
|
||||
shipping_details = ?,
|
||||
revision = ?,
|
||||
bill_to = ?,
|
||||
ship_to = ?,
|
||||
email_sent_at = ?,
|
||||
email_sent_by_user_id = ?
|
||||
WHERE id = ?;
|
||||
|
||||
-- name: ArchiveDocument :exec
|
||||
DELETE FROM documents
|
||||
WHERE id = ?;
|
||||
|
||||
-- name: UnarchiveDocument :exec
|
||||
-- Note: Unarchiving not supported as documents table doesn't have an archived column
|
||||
-- This is a no-op for compatibility
|
||||
SELECT 1 WHERE ? = ?;
|
||||
|
||||
-- name: SearchDocuments :many
|
||||
SELECT
|
||||
d.id,
|
||||
d.type,
|
||||
d.created,
|
||||
d.user_id,
|
||||
d.doc_page_count,
|
||||
d.pdf_filename,
|
||||
d.pdf_created_at,
|
||||
d.pdf_created_by_user_id,
|
||||
d.cmc_reference,
|
||||
d.revision,
|
||||
d.email_sent_at,
|
||||
d.email_sent_by_user_id,
|
||||
u.first_name as user_first_name,
|
||||
u.last_name as user_last_name,
|
||||
u.username as user_username,
|
||||
pdf_creator.first_name as pdf_creator_first_name,
|
||||
pdf_creator.last_name as pdf_creator_last_name,
|
||||
pdf_creator.username as pdf_creator_username,
|
||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
||||
e.title as enquiry_title
|
||||
FROM documents d
|
||||
LEFT JOIN users u ON d.user_id = u.id
|
||||
LEFT JOIN users pdf_creator ON d.pdf_created_by_user_id = pdf_creator.id
|
||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
||||
LEFT JOIN customers ec ON e.customer_id = ec.id
|
||||
LEFT JOIN invoices i ON d.type = 'invoice' AND d.cmc_reference = i.title
|
||||
LEFT JOIN customers ic ON i.customer_id = ic.id
|
||||
WHERE (
|
||||
d.pdf_filename LIKE ? OR
|
||||
d.cmc_reference LIKE ? OR
|
||||
COALESCE(ec.name, ic.name) LIKE ? OR
|
||||
e.title LIKE ? OR
|
||||
u.username LIKE ?
|
||||
)
|
||||
ORDER BY d.id DESC
|
||||
LIMIT 1000;
|
||||
|
||||
-- name: UpdateDocumentPDFInfo :exec
|
||||
UPDATE documents
|
||||
SET
|
||||
pdf_filename = ?,
|
||||
pdf_created_at = ?,
|
||||
pdf_created_by_user_id = ?
|
||||
WHERE id = ?;
|
||||
|
||||
-- name: GetPurchaseOrderByDocumentID :one
|
||||
SELECT
|
||||
po.id,
|
||||
po.title,
|
||||
po.principle_id,
|
||||
po.principle_reference,
|
||||
po.issue_date,
|
||||
po.ordered_from,
|
||||
po.dispatch_by,
|
||||
po.deliver_to,
|
||||
po.shipping_instructions
|
||||
FROM purchase_orders po
|
||||
JOIN documents d ON d.cmc_reference = po.title
|
||||
WHERE d.id = ? AND d.type = 'purchaseOrder';
|
||||
|
|
@ -58,3 +58,8 @@ SELECT * FROM purchase_orders
|
|||
WHERE title LIKE CONCAT('%', ?, '%')
|
||||
ORDER BY issue_date DESC
|
||||
LIMIT ? OFFSET ?;
|
||||
|
||||
-- name: GetPurchaseOrderByDocumentID :one
|
||||
SELECT * FROM purchase_orders
|
||||
WHERE document_id = ?
|
||||
LIMIT 1;
|
||||
|
|
@ -109,7 +109,8 @@
|
|||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if or .Document.CustomerName .Document.EnquiryTitle.Valid}}
|
||||
{{/* TODO: Add customer and enquiry information when queries are available */}}
|
||||
{{if false}}
|
||||
<div class="box">
|
||||
<h3 class="title is-5">Related Information</h3>
|
||||
<table class="table is-fullwidth">
|
||||
|
|
|
|||
Loading…
Reference in a new issue