c2b10347b1
- Removed rust-service/, c-runtime/, kafka stubs - Generic Store[T] pattern with real tests - Slimmed main.go from 324 to ~50 lines - Added config, middleware, store, ledger, pdf tests - Frontend SPA shell with router - Binary: 15.5MB -> 12MB
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
// Package models contains domain entities.
|
|
// No SQL, no JSON tags for external APIs — pure domain.
|
|
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"time"
|
|
|
|
"github.com/lib/pq"
|
|
)
|
|
|
|
// Customer represents a CRM customer
|
|
type Customer struct {
|
|
ID string
|
|
TenantID string
|
|
Name string
|
|
Email string
|
|
Phone string
|
|
Company string
|
|
OrgNumber string
|
|
Status string
|
|
Source string
|
|
Tags []string
|
|
AssignedTo *string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// ScanRow scans a sql.Rows into Customer
|
|
func (c *Customer) ScanRow(rows *sql.Rows) error {
|
|
var tags pq.StringArray
|
|
err := rows.Scan(&c.ID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.OrgNumber,
|
|
&c.Status, &c.Source, &tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt)
|
|
c.Tags = []string(tags)
|
|
return err
|
|
}
|
|
|
|
// ScanOneRow scans a sql.Row into Customer
|
|
func (c *Customer) ScanOneRow(row *sql.Row) error {
|
|
var tags pq.StringArray
|
|
err := row.Scan(&c.ID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.OrgNumber,
|
|
&c.Status, &c.Source, &tags, &c.AssignedTo, &c.CreatedAt, &c.UpdatedAt)
|
|
c.Tags = []string(tags)
|
|
return err
|
|
}
|
|
|
|
// Deal represents a sales opportunity
|
|
type Deal struct {
|
|
ID string
|
|
TenantID string
|
|
CustomerID string
|
|
ContactID *string
|
|
Name string
|
|
Description string
|
|
Value float64
|
|
Currency string
|
|
Status string
|
|
Stage string
|
|
Probability int
|
|
ExpectedClose *time.Time
|
|
ActualClose *time.Time
|
|
AssignedTo *string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// ScanRow scans a sql.Rows into Deal
|
|
func (d *Deal) ScanRow(rows *sql.Rows) error {
|
|
return rows.Scan(&d.ID, &d.TenantID, &d.CustomerID, &d.ContactID, &d.Name,
|
|
&d.Description, &d.Value, &d.Currency, &d.Status, &d.Stage,
|
|
&d.Probability, &d.ExpectedClose, &d.ActualClose, &d.AssignedTo,
|
|
&d.CreatedAt, &d.UpdatedAt)
|
|
}
|
|
|
|
// ScanOneRow scans a sql.Row into Deal
|
|
func (d *Deal) ScanOneRow(row *sql.Row) error {
|
|
return row.Scan(&d.ID, &d.TenantID, &d.CustomerID, &d.ContactID, &d.Name,
|
|
&d.Description, &d.Value, &d.Currency, &d.Status, &d.Stage,
|
|
&d.Probability, &d.ExpectedClose, &d.ActualClose, &d.AssignedTo,
|
|
&d.CreatedAt, &d.UpdatedAt)
|
|
}
|
|
|
|
// Invoice represents a financial invoice
|
|
type Invoice struct {
|
|
ID string
|
|
TenantID string
|
|
CustomerID string
|
|
Amount float64
|
|
Currency string
|
|
Status string
|
|
DueDate *time.Time
|
|
PaidAt *time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// ScanRow scans a sql.Rows into Invoice
|
|
func (i *Invoice) ScanRow(rows *sql.Rows) error {
|
|
return rows.Scan(&i.ID, &i.TenantID, &i.CustomerID, &i.Amount, &i.Currency,
|
|
&i.Status, &i.DueDate, &i.PaidAt, &i.CreatedAt)
|
|
}
|
|
|
|
// ScanOneRow scans a sql.Row into Invoice
|
|
func (i *Invoice) ScanOneRow(row *sql.Row) error {
|
|
return row.Scan(&i.ID, &i.TenantID, &i.CustomerID, &i.Amount, &i.Currency,
|
|
&i.Status, &i.DueDate, &i.PaidAt, &i.CreatedAt)
|
|
}
|