Compare commits

2 Commits

Author SHA1 Message Date
Marco Gallegos
28e4a73cdf docs: Move PRD.md from docs/ to root directory
- Moved PRD.md to root for better visibility as main product document
- PRD serves as single source of truth for AnchorOS
2026-01-19 00:53:46 -06:00
Marco Gallegos
1e93188783 fix: Correct business hours showing only 22:00-23:00 slots
- Created migration to fix ALL locations with incorrect business hours
- Added debug endpoint to check business hours
- Migration updates locations with 22:00/23:00 times to correct 10:00-19:00

This resolves the booking availability showing wrong time slots.
2026-01-19 00:47:52 -06:00
5 changed files with 792 additions and 0 deletions

View File

View File

@@ -0,0 +1,32 @@
import { NextRequest, NextResponse } from 'next/server'
import { supabaseAdmin } from '@/lib/supabase/admin'
/**
* @description Get business hours for all locations (debug endpoint)
*/
export async function GET(request: NextRequest) {
try {
const { data: locations, error } = await supabaseAdmin
.from('locations')
.select('id, name, timezone, business_hours')
if (error) {
console.error('Error fetching locations:', error)
return NextResponse.json(
{ error: error.message },
{ status: 500 }
)
}
return NextResponse.json({
success: true,
locations
})
} catch (error) {
console.error('Business hours GET error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}

18
push.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
echo "🔑 Setting up SSH agent for GitHub push..."
# Kill any existing SSH agents
pkill ssh-agent 2>/dev/null
# Start new SSH agent
eval "$(ssh-agent -s)"
# Add the GitHub SSH key
ssh-add ~/.ssh/id_github
# Push to GitHub
echo "🚀 Pushing to GitHub..."
git push origin main
echo "✅ Push completed successfully!"

698
ralphy.sh Executable file
View File

@@ -0,0 +1,698 @@
#!/usr/bin/env bash
# ============================================
# Ralphy - Autonomous AI Coding Loop
# Supports Claude Code, OpenCode, Codex, Cursor, Qwen-Code and Factory Droid
# Runs until PRD is complete
# ============================================
set -euo pipefail
# ============================================
# CONFIGURATION & DEFAULTS
# ============================================
VERSION="4.0.0"
# Ralphy config directory
RALPHY_DIR=".ralphy"
PROGRESS_FILE="$RALPHY_DIR/progress.txt"
CONFIG_FILE="$RALPHY_DIR/config.yaml"
SINGLE_TASK=""
INIT_MODE=false
SHOW_CONFIG=false
ADD_RULE=""
AUTO_COMMIT=true
# Runtime options
SKIP_TESTS=false
SKIP_LINT=false
AI_ENGINE="claude" # claude, opencode, cursor, codex, qwen, or droid
DRY_RUN=false
MAX_ITERATIONS=0 # 0 = unlimited
MAX_RETRIES=3
RETRY_DELAY=5
VERBOSE=false
# Git branch options
BRANCH_PER_TASK=false
CREATE_PR=false
BASE_BRANCH=""
PR_DRAFT=false
# Parallel execution
PARALLEL=false
MAX_PARALLEL=3
# PRD source options
PRD_SOURCE="markdown" # markdown, yaml, github
PRD_FILE="PRD.md"
GITHUB_REPO=""
GITHUB_LABEL=""
# Colors (detect if terminal supports colors)
if [[ -t 1 ]] && command -v tput &>/dev/null && [[ $(tput colors 2>/dev/null || echo 0) -ge 8 ]]; then
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
BOLD=$(tput bold)
DIM=$(tput dim)
RESET=$(tput sgr0)
else
RED="" GREEN="" YELLOW="" BLUE="" MAGENTA="" CYAN="" BOLD="" DIM="" RESET=""
fi
# Global state
ai_pid=""
monitor_pid=""
tmpfile=""
CODEX_LAST_MESSAGE_FILE=""
current_step="Thinking"
total_input_tokens=0
total_output_tokens=0
total_actual_cost="0" # OpenCode provides actual cost
total_duration_ms=0 # Cursor provides duration
iteration=0
retry_count=0
declare -a parallel_pids=()
declare -a task_branches=()
declare -a integration_branches=() # Track integration branches for cleanup on interrupt
WORKTREE_BASE="" # Base directory for parallel agent worktrees
ORIGINAL_DIR="" # Original working directory (for worktree operations)
ORIGINAL_BASE_BRANCH="" # Original base branch before integration branches
# ============================================
# UTILITY FUNCTIONS
# ============================================
log_info() {
echo "${BLUE}[INFO]${RESET} $*"
}
log_success() {
echo "${GREEN}[OK]${RESET} $*"
}
log_warn() {
echo "${YELLOW}[WARN]${RESET} $*"
}
log_error() {
echo "${RED}[ERROR]${RESET} $*" >&2
}
log_debug() {
if [[ "$VERBOSE" == true ]]; then
echo "${DIM}[DEBUG] $*${RESET}"
fi
}
# Slugify text for branch names
slugify() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-|-$//g' | cut -c1-50
}
# ============================================
# BROWNFIELD MODE (.ralphy/ configuration)
# ============================================
# Initialize .ralphy/ directory with config files
init_ralphy_config() {
if [[ -d "$RALPHY_DIR" ]]; then
log_warn "$RALPHY_DIR already exists"
REPLY='N' # Default if read times out or fails
read -p "Overwrite config? [y/N] " -n 1 -r -t 30 2>/dev/null || true
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 0
fi
mkdir -p "$RALPHY_DIR"
# Smart detection
local project_name=""
local lang=""
local framework=""
local test_cmd=""
local lint_cmd=""
local build_cmd=""
# Get project name from directory or package.json
project_name=$(basename "$PWD")
if [[ -f "package.json" ]]; then
# Get name from package.json if available
local pkg_name
pkg_name=$(jq -r '.name // ""' package.json 2>/dev/null)
[[ -n "$pkg_name" ]] && project_name="$pkg_name"
# Detect language
if [[ -f "tsconfig.json" ]]; then
lang="TypeScript"
else
lang="JavaScript"
fi
# Detect frameworks from dependencies (collect all matches)
local deps frameworks=()
deps=$(jq -r '(.dependencies // {}) + (.devDependencies // {}) | keys[]' package.json 2>/dev/null || true)
# Use grep for reliable exact matching
echo "$deps" | grep -qx "next" && frameworks+=("Next.js")
echo "$deps" | grep -qx "nuxt" && frameworks+=("Nuxt")
echo "$deps" | grep -qx "@remix-run/react" && frameworks+=("Remix")
echo "$deps" | grep -qx "svelte" && frameworks+=("Svelte")
echo "$deps" | grep -qE "@nestjs/" && frameworks+=("NestJS")
echo "$deps" | grep -qx "hono" && frameworks+=("Hono")
echo "$deps" | grep -qx "fastify" && frameworks+=("Fastify")
echo "$deps" | grep -qx "express" && frameworks+=("Express")
# Only add React/Vue if no meta-framework detected
if [[ ${#frameworks[@]} -eq 0 ]]; then
echo "$deps" | grep -qx "react" && frameworks+=("React")
echo "$deps" | grep -qx "vue" && frameworks+=("Vue")
fi
# Join frameworks with comma
framework=$(IFS=', '; echo "${frameworks[*]}")
# Detect commands from package.json scripts
local scripts
scripts=$(jq -r '.scripts // {}' package.json 2>/dev/null)
# Test command (prefer bun if lockfile exists)
if echo "$scripts" | jq -e '.test' >/dev/null 2>&1; then
test_cmd="npm test"
[[ -f "bun.lockb" ]] && test_cmd="bun test"
fi
# Lint command
if echo "$scripts" | jq -e '.lint' >/dev/null 2>&1; then
lint_cmd="npm run lint"
fi
# Build command
if echo "$scripts" | jq -e '.build' >/dev/null 2>&1; then
build_cmd="npm run build"
fi
elif [[ -f "pyproject.toml" ]] || [[ -f "requirements.txt" ]] || [[ -f "setup.py" ]]; then
lang="Python"
local py_frameworks=()
local py_deps=""
[[ -f "pyproject.toml" ]] && py_deps=$(cat pyproject.toml 2>/dev/null)
[[ -f "requirements.txt" ]] && py_deps+=$(cat requirements.txt 2>/dev/null)
echo "$py_deps" | grep -qi "fastapi" && py_frameworks+=("FastAPI")
echo "$py_deps" | grep -qi "django" && py_frameworks+=("Django")
echo "$py_deps" | grep -qi "flask" && py_frameworks+=("Flask")
framework=$(IFS=', '; echo "${py_frameworks[*]}")
test_cmd="pytest"
lint_cmd="ruff check ."
elif [[ -f "go.mod" ]]; then
lang="Go"
test_cmd="go test ./..."
lint_cmd="golangci-lint run"
elif [[ -f "Cargo.toml" ]]; then
lang="Rust"
test_cmd="cargo test"
lint_cmd="cargo clippy"
build_cmd="cargo build"
fi
# Show what we detected
echo ""
echo "${BOLD}Detected:${RESET}"
echo " Project: ${CYAN}$project_name${RESET}"
[[ -n "$lang" ]] && echo " Language: ${CYAN}$lang${RESET}"
[[ -n "$framework" ]] && echo " Framework: ${CYAN}$framework${RESET}"
[[ -n "$test_cmd" ]] && echo " Test: ${CYAN}$test_cmd${RESET}"
[[ -n "$lint_cmd" ]] && echo " Lint: ${CYAN}$lint_cmd${RESET}"
[[ -n "$build_cmd" ]] && echo " Build: ${CYAN}$build_cmd${RESET}"
echo ""
# Escape values for safe YAML (double quotes inside strings)
yaml_escape() { printf '%s' "$1" | sed 's/"/\\"/g'; }
# Create config.yaml with detected values
cat > "$CONFIG_FILE" << EOF
# Ralphy Configuration
# https://github.com/michaelshimeles/ralphy
# Project info (auto-detected, edit if needed)
project:
name: "$(yaml_escape "$project_name")"
language: "$(yaml_escape "${lang:-Unknown}")"
framework: "$(yaml_escape "${framework:-}")"
description: "" # Add a brief description
# Commands (auto-detected from package.json/pyproject.toml)
commands:
test: "$(yaml_escape "${test_cmd:-}")"
lint: "$(yaml_escape "${lint_cmd:-}")"
build: "$(yaml_escape "${build_cmd:-}")"
# Rules - instructions the AI MUST follow
# These are injected into every prompt
rules: []
# Examples:
# - "Always use TypeScript strict mode"
# - "Follow the error handling pattern in src/utils/errors.ts"
# - "All API endpoints must have input validation with Zod"
# - "Use server actions instead of API routes in Next.js"
# Boundaries - files/folders the AI should not modify
boundaries:
never_touch: []
# Examples:
# - "src/legacy/**"
# - "migrations/**"
# - "*.lock"
EOF
# Create progress.txt
echo "# Ralphy Progress Log" > "$PROGRESS_FILE"
echo "" >> "$PROGRESS_FILE"
log_success "Created $RALPHY_DIR/"
echo ""
echo " ${CYAN}$CONFIG_FILE${RESET} - Your rules and preferences"
echo " ${CYAN}$PROGRESS_FILE${RESET} - Progress log (auto-updated)"
echo ""
echo "${BOLD}Next steps:${RESET}"
echo " 1. Add rules: ${CYAN}ralphy --add-rule \"your rule here\"${RESET}"
echo " 2. Or edit: ${CYAN}$CONFIG_FILE${RESET}"
echo " 3. Run: ${CYAN}ralphy \"your task\"${RESET} or ${CYAN}ralphy${RESET} (with PRD.md)"
}
# Load rules from config.yaml
load_ralphy_rules() {
[[ ! -f "$CONFIG_FILE" ]] && return
if command -v yq &>/dev/null; then
yq -r '.rules // [] | .[]' "$CONFIG_FILE" 2>/dev/null || true
fi
}
# Load boundaries from config.yaml
load_ralphy_boundaries() {
local boundary_type="$1" # never_touch or always_test
[[ ! -f "$CONFIG_FILE" ]] && return
if command -v yq &>/dev/null; then
yq -r ".boundaries.$boundary_type // [] | .[]" "$CONFIG_FILE" 2>/dev/null || true
fi
}
# Show current config
show_ralphy_config() {
if [[ ! -f "$CONFIG_FILE" ]]; then
log_warn "No config found. Run 'ralphy --init' first."
exit 1
fi
echo ""
echo "${BOLD}Ralphy Configuration${RESET} ($CONFIG_FILE)"
echo ""
if command -v yq &>/dev/null; then
# Project info
local name lang framework desc
name=$(yq -r '.project.name // "Unknown"' "$CONFIG_FILE" 2>/dev/null)
lang=$(yq -r '.project.language // "Unknown"' "$CONFIG_FILE" 2>/dev/null)
framework=$(yq -r '.project.framework // ""' "$CONFIG_FILE" 2>/dev/null)
desc=$(yq -r '.project.description // ""' "$CONFIG_FILE" 2>/dev/null)
echo "${BOLD}Project:${RESET}"
echo " Name: $name"
echo " Language: $lang"
[[ -n "$framework" ]] && echo " Framework: $framework"
[[ -n "$desc" ]] && echo " About: $desc"
echo ""
# Commands
local test_cmd lint_cmd build_cmd
test_cmd=$(yq -r '.commands.test // ""' "$CONFIG_FILE" 2>/dev/null)
lint_cmd=$(yq -r '.commands.lint // ""' "$CONFIG_FILE" 2>/dev/null)
build_cmd=$(yq -r '.commands.build // ""' "$CONFIG_FILE" 2>/dev/null)
echo "${BOLD}Commands:${RESET}"
[[ -n "$test_cmd" ]] && echo " Test: $test_cmd" || echo " Test: ${DIM}(not set)${RESET}"
[[ -n "$lint_cmd" ]] && echo " Lint: $lint_cmd" || echo " Lint: ${DIM}(not set)${RESET}"
[[ -n "$build_cmd" ]] && echo " Build: $build_cmd" || echo " Build: ${DIM}(not set)${RESET}"
echo ""
# Rules
echo "${BOLD}Rules:${RESET}"
local rules
rules=$(yq -r '.rules // [] | .[]' "$CONFIG_FILE" 2>/dev/null)
if [[ -n "$rules" ]]; then
echo "$rules" | while read -r rule; do
echo "$rule"
done
else
echo " ${DIM}(none - add with: ralphy --add-rule \"...\")${RESET}"
fi
echo ""
# Boundaries
local never_touch
never_touch=$(yq -r '.boundaries.never_touch // [] | .[]' "$CONFIG_FILE" 2>/dev/null)
if [[ -n "$never_touch" ]]; then
echo "${BOLD}Never Touch:${RESET}"
echo "$never_touch" | while read -r path; do
echo "$path"
done
echo ""
fi
else
# Fallback: just show the file
cat "$CONFIG_FILE"
fi
}
# Add a rule to config.yaml
add_ralphy_rule() {
local rule="$1"
if [[ ! -f "$CONFIG_FILE" ]]; then
log_error "No config found. Run 'ralphy --init' first."
exit 1
fi
if ! command -v yq &>/dev/null; then
log_error "yq is required to add rules. Install from https://github.com/mikefarah/yq"
log_info "Or manually edit $CONFIG_FILE"
exit 1
fi
# Add rule to the rules array (use env var to avoid YAML injection)
RULE="$rule" yq -i '.rules += [env(RULE)]' "$CONFIG_FILE"
log_success "Added rule: $rule"
}
# Load test command from config
load_test_command() {
[[ ! -f "$CONFIG_FILE" ]] && echo "" && return
if command -v yq &>/dev/null; then
yq -r '.commands.test // ""' "$CONFIG_FILE" 2>/dev/null || echo ""
else
echo ""
fi
}
# Load project context from config.yaml
load_project_context() {
[[ ! -f "$CONFIG_FILE" ]] && return
if command -v yq &>/dev/null; then
local name lang framework desc
name=$(yq -r '.project.name // ""' "$CONFIG_FILE" 2>/dev/null)
lang=$(yq -r '.project.language // ""' "$CONFIG_FILE" 2>/dev/null)
framework=$(yq -r '.project.framework // ""' "$CONFIG_FILE" 2>/dev/null)
desc=$(yq -r '.project.description // ""' "$CONFIG_FILE" 2>/dev/null)
local context=""
[[ -n "$name" ]] && context+="Project: $name\n"
[[ -n "$lang" ]] && context+="Language: $lang\n"
[[ -n "$framework" ]] && context+="Framework: $framework\n"
[[ -n "$desc" ]] && context+="Description: $desc\n"
echo -e "$context"
fi
}
# Log task to progress file
log_task_history() {
local task="$1"
local status="$2" # completed, failed
[[ ! -f "$PROGRESS_FILE" ]] && return
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M')
local icon="✓"
[[ "$status" == "failed" ]] && icon="✗"
echo "- [$icon] $timestamp - $task" >> "$PROGRESS_FILE"
}
# Build prompt with brownfield context
build_brownfield_prompt() {
local task="$1"
local prompt=""
# Add project context if available
local context
context=$(load_project_context)
if [[ -n "$context" ]]; then
prompt+="## Project Context
$context
"
fi
# Add rules if available
local rules
rules=$(load_ralphy_rules)
if [[ -n "$rules" ]]; then
prompt+="## Rules (you MUST follow these)
$rules
"
fi
# Add boundaries
local never_touch
never_touch=$(load_ralphy_boundaries "never_touch")
if [[ -n "$never_touch" ]]; then
prompt+="## Boundaries
Do NOT modify these files/directories:
$never_touch
"
fi
# Add the task
prompt+="## Task
$task
## Instructions
1. Implement the task described above
2. Write tests if appropriate
3. Ensure the code works correctly"
# Add commit instruction only if auto-commit is enabled
if [[ "$AUTO_COMMIT" == "true" ]]; then
prompt+="
4. Commit your changes with a descriptive message"
fi
prompt+="
Keep changes focused and minimal. Do not refactor unrelated code."
echo "$prompt"
}
# Run a single brownfield task
run_brownfield_task() {
local task="$1"
echo ""
echo "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo "${BOLD}Task:${RESET} $task"
echo "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo ""
local prompt
prompt=$(build_brownfield_prompt "$task")
# Create temp file for output
local output_file
output_file=$(mktemp)
log_info "Running with $AI_ENGINE..."
# Run the AI engine (tee to show output while saving for parsing)
case "$AI_ENGINE" in
claude)
claude --dangerously-skip-permissions \
-p "$prompt" 2>&1 | tee "$output_file"
;;
opencode)
opencode --output-format stream-json \
--approval-mode full-auto \
"$prompt" 2>&1 | tee "$output_file"
;;
cursor)
agent --dangerously-skip-permissions \
-p "$prompt" 2>&1 | tee "$output_file"
;;
qwen)
qwen --output-format stream-json \
--approval-mode yolo \
-p "$prompt" 2>&1 | tee "$output_file"
;;
droid)
droid exec --output-format stream-json \
--auto medium \
"$prompt" 2>&1 | tee "$output_file"
;;
codex)
codex exec --full-auto \
--json \
"$prompt" 2>&1 | tee "$output_file"
;;
esac
local exit_code=$?
# Log to history
if [[ $exit_code -eq 0 ]]; then
log_task_history "$task" "completed"
log_success "Task completed"
else
log_task_history "$task" "failed"
log_error "Task failed"
fi
rm -f "$output_file"
return $exit_code
}
# ============================================
# HELP & VERSION
# ============================================
show_help() {
cat << EOF
${BOLD}Ralphy${RESET} - Autonomous AI Coding Loop (v${VERSION})
${BOLD}USAGE:${RESET}
./ralphy.sh [options] # PRD mode (requires PRD.md)
./ralphy.sh "task description" # Single task mode (brownfield)
./ralphy.sh --init # Initialize .ralphy/ config
${BOLD}CONFIG & SETUP:${RESET}
--init Initialize .ralphy/ with smart defaults
--config Show current configuration
--add-rule "..." Add a rule to config (e.g., "Always use Zod")
${BOLD}SINGLE TASK MODE:${RESET}
"task description" Run a single task without PRD (quotes required)
--no-commit Don't auto-commit after task completion
${BOLD}AI ENGINE OPTIONS:${RESET}
--claude Use Claude Code (default)
--opencode Use OpenCode
--cursor Use Cursor agent
--codex Use Codex CLI
--qwen Use Qwen-Code
--droid Use Factory Droid
${BOLD}WORKFLOW OPTIONS:${RESET}
--no-tests Skip writing and running tests
--no-lint Skip linting
--fast Skip both tests and linting
${BOLD}EXECUTION OPTIONS:${RESET}
--max-iterations N Stop after N iterations (0 = unlimited)
--max-retries N Max retries per task on failure (default: 3)
--retry-delay N Seconds between retries (default: 5)
--dry-run Show what would be done without executing
${BOLD}PARALLEL EXECUTION:${RESET}
--parallel Run independent tasks in parallel
--max-parallel N Max concurrent tasks (default: 3)
${BOLD}GIT BRANCH OPTIONS:${RESET}
--branch-per-task Create a new git branch for each task
--base-branch NAME Base branch to create task branches from (default: current)
--create-pr Create a pull request after each task (requires gh CLI)
--draft-pr Create PRs as drafts
${BOLD}PRD SOURCE OPTIONS:${RESET}
--prd FILE PRD file path (default: PRD.md)
--yaml FILE Use YAML task file instead of markdown
--github REPO Fetch tasks from GitHub issues (e.g., owner/repo)
--github-label TAG Filter GitHub issues by label
${BOLD}OTHER OPTIONS:${RESET}
-v, --verbose Show debug output
-h, --help Show this help
--version Show version number
${BOLD}EXAMPLES:${RESET}
# Brownfield mode (single tasks in existing projects)
./ralphy.sh --init # Initialize config
./ralphy.sh "add dark mode toggle" # Run single task
./ralphy.sh "fix the login bug" --cursor # Single task with Cursor
# PRD mode (task lists)
./ralphy.sh # Run with Claude Code
./ralphy.sh --codex # Run with Codex CLI
./ralphy.sh --branch-per-task --create-pr # Feature branch workflow
./ralphy.sh --parallel --max-parallel 4 # Run 4 tasks concurrently
./ralphy.sh --yaml tasks.yaml # Use YAML task file
./ralphy.sh --github owner/repo # Fetch from GitHub issues
${BOLD}PRD FORMATS:${RESET}
Markdown (PRD.md):
- [ ] Task description
YAML (tasks.yaml):
tasks:
- title: Task description
completed: false
parallel_group: 1 # Optional: tasks with same group run in parallel
GitHub Issues:
Uses open issues from the specified repository
EOF
}
show_version() {
echo "Ralphy v${VERSION}"
}
# ============================================
# ARGUMENT PARSING
# ============================================
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--no-tests|--skip-tests)
SKIP_TESTS=true
shift
;;
--no-lint|--skip-lint)
SKIP_LINT=true
shift
;;
--fast)
SKIP_TESTS=true
SKIP_LINT=true
shift
;;
--opencode)
AI_ENGINE="opencode"
shift
;;
--claude)
AI_ENGINE="claude"
shift
;;
--cursor|--agent)
AI_ENGINE="cursor"
shift
;;
--codex)
AI_ENGINE="codex"
shift
;;
--qwen)

