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 }