347 lines
8.6 KiB
Go
347 lines
8.6 KiB
Go
package repository
|
|
|
|
import (
|
|
"aggios-app/backend/internal/domain"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
"github.com/lib/pq"
|
|
)
|
|
|
|
type CRMRepository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
func NewCRMRepository(db *sql.DB) *CRMRepository {
|
|
return &CRMRepository{db: db}
|
|
}
|
|
|
|
// ==================== CUSTOMERS ====================
|
|
|
|
func (r *CRMRepository) CreateCustomer(customer *domain.CRMCustomer) error {
|
|
query := `
|
|
INSERT INTO crm_customers (
|
|
id, tenant_id, name, email, phone, company, position,
|
|
address, city, state, zip_code, country, notes, tags,
|
|
is_active, created_by
|
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
|
RETURNING created_at, updated_at
|
|
`
|
|
|
|
return r.db.QueryRow(
|
|
query,
|
|
customer.ID, customer.TenantID, customer.Name, customer.Email, customer.Phone,
|
|
customer.Company, customer.Position, customer.Address, customer.City, customer.State,
|
|
customer.ZipCode, customer.Country, customer.Notes, pq.Array(customer.Tags),
|
|
customer.IsActive, customer.CreatedBy,
|
|
).Scan(&customer.CreatedAt, &customer.UpdatedAt)
|
|
}
|
|
|
|
func (r *CRMRepository) GetCustomersByTenant(tenantID string) ([]domain.CRMCustomer, error) {
|
|
query := `
|
|
SELECT id, tenant_id, name, email, phone, company, position,
|
|
address, city, state, zip_code, country, notes, tags,
|
|
is_active, created_by, created_at, updated_at
|
|
FROM crm_customers
|
|
WHERE tenant_id = $1 AND is_active = true
|
|
ORDER BY created_at DESC
|
|
`
|
|
|
|
rows, err := r.db.Query(query, tenantID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var customers []domain.CRMCustomer
|
|
for rows.Next() {
|
|
var c domain.CRMCustomer
|
|
err := rows.Scan(
|
|
&c.ID, &c.TenantID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.Position,
|
|
&c.Address, &c.City, &c.State, &c.ZipCode, &c.Country, &c.Notes, pq.Array(&c.Tags),
|
|
&c.IsActive, &c.CreatedBy, &c.CreatedAt, &c.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
customers = append(customers, c)
|
|
}
|
|
|
|
return customers, nil
|
|
}
|
|
|
|
func (r *CRMRepository) GetCustomerByID(id string, tenantID string) (*domain.CRMCustomer, error) {
|
|
query := `
|
|
SELECT id, tenant_id, name, email, phone, company, position,
|
|
address, city, state, zip_code, country, notes, tags,
|
|
is_active, created_by, created_at, updated_at
|
|
FROM crm_customers
|
|
WHERE id = $1 AND tenant_id = $2
|
|
`
|
|
|
|
var c domain.CRMCustomer
|
|
err := r.db.QueryRow(query, id, tenantID).Scan(
|
|
&c.ID, &c.TenantID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.Position,
|
|
&c.Address, &c.City, &c.State, &c.ZipCode, &c.Country, &c.Notes, pq.Array(&c.Tags),
|
|
&c.IsActive, &c.CreatedBy, &c.CreatedAt, &c.UpdatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &c, nil
|
|
}
|
|
|
|
func (r *CRMRepository) UpdateCustomer(customer *domain.CRMCustomer) error {
|
|
query := `
|
|
UPDATE crm_customers SET
|
|
name = $1, email = $2, phone = $3, company = $4, position = $5,
|
|
address = $6, city = $7, state = $8, zip_code = $9, country = $10,
|
|
notes = $11, tags = $12, is_active = $13
|
|
WHERE id = $14 AND tenant_id = $15
|
|
`
|
|
|
|
result, err := r.db.Exec(
|
|
query,
|
|
customer.Name, customer.Email, customer.Phone, customer.Company, customer.Position,
|
|
customer.Address, customer.City, customer.State, customer.ZipCode, customer.Country,
|
|
customer.Notes, pq.Array(customer.Tags), customer.IsActive,
|
|
customer.ID, customer.TenantID,
|
|
)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows == 0 {
|
|
return fmt.Errorf("customer not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *CRMRepository) DeleteCustomer(id string, tenantID string) error {
|
|
query := `DELETE FROM crm_customers WHERE id = $1 AND tenant_id = $2`
|
|
|
|
result, err := r.db.Exec(query, id, tenantID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows == 0 {
|
|
return fmt.Errorf("customer not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ==================== LISTS ====================
|
|
|
|
func (r *CRMRepository) CreateList(list *domain.CRMList) error {
|
|
query := `
|
|
INSERT INTO crm_lists (id, tenant_id, name, description, color, created_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
RETURNING created_at, updated_at
|
|
`
|
|
|
|
return r.db.QueryRow(
|
|
query,
|
|
list.ID, list.TenantID, list.Name, list.Description, list.Color, list.CreatedBy,
|
|
).Scan(&list.CreatedAt, &list.UpdatedAt)
|
|
}
|
|
|
|
func (r *CRMRepository) GetListsByTenant(tenantID string) ([]domain.CRMListWithCustomers, error) {
|
|
query := `
|
|
SELECT l.id, l.tenant_id, l.name, l.description, l.color, l.created_by,
|
|
l.created_at, l.updated_at,
|
|
COUNT(cl.customer_id) as customer_count
|
|
FROM crm_lists l
|
|
LEFT JOIN crm_customer_lists cl ON l.id = cl.list_id
|
|
WHERE l.tenant_id = $1
|
|
GROUP BY l.id
|
|
ORDER BY l.created_at DESC
|
|
`
|
|
|
|
rows, err := r.db.Query(query, tenantID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var lists []domain.CRMListWithCustomers
|
|
for rows.Next() {
|
|
var l domain.CRMListWithCustomers
|
|
err := rows.Scan(
|
|
&l.ID, &l.TenantID, &l.Name, &l.Description, &l.Color, &l.CreatedBy,
|
|
&l.CreatedAt, &l.UpdatedAt, &l.CustomerCount,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lists = append(lists, l)
|
|
}
|
|
|
|
return lists, nil
|
|
}
|
|
|
|
func (r *CRMRepository) GetListByID(id string, tenantID string) (*domain.CRMList, error) {
|
|
query := `
|
|
SELECT id, tenant_id, name, description, color, created_by, created_at, updated_at
|
|
FROM crm_lists
|
|
WHERE id = $1 AND tenant_id = $2
|
|
`
|
|
|
|
var l domain.CRMList
|
|
err := r.db.QueryRow(query, id, tenantID).Scan(
|
|
&l.ID, &l.TenantID, &l.Name, &l.Description, &l.Color, &l.CreatedBy,
|
|
&l.CreatedAt, &l.UpdatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &l, nil
|
|
}
|
|
|
|
func (r *CRMRepository) UpdateList(list *domain.CRMList) error {
|
|
query := `
|
|
UPDATE crm_lists SET
|
|
name = $1, description = $2, color = $3
|
|
WHERE id = $4 AND tenant_id = $5
|
|
`
|
|
|
|
result, err := r.db.Exec(query, list.Name, list.Description, list.Color, list.ID, list.TenantID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows == 0 {
|
|
return fmt.Errorf("list not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *CRMRepository) DeleteList(id string, tenantID string) error {
|
|
query := `DELETE FROM crm_lists WHERE id = $1 AND tenant_id = $2`
|
|
|
|
result, err := r.db.Exec(query, id, tenantID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rows == 0 {
|
|
return fmt.Errorf("list not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ==================== CUSTOMER <-> LIST ====================
|
|
|
|
func (r *CRMRepository) AddCustomerToList(customerID, listID, addedBy string) error {
|
|
query := `
|
|
INSERT INTO crm_customer_lists (customer_id, list_id, added_by)
|
|
VALUES ($1, $2, $3)
|
|
ON CONFLICT (customer_id, list_id) DO NOTHING
|
|
`
|
|
|
|
_, err := r.db.Exec(query, customerID, listID, addedBy)
|
|
return err
|
|
}
|
|
|
|
func (r *CRMRepository) RemoveCustomerFromList(customerID, listID string) error {
|
|
query := `DELETE FROM crm_customer_lists WHERE customer_id = $1 AND list_id = $2`
|
|
|
|
_, err := r.db.Exec(query, customerID, listID)
|
|
return err
|
|
}
|
|
|
|
func (r *CRMRepository) GetCustomerLists(customerID string) ([]domain.CRMList, error) {
|
|
query := `
|
|
SELECT l.id, l.tenant_id, l.name, l.description, l.color, l.created_by,
|
|
l.created_at, l.updated_at
|
|
FROM crm_lists l
|
|
INNER JOIN crm_customer_lists cl ON l.id = cl.list_id
|
|
WHERE cl.customer_id = $1
|
|
ORDER BY l.name
|
|
`
|
|
|
|
rows, err := r.db.Query(query, customerID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var lists []domain.CRMList
|
|
for rows.Next() {
|
|
var l domain.CRMList
|
|
err := rows.Scan(
|
|
&l.ID, &l.TenantID, &l.Name, &l.Description, &l.Color, &l.CreatedBy,
|
|
&l.CreatedAt, &l.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lists = append(lists, l)
|
|
}
|
|
|
|
return lists, nil
|
|
}
|
|
|
|
func (r *CRMRepository) GetListCustomers(listID string, tenantID string) ([]domain.CRMCustomer, error) {
|
|
query := `
|
|
SELECT c.id, c.tenant_id, c.name, c.email, c.phone, c.company, c.position,
|
|
c.address, c.city, c.state, c.zip_code, c.country, c.notes, c.tags,
|
|
c.is_active, c.created_by, c.created_at, c.updated_at
|
|
FROM crm_customers c
|
|
INNER JOIN crm_customer_lists cl ON c.id = cl.customer_id
|
|
WHERE cl.list_id = $1 AND c.tenant_id = $2 AND c.is_active = true
|
|
ORDER BY c.name
|
|
`
|
|
|
|
rows, err := r.db.Query(query, listID, tenantID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var customers []domain.CRMCustomer
|
|
for rows.Next() {
|
|
var c domain.CRMCustomer
|
|
err := rows.Scan(
|
|
&c.ID, &c.TenantID, &c.Name, &c.Email, &c.Phone, &c.Company, &c.Position,
|
|
&c.Address, &c.City, &c.State, &c.ZipCode, &c.Country, &c.Notes, pq.Array(&c.Tags),
|
|
&c.IsActive, &c.CreatedBy, &c.CreatedAt, &c.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
customers = append(customers, c)
|
|
}
|
|
|
|
return customers, nil
|
|
}
|