package repository import ( "apskel-pos-be/internal/entities" "context" "database/sql" "fmt" "github.com/google/uuid" ) type UnitRepository struct { db *sql.DB } func NewUnitRepository(db *sql.DB) *UnitRepository { return &UnitRepository{db: db} } func (r *UnitRepository) Create(ctx context.Context, unit *entities.Unit) error { query := ` INSERT INTO units (id, organization_id, outlet_id, name, abbreviation, is_active, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ` _, err := r.db.ExecContext(ctx, query, unit.ID, unit.OrganizationID, unit.OutletID, unit.Name, unit.Abbreviation, unit.IsActive, unit.CreatedAt, unit.UpdatedAt, ) return err } func (r *UnitRepository) GetByID(ctx context.Context, id, organizationID uuid.UUID) (*entities.Unit, error) { query := ` SELECT id, organization_id, outlet_id, name, abbreviation, is_active, created_at, updated_at FROM units WHERE id = $1 AND organization_id = $2 ` unit := &entities.Unit{} err := r.db.QueryRowContext(ctx, query, id, organizationID).Scan( &unit.ID, &unit.OrganizationID, &unit.OutletID, &unit.Name, &unit.Abbreviation, &unit.IsActive, &unit.CreatedAt, &unit.UpdatedAt, ) if err != nil { return nil, err } return unit, nil } func (r *UnitRepository) GetAll(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, page, limit int, search string) ([]*entities.Unit, int, error) { offset := (page - 1) * limit // Build WHERE clause whereClause := "WHERE organization_id = $1" args := []interface{}{organizationID} argCount := 1 if outletID != nil { argCount++ whereClause += fmt.Sprintf(" AND outlet_id = $%d", argCount) args = append(args, *outletID) } if search != "" { argCount++ whereClause += fmt.Sprintf(" AND (name ILIKE $%d OR abbreviation ILIKE $%d)", argCount, argCount) args = append(args, "%"+search+"%") } // Count query countQuery := fmt.Sprintf("SELECT COUNT(*) FROM units %s", whereClause) var total int err := r.db.QueryRowContext(ctx, countQuery, args...).Scan(&total) if err != nil { return nil, 0, err } // Data query argCount++ query := fmt.Sprintf(` SELECT id, organization_id, outlet_id, name, abbreviation, is_active, created_at, updated_at FROM units %s ORDER BY created_at DESC LIMIT $%d OFFSET $%d `, whereClause, argCount, argCount+1) args = append(args, limit, offset) rows, err := r.db.QueryContext(ctx, query, args...) if err != nil { return nil, 0, err } defer rows.Close() var units []*entities.Unit for rows.Next() { unit := &entities.Unit{} err := rows.Scan( &unit.ID, &unit.OrganizationID, &unit.OutletID, &unit.Name, &unit.Abbreviation, &unit.IsActive, &unit.CreatedAt, &unit.UpdatedAt, ) if err != nil { return nil, 0, err } units = append(units, unit) } return units, total, nil } func (r *UnitRepository) Update(ctx context.Context, unit *entities.Unit) error { query := ` UPDATE units SET outlet_id = $1, name = $2, abbreviation = $3, is_active = $4, updated_at = $5 WHERE id = $6 AND organization_id = $7 ` result, err := r.db.ExecContext(ctx, query, unit.OutletID, unit.Name, unit.Abbreviation, unit.IsActive, unit.UpdatedAt, unit.ID, unit.OrganizationID, ) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return sql.ErrNoRows } return nil } func (r *UnitRepository) Delete(ctx context.Context, id, organizationID uuid.UUID) error { query := `DELETE FROM units WHERE id = $1 AND organization_id = $2` result, err := r.db.ExecContext(ctx, query, id, organizationID) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return sql.ErrNoRows } return nil }