fix(security): JWT require env, remove *** token, WS auth disabled

fix(automation): implement all 6 actions + real cron parser
fix(db): pq.Array for TEXT[], add sqlmock tests
fix(schema): single source migrations
docs: v2 architecture + frontend refactor proposals
This commit is contained in:
Bernt (LandveX AI)
2026-07-14 11:46:06 +00:00
parent 77465ee9eb
commit 95b581e8c5
19 changed files with 1550 additions and 130 deletions
+12 -5
View File
@@ -7,6 +7,7 @@ import (
"time"
"github.com/go-chi/chi/v5"
"github.com/lib/pq"
)
type CRMHandler struct {
@@ -72,10 +73,12 @@ func (h *CRMHandler) ListCustomers(w http.ResponseWriter, r *http.Request) {
customers := []Customer{}
for rows.Next() {
var c Customer
var tags pq.StringArray
if err := rows.Scan(&c.ID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.OrgNumber,
&c.Status, &c.Source, &c.Tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt); err != nil {
&c.Status, &c.Source, &tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt); err != nil {
continue
}
c.Tags = []string(tags)
customers = append(customers, c)
}
@@ -97,7 +100,7 @@ func (h *CRMHandler) CreateCustomer(w http.ResponseWriter, r *http.Request) {
INSERT INTO boc_customers (name, email, phone, company, org_number, status, source, tags)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id
`, req.Name, req.Email, req.Phone, req.Company, req.OrgNumber, req.Status, req.Source, req.Tags).Scan(&id)
`, req.Name, req.Email, req.Phone, req.Company, req.OrgNumber, req.Status, req.Source, pq.Array(req.Tags)).Scan(&id)
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to create customer")
@@ -114,11 +117,13 @@ func (h *CRMHandler) GetCustomer(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
var c Customer
var tags pq.StringArray
err := h.DB.QueryRow(`
SELECT id, name, email, phone, company, org_number, status, source, tags, assigned_to, created_at, updated_at
FROM boc_customers WHERE id = $1
`, id).Scan(&c.ID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.OrgNumber,
&c.Status, &c.Source, &c.Tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt)
&c.Status, &c.Source, &tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt)
c.Tags = []string(tags)
if err == sql.ErrNoRows {
writeError(w, http.StatusNotFound, "customer not found")
@@ -147,7 +152,7 @@ func (h *CRMHandler) UpdateCustomer(w http.ResponseWriter, r *http.Request) {
status = $6, source = $7, tags = $8, assigned_to = $9
WHERE id = $10
`, req.Name, req.Email, req.Phone, req.Company, req.OrgNumber,
req.Status, req.Source, req.Tags, req.AssignedTo, id)
req.Status, req.Source, pq.Array(req.Tags), req.AssignedTo, id)
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to update customer")
@@ -189,10 +194,12 @@ func (h *CRMHandler) ListLeads(w http.ResponseWriter, r *http.Request) {
leads := []Customer{}
for rows.Next() {
var c Customer
var tags pq.StringArray
if err := rows.Scan(&c.ID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.OrgNumber,
&c.Status, &c.Source, &c.Tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt); err != nil {
&c.Status, &c.Source, &tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt); err != nil {
continue
}
c.Tags = []string(tags)
leads = append(leads, c)
}