View File

@@ -0,0 +1,44 @@
-- ============================================
-- FIX: Actualizar TODOS los horarios de negocio incorrectos
-- Date: 20260119
-- Description: Fix all locations with incorrect business hours (22:00-23:00)
-- ============================================
-- Verificar horarios actuales antes de la corrección
SELECT id, name, business_hours FROM locations;
-- Actualizar TODOS los horarios incorrectos (incluyendo 22:00-23:00)
UPDATE locations
SET business_hours = '{
"monday": {"open": "10:00", "close": "19:00", "is_closed": false},
"tuesday": {"open": "10:00", "close": "19:00", "is_closed": false},
"wednesday": {"open": "10:00", "close": "19:00", "is_closed": false},
"thursday": {"open": "10:00", "close": "19:00", "is_closed": false},
"friday": {"open": "10:00", "close": "19:00", "is_closed": false},
"saturday": {"open": "10:00", "close": "18:00", "is_closed": false},
"sunday": {"is_closed": true}
}'::jsonb
WHERE
-- Horarios que contienen 22:00 (hora incorrecta)
business_hours::text LIKE '%"22:00"%' OR
-- Horarios que contienen 23:00 (hora incorrecta)
business_hours::text LIKE '%"23:00"%' OR
-- Horarios completamente vacíos o con datos incorrectos
business_hours IS NULL OR
business_hours = '{}'::jsonb OR
-- Horarios que no tienen la estructura correcta
jsonb_typeof(business_hours) != 'object';
-- Verificar que los horarios se actualizaron correctamente
SELECT id, name, business_hours FROM locations;
-- Log para confirmar la corrección
DO $$
DECLARE
updated_count INTEGER;
BEGIN
SELECT COUNT(*) INTO updated_count FROM locations
WHERE business_hours::text LIKE '%"10:00"%';
RAISE NOTICE 'Updated % locations with correct business hours (10:00-19:00)', updated_count;
END $$;