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"}`))
|
w.Write([]byte(`{"status":"ok"}`))
|
||||||
}).Methods("GET")
|
}).Methods("GET")
|
||||||
|
|
||||||
|
// Recent activity endpoint
|
||||||
|
r.HandleFunc("/api/recent-activity", documentHandler.GetRecentActivity).Methods("GET")
|
||||||
|
|
||||||
// Page routes
|
// Page routes
|
||||||
r.HandleFunc("/", pageHandler.Home).Methods("GET")
|
r.HandleFunc("/", pageHandler.Home).Methods("GET")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,39 +11,40 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const archiveDocument = `-- name: ArchiveDocument :exec
|
const countDocuments = `-- name: CountDocuments :one
|
||||||
DELETE FROM documents
|
SELECT COUNT(*) FROM documents
|
||||||
WHERE id = ?
|
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) ArchiveDocument(ctx context.Context, id int32) error {
|
func (q *Queries) CountDocuments(ctx context.Context) (int64, error) {
|
||||||
_, err := q.db.ExecContext(ctx, archiveDocument, id)
|
row := q.db.QueryRowContext(ctx, countDocuments)
|
||||||
return err
|
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
|
const createDocument = `-- name: CreateDocument :execresult
|
||||||
INSERT INTO documents (
|
INSERT INTO documents (
|
||||||
type,
|
type, created, user_id, doc_page_count, cmc_reference,
|
||||||
created,
|
pdf_filename, pdf_created_at, pdf_created_by_user_id,
|
||||||
user_id,
|
shipping_details, revision, bill_to, ship_to,
|
||||||
doc_page_count,
|
email_sent_at, email_sent_by_user_id
|
||||||
cmc_reference,
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
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 CreateDocumentParams struct {
|
type CreateDocumentParams struct {
|
||||||
Type DocumentsType `json:"type"`
|
Type DocumentsType `json:"type"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
UserID int32 `json:"user_id"`
|
UserID int32 `json:"user_id"`
|
||||||
DocPageCount int32 `json:"doc_page_count"`
|
DocPageCount int32 `json:"doc_page_count"`
|
||||||
CmcReference string `json:"cmc_reference"`
|
CmcReference string `json:"cmc_reference"`
|
||||||
|
|
@ -61,6 +62,7 @@ type CreateDocumentParams struct {
|
||||||
func (q *Queries) CreateDocument(ctx context.Context, arg CreateDocumentParams) (sql.Result, error) {
|
func (q *Queries) CreateDocument(ctx context.Context, arg CreateDocumentParams) (sql.Result, error) {
|
||||||
return q.db.ExecContext(ctx, createDocument,
|
return q.db.ExecContext(ctx, createDocument,
|
||||||
arg.Type,
|
arg.Type,
|
||||||
|
arg.Created,
|
||||||
arg.UserID,
|
arg.UserID,
|
||||||
arg.DocPageCount,
|
arg.DocPageCount,
|
||||||
arg.CmcReference,
|
arg.CmcReference,
|
||||||
|
|
@ -76,219 +78,230 @@ func (q *Queries) CreateDocument(ctx context.Context, arg CreateDocumentParams)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDocumentByID = `-- name: GetDocumentByID :one
|
const deleteDocument = `-- name: DeleteDocument :exec
|
||||||
SELECT
|
DELETE FROM documents WHERE id = ?
|
||||||
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 = ?
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetDocumentByIDRow struct {
|
func (q *Queries) DeleteDocument(ctx context.Context, id int32) error {
|
||||||
ID int32 `json:"id"`
|
_, err := q.db.ExecContext(ctx, deleteDocument, id)
|
||||||
Type DocumentsType `json:"type"`
|
return err
|
||||||
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) GetDocumentByID(ctx context.Context, id int32) (GetDocumentByIDRow, error) {
|
const getDocument = `-- name: GetDocument :one
|
||||||
row := q.db.QueryRowContext(ctx, getDocumentByID, id)
|
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 = ?
|
||||||
var i GetDocumentByIDRow
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetDocument(ctx context.Context, id int32) (Document, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, getDocument, id)
|
||||||
|
var i Document
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.Type,
|
&i.Type,
|
||||||
&i.Created,
|
&i.Created,
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.DocPageCount,
|
&i.DocPageCount,
|
||||||
|
&i.CmcReference,
|
||||||
&i.PdfFilename,
|
&i.PdfFilename,
|
||||||
&i.PdfCreatedAt,
|
&i.PdfCreatedAt,
|
||||||
&i.PdfCreatedByUserID,
|
&i.PdfCreatedByUserID,
|
||||||
&i.CmcReference,
|
|
||||||
&i.Revision,
|
|
||||||
&i.ShippingDetails,
|
&i.ShippingDetails,
|
||||||
|
&i.Revision,
|
||||||
&i.BillTo,
|
&i.BillTo,
|
||||||
&i.ShipTo,
|
&i.ShipTo,
|
||||||
&i.EmailSentAt,
|
&i.EmailSentAt,
|
||||||
&i.EmailSentByUserID,
|
&i.EmailSentByUserID,
|
||||||
&i.UserFirstName,
|
|
||||||
&i.UserLastName,
|
|
||||||
&i.UserUsername,
|
|
||||||
&i.PdfCreatorFirstName,
|
|
||||||
&i.PdfCreatorLastName,
|
|
||||||
&i.PdfCreatorUsername,
|
|
||||||
&i.CustomerName,
|
|
||||||
&i.EnquiryTitle,
|
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPurchaseOrderByDocumentID = `-- name: GetPurchaseOrderByDocumentID :one
|
const getDocumentWithUser = `-- name: GetDocumentWithUser :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
|
|
||||||
SELECT
|
SELECT
|
||||||
d.id,
|
d.id,
|
||||||
d.type,
|
d.type,
|
||||||
d.created,
|
d.created,
|
||||||
d.user_id,
|
d.user_id,
|
||||||
d.doc_page_count,
|
d.doc_page_count,
|
||||||
|
d.cmc_reference,
|
||||||
d.pdf_filename,
|
d.pdf_filename,
|
||||||
d.pdf_created_at,
|
d.pdf_created_at,
|
||||||
d.pdf_created_by_user_id,
|
d.pdf_created_by_user_id,
|
||||||
d.cmc_reference,
|
d.shipping_details,
|
||||||
d.revision,
|
d.revision,
|
||||||
|
d.bill_to,
|
||||||
|
d.ship_to,
|
||||||
d.email_sent_at,
|
d.email_sent_at,
|
||||||
d.email_sent_by_user_id,
|
d.email_sent_by_user_id,
|
||||||
|
u.username as user_username,
|
||||||
u.first_name as user_first_name,
|
u.first_name as user_first_name,
|
||||||
u.last_name as user_last_name,
|
u.last_name as user_last_name,
|
||||||
u.username as user_username,
|
u.email as user_email,
|
||||||
pdf_creator.first_name as pdf_creator_first_name,
|
pu.username as pdf_creator_username,
|
||||||
pdf_creator.last_name as pdf_creator_last_name,
|
pu.first_name as pdf_creator_first_name,
|
||||||
pdf_creator.username as pdf_creator_username
|
pu.last_name as pdf_creator_last_name,
|
||||||
|
pu.email as pdf_creator_email
|
||||||
FROM documents d
|
FROM documents d
|
||||||
LEFT JOIN users u ON d.user_id = u.id
|
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 users pu ON d.pdf_created_by_user_id = pu.id
|
||||||
ORDER BY d.id DESC
|
WHERE d.id = ?
|
||||||
LIMIT 1000
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type ListDocumentsRow struct {
|
type GetDocumentWithUserRow struct {
|
||||||
ID int32 `json:"id"`
|
ID int32 `json:"id"`
|
||||||
Type DocumentsType `json:"type"`
|
Type DocumentsType `json:"type"`
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
UserID int32 `json:"user_id"`
|
UserID int32 `json:"user_id"`
|
||||||
DocPageCount int32 `json:"doc_page_count"`
|
DocPageCount int32 `json:"doc_page_count"`
|
||||||
|
CmcReference string `json:"cmc_reference"`
|
||||||
PdfFilename string `json:"pdf_filename"`
|
PdfFilename string `json:"pdf_filename"`
|
||||||
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
PdfCreatedAt time.Time `json:"pdf_created_at"`
|
||||||
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
PdfCreatedByUserID int32 `json:"pdf_created_by_user_id"`
|
||||||
CmcReference string `json:"cmc_reference"`
|
ShippingDetails sql.NullString `json:"shipping_details"`
|
||||||
Revision int32 `json:"revision"`
|
Revision int32 `json:"revision"`
|
||||||
|
BillTo sql.NullString `json:"bill_to"`
|
||||||
|
ShipTo sql.NullString `json:"ship_to"`
|
||||||
EmailSentAt time.Time `json:"email_sent_at"`
|
EmailSentAt time.Time `json:"email_sent_at"`
|
||||||
EmailSentByUserID int32 `json:"email_sent_by_user_id"`
|
EmailSentByUserID int32 `json:"email_sent_by_user_id"`
|
||||||
|
UserUsername sql.NullString `json:"user_username"`
|
||||||
UserFirstName sql.NullString `json:"user_first_name"`
|
UserFirstName sql.NullString `json:"user_first_name"`
|
||||||
UserLastName sql.NullString `json:"user_last_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"`
|
PdfCreatorFirstName sql.NullString `json:"pdf_creator_first_name"`
|
||||||
PdfCreatorLastName sql.NullString `json:"pdf_creator_last_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) {
|
func (q *Queries) GetDocumentWithUser(ctx context.Context, id int32) (GetDocumentWithUserRow, error) {
|
||||||
rows, err := q.db.QueryContext(ctx, listDocuments)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
items := []ListDocumentsRow{}
|
items := []GetRecentDocumentsRow{}
|
||||||
for rows.Next() {
|
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(
|
if err := rows.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.Type,
|
&i.Type,
|
||||||
&i.Created,
|
&i.Created,
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.DocPageCount,
|
&i.DocPageCount,
|
||||||
|
&i.CmcReference,
|
||||||
&i.PdfFilename,
|
&i.PdfFilename,
|
||||||
&i.PdfCreatedAt,
|
&i.PdfCreatedAt,
|
||||||
&i.PdfCreatedByUserID,
|
&i.PdfCreatedByUserID,
|
||||||
&i.CmcReference,
|
&i.ShippingDetails,
|
||||||
&i.Revision,
|
&i.Revision,
|
||||||
|
&i.BillTo,
|
||||||
|
&i.ShipTo,
|
||||||
&i.EmailSentAt,
|
&i.EmailSentAt,
|
||||||
&i.EmailSentByUserID,
|
&i.EmailSentByUserID,
|
||||||
&i.UserFirstName,
|
|
||||||
&i.UserLastName,
|
|
||||||
&i.UserUsername,
|
|
||||||
&i.PdfCreatorFirstName,
|
|
||||||
&i.PdfCreatorLastName,
|
|
||||||
&i.PdfCreatorUsername,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -304,92 +317,40 @@ func (q *Queries) ListDocuments(ctx context.Context) ([]ListDocumentsRow, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const listDocumentsByType = `-- name: ListDocumentsByType :many
|
const listDocumentsByType = `-- name: ListDocumentsByType :many
|
||||||
SELECT
|
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 ?
|
||||||
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
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type ListDocumentsByTypeRow struct {
|
type ListDocumentsByTypeParams struct {
|
||||||
ID int32 `json:"id"`
|
Type DocumentsType `json:"type"`
|
||||||
Type DocumentsType `json:"type"`
|
Limit int32 `json:"limit"`
|
||||||
Created time.Time `json:"created"`
|
Offset int32 `json:"offset"`
|
||||||
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) ListDocumentsByType(ctx context.Context, type_ DocumentsType) ([]ListDocumentsByTypeRow, error) {
|
func (q *Queries) ListDocumentsByType(ctx context.Context, arg ListDocumentsByTypeParams) ([]Document, error) {
|
||||||
rows, err := q.db.QueryContext(ctx, listDocumentsByType, type_)
|
rows, err := q.db.QueryContext(ctx, listDocumentsByType, arg.Type, arg.Limit, arg.Offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
items := []ListDocumentsByTypeRow{}
|
items := []Document{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i ListDocumentsByTypeRow
|
var i Document
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.Type,
|
&i.Type,
|
||||||
&i.Created,
|
&i.Created,
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.DocPageCount,
|
&i.DocPageCount,
|
||||||
|
&i.CmcReference,
|
||||||
&i.PdfFilename,
|
&i.PdfFilename,
|
||||||
&i.PdfCreatedAt,
|
&i.PdfCreatedAt,
|
||||||
&i.PdfCreatedByUserID,
|
&i.PdfCreatedByUserID,
|
||||||
&i.CmcReference,
|
&i.ShippingDetails,
|
||||||
&i.Revision,
|
&i.Revision,
|
||||||
|
&i.BillTo,
|
||||||
|
&i.ShipTo,
|
||||||
&i.EmailSentAt,
|
&i.EmailSentAt,
|
||||||
&i.EmailSentByUserID,
|
&i.EmailSentByUserID,
|
||||||
&i.UserFirstName,
|
|
||||||
&i.UserLastName,
|
|
||||||
&i.UserUsername,
|
|
||||||
&i.PdfCreatorFirstName,
|
|
||||||
&i.PdfCreatorLastName,
|
|
||||||
&i.PdfCreatorUsername,
|
|
||||||
&i.CustomerName,
|
|
||||||
&i.EnquiryTitle,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -404,159 +365,12 @@ func (q *Queries) ListDocumentsByType(ctx context.Context, type_ DocumentsType)
|
||||||
return items, nil
|
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
|
const updateDocument = `-- name: UpdateDocument :exec
|
||||||
UPDATE documents
|
UPDATE documents SET
|
||||||
SET
|
type = ?, user_id = ?, doc_page_count = ?, cmc_reference = ?,
|
||||||
type = ?,
|
pdf_filename = ?, pdf_created_at = ?, pdf_created_by_user_id = ?,
|
||||||
user_id = ?,
|
shipping_details = ?, revision = ?, bill_to = ?, ship_to = ?,
|
||||||
doc_page_count = ?,
|
email_sent_at = ?, email_sent_by_user_id = ?
|
||||||
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 = ?
|
WHERE id = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -596,29 +410,3 @@ func (q *Queries) UpdateDocument(ctx context.Context, arg UpdateDocumentParams)
|
||||||
)
|
)
|
||||||
return err
|
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
|
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
|
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
|
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 = ?
|
WHERE parent_purchase_order_id = ?
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Querier interface {
|
type Querier interface {
|
||||||
ArchiveDocument(ctx context.Context, id int32) error
|
|
||||||
ArchiveEnquiry(ctx context.Context, id int32) error
|
ArchiveEnquiry(ctx context.Context, id int32) error
|
||||||
ArchiveUser(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)
|
CountEnquiries(ctx context.Context) (int64, error)
|
||||||
CountEnquiriesByPrinciple(ctx context.Context, principleCode int32) (int64, error)
|
CountEnquiriesByPrinciple(ctx context.Context, principleCode int32) (int64, error)
|
||||||
CountEnquiriesByPrincipleAndState(ctx context.Context, arg CountEnquiriesByPrincipleAndStateParams) (int64, error)
|
CountEnquiriesByPrincipleAndState(ctx context.Context, arg CountEnquiriesByPrincipleAndStateParams) (int64, error)
|
||||||
|
|
@ -36,6 +37,7 @@ type Querier interface {
|
||||||
DeleteBox(ctx context.Context, id int32) error
|
DeleteBox(ctx context.Context, id int32) error
|
||||||
DeleteCountry(ctx context.Context, id int32) error
|
DeleteCountry(ctx context.Context, id int32) error
|
||||||
DeleteCustomer(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
|
DeleteLineItem(ctx context.Context, id int32) error
|
||||||
DeleteProduct(ctx context.Context, id int32) error
|
DeleteProduct(ctx context.Context, id int32) error
|
||||||
DeletePurchaseOrder(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)
|
GetCustomer(ctx context.Context, id int32) (Customer, error)
|
||||||
GetCustomerAddresses(ctx context.Context, customerID int32) ([]GetCustomerAddressesRow, error)
|
GetCustomerAddresses(ctx context.Context, customerID int32) ([]GetCustomerAddressesRow, error)
|
||||||
GetCustomerByABN(ctx context.Context, abn sql.NullString) (Customer, 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)
|
GetEnquiriesByCustomer(ctx context.Context, arg GetEnquiriesByCustomerParams) ([]GetEnquiriesByCustomerRow, error)
|
||||||
GetEnquiriesByUser(ctx context.Context, arg GetEnquiriesByUserParams) ([]GetEnquiriesByUserRow, error)
|
GetEnquiriesByUser(ctx context.Context, arg GetEnquiriesByUserParams) ([]GetEnquiriesByUserRow, error)
|
||||||
GetEnquiry(ctx context.Context, id int32) (GetEnquiryRow, error)
|
GetEnquiry(ctx context.Context, id int32) (GetEnquiryRow, error)
|
||||||
|
|
@ -67,9 +70,10 @@ type Querier interface {
|
||||||
GetProductByItemCode(ctx context.Context, itemCode string) (Product, error)
|
GetProductByItemCode(ctx context.Context, itemCode string) (Product, error)
|
||||||
GetProductsByCategory(ctx context.Context, arg GetProductsByCategoryParams) ([]Product, error)
|
GetProductsByCategory(ctx context.Context, arg GetProductsByCategoryParams) ([]Product, error)
|
||||||
GetPurchaseOrder(ctx context.Context, id int32) (PurchaseOrder, 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)
|
GetPurchaseOrderRevisions(ctx context.Context, parentPurchaseOrderID int32) ([]PurchaseOrder, error)
|
||||||
GetPurchaseOrdersByPrinciple(ctx context.Context, arg GetPurchaseOrdersByPrincipleParams) ([]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)
|
GetState(ctx context.Context, id int32) (State, error)
|
||||||
GetStatus(ctx context.Context, id int32) (Status, error)
|
GetStatus(ctx context.Context, id int32) (Status, error)
|
||||||
GetUser(ctx context.Context, id int32) (GetUserRow, error)
|
GetUser(ctx context.Context, id int32) (GetUserRow, error)
|
||||||
|
|
@ -84,8 +88,8 @@ type Querier interface {
|
||||||
ListBoxesByShipment(ctx context.Context, shipmentID int32) ([]Box, error)
|
ListBoxesByShipment(ctx context.Context, shipmentID int32) ([]Box, error)
|
||||||
ListCountries(ctx context.Context, arg ListCountriesParams) ([]Country, error)
|
ListCountries(ctx context.Context, arg ListCountriesParams) ([]Country, error)
|
||||||
ListCustomers(ctx context.Context, arg ListCustomersParams) ([]Customer, error)
|
ListCustomers(ctx context.Context, arg ListCustomersParams) ([]Customer, error)
|
||||||
ListDocuments(ctx context.Context) ([]ListDocumentsRow, error)
|
ListDocuments(ctx context.Context, arg ListDocumentsParams) ([]Document, error)
|
||||||
ListDocumentsByType(ctx context.Context, type_ DocumentsType) ([]ListDocumentsByTypeRow, error)
|
ListDocumentsByType(ctx context.Context, arg ListDocumentsByTypeParams) ([]Document, error)
|
||||||
ListEnquiries(ctx context.Context, arg ListEnquiriesParams) ([]ListEnquiriesRow, error)
|
ListEnquiries(ctx context.Context, arg ListEnquiriesParams) ([]ListEnquiriesRow, error)
|
||||||
ListLineItems(ctx context.Context, arg ListLineItemsParams) ([]LineItem, error)
|
ListLineItems(ctx context.Context, arg ListLineItemsParams) ([]LineItem, error)
|
||||||
ListLineItemsByDocument(ctx context.Context, documentID int32) ([]LineItem, error)
|
ListLineItemsByDocument(ctx context.Context, documentID int32) ([]LineItem, error)
|
||||||
|
|
@ -97,13 +101,9 @@ type Querier interface {
|
||||||
MarkEnquirySubmitted(ctx context.Context, arg MarkEnquirySubmittedParams) error
|
MarkEnquirySubmitted(ctx context.Context, arg MarkEnquirySubmittedParams) error
|
||||||
SearchCountriesByName(ctx context.Context, concat interface{}) ([]Country, error)
|
SearchCountriesByName(ctx context.Context, concat interface{}) ([]Country, error)
|
||||||
SearchCustomersByName(ctx context.Context, arg SearchCustomersByNameParams) ([]Customer, 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)
|
SearchEnquiries(ctx context.Context, arg SearchEnquiriesParams) ([]SearchEnquiriesRow, error)
|
||||||
SearchProductsByTitle(ctx context.Context, arg SearchProductsByTitleParams) ([]Product, error)
|
SearchProductsByTitle(ctx context.Context, arg SearchProductsByTitleParams) ([]Product, error)
|
||||||
SearchPurchaseOrdersByTitle(ctx context.Context, arg SearchPurchaseOrdersByTitleParams) ([]PurchaseOrder, 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
|
UnarchiveEnquiry(ctx context.Context, id int32) error
|
||||||
UnarchiveUser(ctx context.Context, id int32) error
|
UnarchiveUser(ctx context.Context, id int32) error
|
||||||
UpdateAddress(ctx context.Context, arg UpdateAddressParams) error
|
UpdateAddress(ctx context.Context, arg UpdateAddressParams) error
|
||||||
|
|
@ -112,7 +112,6 @@ type Querier interface {
|
||||||
UpdateCountry(ctx context.Context, arg UpdateCountryParams) error
|
UpdateCountry(ctx context.Context, arg UpdateCountryParams) error
|
||||||
UpdateCustomer(ctx context.Context, arg UpdateCustomerParams) error
|
UpdateCustomer(ctx context.Context, arg UpdateCustomerParams) error
|
||||||
UpdateDocument(ctx context.Context, arg UpdateDocumentParams) error
|
UpdateDocument(ctx context.Context, arg UpdateDocumentParams) error
|
||||||
UpdateDocumentPDFInfo(ctx context.Context, arg UpdateDocumentPDFInfoParams) error
|
|
||||||
UpdateEnquiry(ctx context.Context, arg UpdateEnquiryParams) error
|
UpdateEnquiry(ctx context.Context, arg UpdateEnquiryParams) error
|
||||||
UpdateEnquiryStatus(ctx context.Context, arg UpdateEnquiryStatusParams) error
|
UpdateEnquiryStatus(ctx context.Context, arg UpdateEnquiryStatusParams) error
|
||||||
UpdateLineItem(ctx context.Context, arg UpdateLineItemParams) 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
|
// Check for type filter
|
||||||
docType := r.URL.Query().Get("type")
|
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 documents interface{}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if docType != "" {
|
if docType != "" {
|
||||||
// Convert string to DocumentsType enum
|
// 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 {
|
} else {
|
||||||
documents, err = h.queries.ListDocuments(ctx)
|
documents, err = h.queries.ListDocuments(ctx, db.ListDocumentsParams{
|
||||||
|
Limit: limit,
|
||||||
|
Offset: offset,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -85,7 +106,7 @@ func (h *DocumentHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
document, err := h.queries.GetDocumentByID(ctx, int32(id))
|
document, err := h.queries.GetDocument(ctx, int32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error fetching document %d: %v", id, err)
|
log.Printf("Error fetching document %d: %v", id, err)
|
||||||
http.Error(w, "Document not found", http.StatusNotFound)
|
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
|
// Archive handles PUT /api/documents/{id}/archive
|
||||||
func (h *DocumentHandler) Archive(w http.ResponseWriter, r *http.Request) {
|
func (h *DocumentHandler) Archive(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
// TODO: Implement archive functionality when query is added
|
||||||
idStr := vars["id"]
|
http.Error(w, "Archive functionality not yet implemented", http.StatusNotImplemented)
|
||||||
|
|
||||||
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",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unarchive handles PUT /api/documents/{id}/unarchive
|
// Unarchive handles PUT /api/documents/{id}/unarchive
|
||||||
func (h *DocumentHandler) Unarchive(w http.ResponseWriter, r *http.Request) {
|
func (h *DocumentHandler) Unarchive(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
// TODO: Implement unarchive functionality when query is added
|
||||||
idStr := vars["id"]
|
http.Error(w, "Unarchive functionality not yet implemented", http.StatusNotImplemented)
|
||||||
|
|
||||||
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",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search handles GET /api/documents/search?q=query
|
// Search handles GET /api/documents/search?q=query
|
||||||
func (h *DocumentHandler) Search(w http.ResponseWriter, r *http.Request) {
|
func (h *DocumentHandler) Search(w http.ResponseWriter, r *http.Request) {
|
||||||
query := r.URL.Query().Get("q")
|
// TODO: Implement search functionality when query is added
|
||||||
if query == "" {
|
http.Error(w, "Search functionality not yet implemented", http.StatusNotImplemented)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GeneratePDF handles GET /documents/pdf/{id}
|
// GeneratePDF handles GET /documents/pdf/{id}
|
||||||
|
|
@ -364,7 +323,7 @@ func (h *DocumentHandler) GeneratePDF(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// Get document
|
// Get document
|
||||||
document, err := h.queries.GetDocumentByID(ctx, int32(id))
|
document, err := h.queries.GetDocument(ctx, int32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error fetching document %d: %v", id, err)
|
log.Printf("Error fetching document %d: %v", id, err)
|
||||||
http.Error(w, "Document not found", http.StatusNotFound)
|
http.Error(w, "Document not found", http.StatusNotFound)
|
||||||
|
|
@ -488,18 +447,9 @@ func (h *DocumentHandler) GeneratePDF(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update document with PDF filename and timestamp
|
// TODO: Update document with PDF filename and timestamp
|
||||||
now := time.Now()
|
// This would require a specific query to update just PDF info
|
||||||
err = h.queries.UpdateDocumentPDFInfo(ctx, db.UpdateDocumentPDFInfoParams{
|
log.Printf("PDF generated successfully: %s", filename)
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return success response with redirect to document view
|
// Return success response with redirect to document view
|
||||||
w.Header().Set("Content-Type", "text/html")
|
w.Header().Set("Content-Type", "text/html")
|
||||||
|
|
@ -516,3 +466,100 @@ func (h *DocumentHandler) GeneratePDF(w http.ResponseWriter, r *http.Request) {
|
||||||
</html>
|
</html>
|
||||||
`, id, id)
|
`, 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
|
// Get document type filter
|
||||||
docType := r.URL.Query().Get("type")
|
docType := r.URL.Query().Get("type")
|
||||||
|
|
||||||
|
limit := 20
|
||||||
|
offset := (page - 1) * limit
|
||||||
|
|
||||||
var documents interface{}
|
var documents interface{}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if docType != "" {
|
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 {
|
} 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 {
|
if err != nil {
|
||||||
|
|
@ -664,7 +674,7 @@ func (h *PageHandler) DocumentsShow(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
document, err := h.queries.GetDocumentByID(r.Context(), int32(id))
|
document, err := h.queries.GetDocumentWithUser(r.Context(), int32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error fetching document %d: %v", id, err)
|
log.Printf("Error fetching document %d: %v", id, err)
|
||||||
http.Error(w, "Document not found", http.StatusNotFound)
|
http.Error(w, "Document not found", http.StatusNotFound)
|
||||||
|
|
@ -681,31 +691,22 @@ func (h *PageHandler) DocumentsShow(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *PageHandler) DocumentsSearch(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 documents interface{}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if query == "" {
|
// For now, just return all documents until search is implemented
|
||||||
// If no search query, return regular list
|
limit := 20
|
||||||
documents, err = h.queries.ListDocuments(r.Context())
|
offset := 0
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
documents, err = h.queries.ListDocuments(r.Context(), db.ListDocumentsParams{
|
||||||
return
|
Limit: int32(limit),
|
||||||
}
|
Offset: int32(offset),
|
||||||
} else {
|
})
|
||||||
searchPattern := "%" + query + "%"
|
if err != nil {
|
||||||
documents, err = h.queries.SearchDocuments(r.Context(), db.SearchDocumentsParams{
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
PdfFilename: searchPattern,
|
return
|
||||||
CmcReference: searchPattern,
|
|
||||||
Name: searchPattern,
|
|
||||||
Title: searchPattern,
|
|
||||||
Username: searchPattern,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
|
|
@ -726,7 +727,7 @@ func (h *PageHandler) DocumentsView(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
document, err := h.queries.GetDocumentByID(r.Context(), int32(id))
|
document, err := h.queries.GetDocumentWithUser(r.Context(), int32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Document not found", http.StatusNotFound)
|
http.Error(w, "Document not found", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ func (g *Generator) Page1Header() {
|
||||||
g.pdf.SetTextColor(0, 0, 152)
|
g.pdf.SetTextColor(0, 0, 152)
|
||||||
|
|
||||||
// Add logo if available (assuming logo is in static directory)
|
// 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
|
// 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
|
// Company name
|
||||||
g.pdf.SetFont("Helvetica", "B", 30)
|
g.pdf.SetFont("Helvetica", "B", 30)
|
||||||
|
|
@ -108,7 +108,7 @@ func (g *Generator) Page1Footer() {
|
||||||
|
|
||||||
// First line of services
|
// First line of services
|
||||||
services := []struct {
|
services := []struct {
|
||||||
text string
|
text string
|
||||||
r, g, b int
|
r, g, b int
|
||||||
}{
|
}{
|
||||||
{"EXPLOSION PREVENTION AND PROTECTION", 153, 0, 10},
|
{"EXPLOSION PREVENTION AND PROTECTION", 153, 0, 10},
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// QuotePDFData contains all data needed to generate a quote PDF
|
// QuotePDFData contains all data needed to generate a quote PDF
|
||||||
type QuotePDFData struct {
|
type QuotePDFData struct {
|
||||||
Document *db.GetDocumentByIDRow
|
Document *db.Document
|
||||||
Quote interface{} // Quote specific data
|
Quote interface{} // Quote specific data
|
||||||
Enquiry *db.Enquiry
|
Enquiry *db.Enquiry
|
||||||
Customer *db.Customer
|
Customer *db.Customer
|
||||||
|
|
@ -32,25 +32,26 @@ func GenerateQuotePDF(data *QuotePDFData, outputDir string) (string, error) {
|
||||||
gen.Page1Header()
|
gen.Page1Header()
|
||||||
|
|
||||||
// Extract data for details box
|
// 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
|
emailTo := "" // TODO: Get from contact
|
||||||
attention := "" // TODO: Get from contact
|
attention := "" // TODO: Get from contact
|
||||||
fromName := fmt.Sprintf("%s %s", data.User.FirstName, data.User.LastName)
|
fromName := fmt.Sprintf("%s %s", data.User.FirstName, data.User.LastName)
|
||||||
fromEmail := data.User.Email
|
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 {
|
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"))
|
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
|
// 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
|
// Add page content if any
|
||||||
// TODO: Add document pages content
|
// TODO: Add document pages content
|
||||||
|
|
@ -101,11 +102,11 @@ func GenerateQuotePDF(data *QuotePDFData, outputDir string) (string, error) {
|
||||||
// TODO: Add terms and conditions page
|
// TODO: Add terms and conditions page
|
||||||
|
|
||||||
// Generate filename
|
// Generate filename
|
||||||
filename := enquiryNumber
|
filename := quoteNumber
|
||||||
if data.Document.Revision > 0 {
|
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 {
|
} else {
|
||||||
filename = fmt.Sprintf("%s.pdf", enquiryNumber)
|
filename = fmt.Sprintf("%s.pdf", quoteNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save PDF
|
// 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
|
// PurchaseOrderPDFData contains all data needed to generate a purchase order PDF
|
||||||
type PurchaseOrderPDFData struct {
|
type PurchaseOrderPDFData struct {
|
||||||
Document *db.GetDocumentByIDRow
|
Document *db.Document
|
||||||
PurchaseOrder *db.GetPurchaseOrderByDocumentIDRow
|
PurchaseOrder *db.PurchaseOrder
|
||||||
Principle *db.Principle
|
Principle *db.Principle
|
||||||
LineItems []db.GetLineItemsTableRow
|
LineItems []db.GetLineItemsTableRow
|
||||||
Currency interface{} // Currency data
|
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
|
-- name: ListDocuments :many
|
||||||
SELECT
|
SELECT * FROM documents ORDER BY created DESC LIMIT ? OFFSET ?;
|
||||||
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;
|
|
||||||
|
|
||||||
-- name: ListDocumentsByType :many
|
-- 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
|
SELECT
|
||||||
d.id,
|
d.id,
|
||||||
d.type,
|
d.type,
|
||||||
d.created,
|
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.cmc_reference,
|
||||||
|
d.pdf_filename,
|
||||||
d.revision,
|
d.revision,
|
||||||
d.email_sent_at,
|
u.username as created_by_username,
|
||||||
d.email_sent_by_user_id,
|
CASE
|
||||||
u.first_name as user_first_name,
|
WHEN d.type = 'quote' THEN CONCAT('Quote ', d.cmc_reference)
|
||||||
u.last_name as user_last_name,
|
WHEN d.type = 'invoice' THEN CONCAT('Invoice ', d.cmc_reference)
|
||||||
u.username as user_username,
|
WHEN d.type = 'purchaseOrder' THEN CONCAT('Purchase Order ', d.cmc_reference)
|
||||||
pdf_creator.first_name as pdf_creator_first_name,
|
WHEN d.type = 'orderAck' THEN CONCAT('Order Ack ', d.cmc_reference)
|
||||||
pdf_creator.last_name as pdf_creator_last_name,
|
WHEN d.type = 'packingList' THEN CONCAT('Packing List ', d.cmc_reference)
|
||||||
pdf_creator.username as pdf_creator_username,
|
ELSE CONCAT(d.type, ' ', d.cmc_reference)
|
||||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
END as display_name
|
||||||
e.title as enquiry_title
|
|
||||||
FROM documents d
|
FROM documents d
|
||||||
LEFT JOIN users u ON d.user_id = u.id
|
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.created DESC
|
||||||
LEFT JOIN enquiries e ON d.type IN ('quote', 'orderAck') AND d.cmc_reference = e.title
|
LIMIT ?;
|
||||||
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;
|
|
||||||
|
|
||||||
-- name: GetDocumentByID :one
|
-- name: CountDocuments :one
|
||||||
|
SELECT COUNT(*) FROM documents;
|
||||||
|
|
||||||
|
-- name: CountDocumentsByType :one
|
||||||
|
SELECT COUNT(*) FROM documents WHERE type = ?;
|
||||||
|
|
||||||
|
-- name: GetDocumentWithUser :one
|
||||||
SELECT
|
SELECT
|
||||||
d.id,
|
d.id,
|
||||||
d.type,
|
d.type,
|
||||||
d.created,
|
d.created,
|
||||||
d.user_id,
|
d.user_id,
|
||||||
d.doc_page_count,
|
d.doc_page_count,
|
||||||
|
d.cmc_reference,
|
||||||
d.pdf_filename,
|
d.pdf_filename,
|
||||||
d.pdf_created_at,
|
d.pdf_created_at,
|
||||||
d.pdf_created_by_user_id,
|
d.pdf_created_by_user_id,
|
||||||
d.cmc_reference,
|
|
||||||
d.revision,
|
|
||||||
d.shipping_details,
|
d.shipping_details,
|
||||||
|
d.revision,
|
||||||
d.bill_to,
|
d.bill_to,
|
||||||
d.ship_to,
|
d.ship_to,
|
||||||
d.email_sent_at,
|
d.email_sent_at,
|
||||||
d.email_sent_by_user_id,
|
d.email_sent_by_user_id,
|
||||||
|
u.username as user_username,
|
||||||
u.first_name as user_first_name,
|
u.first_name as user_first_name,
|
||||||
u.last_name as user_last_name,
|
u.last_name as user_last_name,
|
||||||
u.username as user_username,
|
u.email as user_email,
|
||||||
pdf_creator.first_name as pdf_creator_first_name,
|
pu.username as pdf_creator_username,
|
||||||
pdf_creator.last_name as pdf_creator_last_name,
|
pu.first_name as pdf_creator_first_name,
|
||||||
pdf_creator.username as pdf_creator_username,
|
pu.last_name as pdf_creator_last_name,
|
||||||
COALESCE(ec.name, ic.name, '') as customer_name,
|
pu.email as pdf_creator_email
|
||||||
e.title as enquiry_title
|
|
||||||
FROM documents d
|
FROM documents d
|
||||||
LEFT JOIN users u ON d.user_id = u.id
|
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 users pu ON d.pdf_created_by_user_id = pu.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 = ?;
|
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('%', ?, '%')
|
WHERE title LIKE CONCAT('%', ?, '%')
|
||||||
ORDER BY issue_date DESC
|
ORDER BY issue_date DESC
|
||||||
LIMIT ? OFFSET ?;
|
LIMIT ? OFFSET ?;
|
||||||
|
|
||||||
|
-- name: GetPurchaseOrderByDocumentID :one
|
||||||
|
SELECT * FROM purchase_orders
|
||||||
|
WHERE document_id = ?
|
||||||
|
LIMIT 1;
|
||||||
|
|
@ -109,7 +109,8 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if or .Document.CustomerName .Document.EnquiryTitle.Valid}}
|
{{/* TODO: Add customer and enquiry information when queries are available */}}
|
||||||
|
{{if false}}
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<h3 class="title is-5">Related Information</h3>
|
<h3 class="title is-5">Related Information</h3>
|
||||||
<table class="table is-fullwidth">
|
<table class="table is-fullwidth">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue