Files
FPandA-Engine/internal/database/refrence-repo.go
2026-03-21 16:49:01 +01:00

206 lines
6.7 KiB
Go

package database
import (
"Engine/internal/model"
"context"
"database/sql"
"fmt"
)
// ── ReferenceRepo ─────────────────────────────────────────────────────────────
type ReferenceRepo struct {
db *sql.DB
}
func NewReferenceRepo(db *sql.DB) *ReferenceRepo {
return &ReferenceRepo{db: db}
}
// ── Department operations ─────────────────────────────────────────────────────
func (r *ReferenceRepo) CreateDepartment(ctx context.Context, d model.CreateDepartmentRequest) (*model.Department, error) {
res, err := r.db.ExecContext(ctx, `
INSERT INTO departments (code, name, cost_center, active)
VALUES (?, ?, ?, ?)
ON CONFLICT(code) DO UPDATE
SET name = excluded.name,
cost_center = excluded.cost_center,
active = excluded.active`,
d.Code, d.Name, d.CostCenter, boolToInt(d.Active),
)
if err != nil {
return nil, fmt.Errorf("upsert department: %w", err)
}
id, err := res.LastInsertId()
if err != nil || id == 0 {
// ON CONFLICT branch — fetch existing row
return r.GetDepartmentByCode(ctx, d.Code)
}
return r.GetDepartmentByCode(ctx, d.Code)
}
func (r *ReferenceRepo) GetDepartmentByCode(ctx context.Context, code string) (*model.Department, error) {
var d model.Department
var active int
err := r.db.QueryRowContext(ctx,
`SELECT id, code, name, cost_center, active, created_at FROM departments WHERE code = ?`, code,
).Scan(&d.ID, &d.Code, &d.Name, &d.CostCenter, &active, &d.CreatedAt)
if err != nil {
return nil, fmt.Errorf("fetch department by code: %w", err)
}
d.Active = active == 1
return &d, nil
}
func (r *ReferenceRepo) GetDepartmentByCostCenter(ctx context.Context, cc string) (*model.Department, error) {
var d model.Department
var active int
err := r.db.QueryRowContext(ctx,
`SELECT id, code, name, cost_center, active, created_at FROM departments WHERE cost_center = ?`, cc,
).Scan(&d.ID, &d.Code, &d.Name, &d.CostCenter, &active, &d.CreatedAt)
if err != nil {
return nil, fmt.Errorf("fetch department by code: %w", err)
}
d.Active = active == 1
return &d, nil
}
func (r *ReferenceRepo) GetDepartmentByName(ctx context.Context, name string) (*model.Department, error) {
var d model.Department
var active int
err := r.db.QueryRowContext(ctx,
`SELECT id, code, name, cost_center, active, created_at FROM departments WHERE name = ?`, name,
).Scan(&d.ID, &d.Code, &d.Name, &d.CostCenter, &active, &d.CreatedAt)
if err != nil {
return nil, fmt.Errorf("fetch department by code: %w", err)
}
d.Active = active == 1
return &d, nil
}
func (r *ReferenceRepo) SetDepartmentActivityByCode(ctx context.Context, code string, active bool) error {
_, err := r.db.ExecContext(ctx,
`UPDATE departments SET active = ? WHERE code = ?`,
boolToInt(active), code)
return err
}
func (r *ReferenceRepo) SetDepartmentActivityByName(ctx context.Context, name string, active bool) error {
_, err := r.db.ExecContext(ctx,
`UPDATE departments SET active = ? WHERE name = ?`,
boolToInt(active), name)
return err
}
func (r *ReferenceRepo) SetDepartmentActivityByCostCenter(ctx context.Context, cc string, active bool) error {
_, err := r.db.ExecContext(ctx,
`UPDATE departments SET active = ? WHERE cost_center = ?`,
boolToInt(active), cc)
return err
}
func (r *ReferenceRepo) ListDepartments(ctx context.Context) ([]model.Department, error) {
rows, err := r.db.QueryContext(ctx,
`SELECT id, code, name, cost_center, active, created_at
FROM departments ORDER BY code`)
if err != nil {
return nil, err
}
defer rows.Close()
var depts []model.Department
for rows.Next() {
var d model.Department
var active int
if err := rows.Scan(&d.ID, &d.Code, &d.Name, &d.CostCenter, &active, &d.CreatedAt); err != nil {
return nil, err
}
d.Active = active == 1
depts = append(depts, d)
}
return depts, rows.Err()
}
func (r *ReferenceRepo) DeleteDepartment(ctx context.Context, id int) error {
_, err := r.db.ExecContext(ctx, `DELETE FROM departments WHERE id = ?`, id)
return err
}
// ── GL Account operations ─────────────────────────────────────────────────────
func (r *ReferenceRepo) CreateGLAccount(ctx context.Context, a model.GLAccount) (*model.GLAccount, error) {
res, err := r.db.ExecContext(ctx, `
INSERT INTO gl_accounts (code, description, type, favour_high, active)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(code) DO UPDATE
SET description = excluded.description,
type = excluded.type,
favour_high = excluded.favour_high,
active = excluded.active`,
a.Code, a.Description, a.Type, boolToInt(a.FavourHigh), boolToInt(a.Active),
)
if err != nil {
return nil, fmt.Errorf("upsert gl_account: %w", err)
}
id, err := res.LastInsertId()
if err != nil || id == 0 {
return r.getGLAccountByCode(ctx, a.Code)
}
a.ID = int(id)
return &a, nil
}
func (r *ReferenceRepo) getGLAccountByCode(ctx context.Context, code string) (*model.GLAccount, error) {
var a model.GLAccount
var favourHigh, active int
err := r.db.QueryRowContext(ctx,
`SELECT id, code, description, type, favour_high, active FROM gl_accounts WHERE code = ?`, code,
).Scan(&a.ID, &a.Code, &a.Description, &a.Type, &favourHigh, &active)
if err != nil {
return nil, fmt.Errorf("fetch gl_account by code: %w", err)
}
a.FavourHigh = favourHigh == 1
a.Active = active == 1
return &a, nil
}
func (r *ReferenceRepo) ListGLAccounts(ctx context.Context) ([]model.GLAccount, error) {
rows, err := r.db.QueryContext(ctx,
`SELECT id, code, description, type, favour_high, active
FROM gl_accounts ORDER BY code`)
if err != nil {
return nil, err
}
defer rows.Close()
var accts []model.GLAccount
for rows.Next() {
var a model.GLAccount
var favourHigh, active int
if err := rows.Scan(&a.ID, &a.Code, &a.Description, &a.Type, &favourHigh, &active); err != nil {
return nil, err
}
a.FavourHigh = favourHigh == 1
a.Active = active == 1
accts = append(accts, a)
}
return accts, rows.Err()
}
func (r *ReferenceRepo) DeleteGLAccount(ctx context.Context, id int) error {
_, err := r.db.ExecContext(ctx, `DELETE FROM gl_accounts WHERE id = ?`, id)
return err
}
// ── helpers ───────────────────────────────────────────────────────────────────
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}