Snippets Collections
import tkinter as tk
from tkinter import ttk

root = tk.Tk()

root.geometry('200x200')



progress_bar = ttk.Progressbar(root, length=100, value=2)
progress_bar.pack()


def test_func():
    for i, n in enumerate([1000, 2000, 500], start=1):
        for j in range(n):
            print(j)
        progress_bar.config({'value': (i/3) * 100})
        progress_bar.update()

test_func()
root.mainloop()
@misc{tongyidr,
  author={Tongyi DeepResearch Team},
  title={Tongyi-DeepResearch},
  year={2025},
  howpublished={\url{https://github.com/Alibaba-NLP/DeepResearch}}
}
Reservation_id = 5971686000063835007;
access_token_response = invokeurl
[
	url :"https://www.zohoapis.com/crm/v6/settings/variables/5971686000102746225"
	type :GET
	connection:"newzohocrm"
];
access_token = access_token_response.get("variables").get(0).get("value");
//info access_token;
// Prepare request headers for DocuSign API
headers = Map();
headers.put("Authorization","Bearer " + access_token);
headers.put("Content-Type","application/json");
// Envelope ID to track
envelopeId = "ba06cba1-ac8e-4c7d-a225-050b354e6c89";
// Fetch envelope status from DocuSign
status_resp = invokeurl
[
	url :"https://eu.docusign.net/restapi/v2.1/accounts/2a0daa7d-a770-4979-8208-9543d21f12e5/envelopes/" + envelopeId
	type :GET
	headers:headers
];
//info status_resp;
if(status_resp.get("status") == "completed")
{

	pdf_binary = invokeurl
	[
		url :"https://eu.docusign.net/restapi/v2.1/accounts/2a0daa7d-a770-4979-8208-9543d21f12e5/envelopes/" + envelopeId + "/documents/1"
		type :GET
		headers:headers
	];
	//	info pdf_binary;
	pdf_binary.setParamName("file");
	response = invokeurl
	[
	url :"https://www.zohoapis.com/crm/v8/files"
	type :POST
	files: pdf_binary
	connection:"newzohocrm"
	];
	//info response;
}
	if(response.get("data") != null && response.get("data").size() > 0)
	{
		fileId = response.get("data").get(0).get("details").get("id");

		// Prepare file upload field value
		fileMap = Map();
		fileMap.put("file_id", fileId);
		fileList = List();
		fileList.add(fileMap);

		updateMap = Map();
		updateMap.put("Customer_Signed_Document", fileList);
		// Update Reservation record with uploaded file
		updateResp = zoho.crm.updateRecord("Deals", Reservation_id, updateMap);
		info "Update response: " +updateResp;
	}
	else
	{
		info "File upload failed. Response: " + response.toString();
	}
	
void Creation_of_file_Zoho_wd_Files_on_Crm_Unit(string res_id, string P_Folder_ID, String WD_File_name)
{
info WD_File_name;
///////
////////
remove_dot = WD_File_name.lastIndexOf(".");
if(remove_dot != -1)
{
	file_name_without_ext = WD_File_name.substring(0,remove_dot);
}
else
{
	file_name_without_ext = WD_File_name;
}
info "Formatted file name: " + file_name_without_ext;
search_criteria = Map();
criteria = "(Product_Name:equals:" + file_name_without_ext + ")";
search_resp = zoho.crm.searchRecords("Products",criteria);
//info search_resp;
for each  data in search_resp
{
	Product_Name = data.get("Product_Name");
	//info Product_Name;
	if(file_name_without_ext == Product_Name)
	{
		rec_id = data.get("id");
		info rec_id;
	}
}
/////////
////////////////
///////
/////////////
///////////////
///////////
attribute = Map();
attribute.put("resource_id",res_id);
attribute.put("allow_download",true);
attribute.put("request_user_data",false);
attribute.put("link_name",file_name_without_ext);
attributeMap = Map();
attributeMap.put("attributes",attribute);
attributeMap.put("type","links");
param = Map();
param.put("data",attributeMap);
paramString = param.toString();
mp = Map();
mp.put("Accept","application/vnd.api+json");
makeExternalLink = invokeurl
[
	url :"https://workdrive.zoho.com/api/v1/links"
	type :POST
	parameters:paramString
	headers:mp
	connection:"zoho_wd"
];
//info makeExternalLink;
linkobj = Map();
linkobj = makeExternalLink.get("data");
downloadlink = "";
if(linkobj != null)
{
	constructURl = linkobj.get("attributes").get("download_url");
	downloadlink = constructURl + "?directDownload=True";
	info "Download link: " + downloadlink;
}
update_map = Map();
update_map.put("Unit_Plan_SPA_URL",downloadlink);
update_Rec = zoho.crm.updateRecord("Products",rec_id,update_map);
info "Unit update resp: " + update_Rec;
}
At Hivelance, we deliver robust cryptocurrency exchange scripts tailored to your business goals and technical requirements. Our team of blockchain developers, cybersecurity specialists, and fintech experts ensures that every exchange we build is secure, scalable, and user-friendly. With advanced features like multi-currency wallets, real-time trading, and regulatory compliance, our scripts are designed to help you launch a profitable exchange platform with low investment and high efficiency.

Know More:

🌐 Visit Us: https://www.hivelance.com/cryptocurrency-exchange-script

📞 Call/WhatsApp: +918438595928, +971505249877

📲 Telegram: @Hivelance

📧 Email: marketing@hivelance.com

💬 Skype: live:.cid.8e890e9d0810f62c?chat

🌐 Get Free Demo: https://www.hivelance.com/contact-us
#!/bin/bash

# Colores para la salida
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Funciones de mensajes
error() { echo -e "${RED}Error: $1${NC}" >&2; }
success() { echo -e "${GREEN}$1${NC}"; }
info() { echo -e "${BLUE}$1${NC}"; }
warning() { echo -e "${YELLOW}$1${NC}" >&2; }
process() { echo -e "${CYAN}$1${NC}"; }

# Variables globales
DOCKER_DIR="docker"
PROJECT_NAME=""
FRAMEWORK=""
PHP_VERSION=""
WEB_PORT=""
DB_PORT=""
CURRENT_DIR=$(pwd)

# Función para verificar y corregir permisos
check_and_fix_permissions() {
    local target_dir="$1"
    
    # Verificar si el directorio existe
    if [ ! -d "$target_dir" ]; then
        return 0
    fi
    
    process "Verificando permisos de $target_dir..."
    
    # Verificar si tenemos permisos de escritura
    if [ ! -w "$target_dir" ]; then
        warning "No tenemos permisos de escritura en $target_dir"
        process "Intentando corregir permisos..."
        
        # Intentar con sudo si está disponible
        if command -v sudo &> /dev/null; then
            if sudo chmod 755 "$target_dir" && sudo chown "$USER:$USER" "$target_dir" 2>/dev/null; then
                success "Permisos corregidos con sudo"
                return 0
            fi
        fi
        
        # Intentar sin sudo
        if chmod 755 "$target_dir" 2>/dev/null; then
            success "Permisos corregidos"
        else
            error "No se pueden corregir los permisos automáticamente"
            info "Por favor, ejecuta manualmente:"
            echo "  sudo chmod 755 \"$target_dir\""
            echo "  sudo chown \$USER:\$USER \"$target_dir\""
            return 1
        fi
    else
        success "Permisos correctos en $target_dir"
    fi
    
    return 0
}

# Función para limpiar directorio de forma segura
safe_clean_directory() {
    local dir_path="$1"
    
    if [ ! -d "$dir_path" ]; then
        return 0
    fi
    
    process "Limpiando directorio $dir_path..."
    
    # Verificar permisos primero
    if ! check_and_fix_permissions "$dir_path"; then
        return 1
    fi
    
    # Intentar eliminar contenido del directorio
    if [ -w "$dir_path" ]; then
        # Usar find para eliminar contenido de forma segura
        if find "$dir_path" -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null; then
            success "Directorio limpiado correctamente"
            return 0
        else
            # Si falla, intentar con sudo
            if command -v sudo &> /dev/null; then
                if sudo rm -rf "${dir_path:?}/"* 2>/dev/null; then
                    success "Directorio limpiado con sudo"
                    return 0
                fi
            fi
        fi
    fi
    
    error "No se pudo limpiar el directorio $dir_path"
    return 1
}

# Verificar instalación de Docker y Docker Compose
check_docker_installation() {
    process "Verificando instalación de Docker..."
    if ! command -v docker &> /dev/null; then
        error "Docker no está instalado. Instala Docker primero."
        echo "Visita: https://docs.docker.com/get-docker/"
        exit 1
    fi
    success "Docker está instalado."

    process "Verificando Docker Compose..."
    if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
        error "Docker Compose no está instalado."
        echo "Visita: https://docs.docker.com/compose/install/"
        exit 1
    fi
    success "Docker Compose está instalado."
}

# Verificar permisos de Docker
check_docker_permissions() {
    process "Verificando permisos de Docker..."
    if ! docker info &> /dev/null; then
        error "No tienes permisos para acceder a Docker."
        warning "Solución:"
        echo "  sudo usermod -aG docker \$USER"
        echo "  newgrp docker"
        exit 1
    fi
    success "Permisos de Docker verificados."
}

# Verificar conexión a internet
check_internet_connection() {
    process "Verificando conexión a internet..."
    if ! curl -s --connect-timeout 10 https://packagist.org > /dev/null; then
        error "No hay conexión a internet o Packagist no está disponible"
        warning "El script requiere conexión a internet para descargar dependencias"
        read -p "¿Continuar de todos modos? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            exit 1
        fi
    else
        success "Conexión a internet verificada"
    fi
}

# Encontrar puertos disponibles
find_available_ports() {
    local web_port=8081
    local db_port=5433
    
    # Encontrar puerto web disponible
    while ss -tuln 2>/dev/null | grep -q ":${web_port} "; do
        web_port=$((web_port + 1))
    done
    
    # Encontrar puerto DB disponible (empezando desde 5433)
    while ss -tuln 2>/dev/null | grep -q ":${db_port} "; do
        db_port=$((db_port + 1))
    done
    
    WEB_PORT="$web_port"
    DB_PORT="$db_port"
    success "Puertos disponibles encontrados: Web → ${WEB_PORT}, DB → ${DB_PORT}"
}

# Seleccionar framework CON VERSIONES CORRECTAS
select_framework() {
    echo ""
    info "🎯 SELECCIÓN DE FRAMEWORK"
    echo "========================="
    echo ""
    echo "  1) Yii2 Basic - Framework tradicional (PHP 7.4)"
    echo "  2) Yii2 Advanced - Framework avanzado (PHP 7.4)"
    echo "  3) Yii3 - Framework moderno (PHP 8.4+)"  
    echo "  4) Laravel - Framework elegante (PHP 8.3+)"
    echo ""
    
    while true; do
        read -p "Selecciona el framework (1-4): " choice
        case $choice in
            1) 
                FRAMEWORK="yii2-basic"
                PHP_VERSION="7.4"
                success "Seleccionado: Yii2 Basic con PHP 7.4"
                break
                ;;
            2) 
                FRAMEWORK="yii2-advanced"
                PHP_VERSION="7.4"
                success "Seleccionado: Yii2 Advanced con PHP 7.4"
                break
                ;;
            3) 
                FRAMEWORK="yii3"
                PHP_VERSION="8.4"
                success "Seleccionado: Yii3 con PHP 8.4"
                break
                ;;
            4) 
                FRAMEWORK="laravel"
                PHP_VERSION="8.3"
                success "Seleccionado: Laravel con PHP 8.3"
                break
                ;;
            *) 
                error "Opción inválida. Por favor, selecciona 1, 2, 3 o 4"
                ;;
        esac
    done
}

# Validar nombre del proyecto
get_project_name() {
    echo ""
    info "📝 NOMBRE DEL PROYECTO"
    echo "======================"
    echo "Elige un nombre para tu proyecto:"
    echo "  - Debe comenzar con una letra"
    echo "  - Puede contener letras, números, guiones y guiones bajos"
    echo ""
    
    while true; do
        read -p "Ingresa el nombre del proyecto: " project_name
        
        if [ -z "$project_name" ]; then
            error "El nombre no puede estar vacío."
            continue
        fi
        
        if [[ ! "$project_name" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]; then
            error "El nombre debe comenzar con una letra y solo puede contener letras, números, guiones y guiones bajos."
            continue
        fi
        
        PROJECT_NAME="$project_name"
        success "Nombre del proyecto validado: $PROJECT_NAME"
        break
    done
}

# Crear estructura de directorios MEJORADA con gestión de permisos
create_directory_structure() {
    process "Creando estructura de directorios en '$DOCKER_DIR'..."
    
    # Verificar y corregir permisos del directorio docker si existe
    if [ -d "$DOCKER_DIR" ]; then
        warning "El directorio $DOCKER_DIR ya existe. Verificando permisos..."
        
        if ! check_and_fix_permissions "$DOCKER_DIR"; then
            error "No se pueden corregir los permisos de $DOCKER_DIR"
            return 1
        fi
        
        # Verificar y corregir permisos de subdirectorios
        if [ -d "$DOCKER_DIR/src" ]; then
            if ! check_and_fix_permissions "$DOCKER_DIR/src"; then
                error "No se pueden corregir los permisos de $DOCKER_DIR/src"
                return 1
            fi
            
            # Limpiar el directorio src de forma segura
            if ! safe_clean_directory "$DOCKER_DIR/src"; then
                error "No se pudo limpiar el directorio $DOCKER_DIR/src"
                return 1
            fi
        else
            # Crear directorio src con permisos correctos
            if ! mkdir -p "$DOCKER_DIR/src"; then
                error "No se pudo crear el directorio $DOCKER_DIR/src"
                return 1
            fi
            chmod 755 "$DOCKER_DIR/src"
        fi
    else
        # Crear toda la estructura desde cero
        if ! mkdir -p "$DOCKER_DIR/src" "$DOCKER_DIR/apache-logs" "$DOCKER_DIR/postgres-backups"; then
            error "No se pudo crear la estructura de directorios"
            return 1
        fi
        # Establecer permisos correctos
        chmod 755 "$DOCKER_DIR" "$DOCKER_DIR/src" "$DOCKER_DIR/apache-logs" "$DOCKER_DIR/postgres-backups"
        success "Estructura de directorios creada en: $DOCKER_DIR/"
    fi
    
    # Crear subcarpeta con nombre del proyecto dentro de src
    process "Creando directorio del proyecto: $DOCKER_DIR/src/$PROJECT_NAME"
    if ! mkdir -p "$DOCKER_DIR/src/$PROJECT_NAME"; then
        error "No se pudo crear la subcarpeta del proyecto"
        return 1
    fi
    
    # Establecer permisos correctos para la carpeta del proyecto
    if ! chmod 755 "$DOCKER_DIR/src/$PROJECT_NAME"; then
        warning "No se pudieron establecer los permisos automáticamente en $DOCKER_DIR/src/$PROJECT_NAME"
        info "Puedes establecerlos manualmente después:"
        echo "  chmod 755 \"$DOCKER_DIR/src/$PROJECT_NAME\""
    fi
    
    success "Estructura de directorios creada: $DOCKER_DIR/src/$PROJECT_NAME/"
    return 0
}

# Crear archivo .env
create_env_file() {
    process "Creando archivo de configuración .env..."
    
    find_available_ports
    
    cat > "$DOCKER_DIR/.env" << EOF
# Configuración de la aplicación
APP_NAME=$PROJECT_NAME
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost:${WEB_PORT}

# Configuración de base de datos
DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432  # Puerto INTERNO del contenedor (SIEMPRE 5432)
DB_DATABASE=${PROJECT_NAME}_db
DB_USERNAME=postgres
DB_PASSWORD=password

# Configuración de PostgreSQL
POSTGRES_DB=${PROJECT_NAME}_db
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password

# Configuración de Docker
PHP_VERSION=${PHP_VERSION}
WEB_PORT=${WEB_PORT}
DB_EXTERNAL_PORT=${DB_PORT}  # Puerto EXPUESTO en el host

# Configuración específica del framework
FRAMEWORK=${FRAMEWORK}
PROJECT_NAME=${PROJECT_NAME}
EOF

    # Verificar que el archivo se creó y establecer permisos
    if [ ! -f "$DOCKER_DIR/.env" ]; then
        error "No se pudo crear el archivo .env"
        return 1
    fi
    
    chmod 644 "$DOCKER_DIR/.env"
    success "Archivo .env creado con puertos: Web → ${WEB_PORT}, DB Host → ${DB_PORT}"
    return 0
}

# Crear configuración de Apache
create_apache_config() {
    process "Creando configuración de Apache..."
    
    # Configuración diferente para Yii2 Advanced
    if [ "$FRAMEWORK" = "yii2-advanced" ]; then
        cat > "$DOCKER_DIR/000-default.conf" << EOF
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/frontend/web
    <Directory /var/www/html/frontend/web>
        AllowOverride All
        Require all granted
        Options Indexes FollowSymLinks
    </Directory>
    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
    else
        cat > "$DOCKER_DIR/000-default.conf" << EOF
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/public
    <Directory /var/www/html>
        AllowOverride All
        Require all granted
        Options Indexes FollowSymLinks
    </Directory>
    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
    fi

    if [ ! -f "$DOCKER_DIR/000-default.conf" ]; then
        error "No se pudo crear la configuración de Apache"
        return 1
    fi
    
    chmod 644 "$DOCKER_DIR/000-default.conf"
    success "Configuración de Apache creada"
    return 0
}

# Crear Dockerfile específico para cada framework - CORREGIDO
create_dockerfile() {
    process "Creando Dockerfile para PHP $PHP_VERSION..."
    
    case "$FRAMEWORK" in
        "yii2-basic"|"yii2-advanced")
            create_yii2_dockerfile
            ;;
        "yii3")
            create_yii3_dockerfile
            ;;
        "laravel")
            create_laravel_dockerfile
            ;;
    esac
    
    if [ ! -f "$DOCKER_DIR/Dockerfile" ]; then
        error "No se pudo crear el Dockerfile"
        return 1
    fi
    
    chmod 644 "$DOCKER_DIR/Dockerfile"
    return 0
}

create_yii2_dockerfile() {
    cat > "$DOCKER_DIR/Dockerfile" << 'EOF'
ARG PHP_VERSION=7.4
FROM php:${PHP_VERSION}-apache

# Actualizar lista de paquetes y instalar dependencias
RUN apt-get update && apt-get install -y \
    libpq-dev \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    zip \
    unzip \
    git \
    curl \
    gnupg \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# Configurar extensiones de PHP para PHP 7.4 - CONFIGURACIÓN CORREGIDA
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) \
        pdo \
        pdo_pgsql \
        pgsql \
        zip \
        gd \
        bcmath \
        opcache \
    && a2enmod rewrite

# Instalar Composer
RUN curl -sS https://getcomposer.org/installer | php -- \
    --install-dir=/usr/local/bin \
    --filename=composer

# Configurar Composer para evitar timeouts
RUN composer config -g process-timeout 1200 && \
    composer config -g repo.packagist composer https://packagist.org

# Instalar extensiones adicionales necesarias para Yii2
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli

COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
RUN a2ensite 000-default.conf
RUN chown -R www-data:www-data /var/www/html
WORKDIR /var/www/html

# Configuraciones PHP optimizadas para PHP 7.4
RUN echo "memory_limit = 512M" > /usr/local/etc/php/conf.d/memory.ini && \
    echo "upload_max_filesize = 64M" >> /usr/local/etc/php/conf.d/uploads.ini && \
    echo "post_max_size = 64M" >> /usr/local/etc/php/conf.d/uploads.ini && \
    echo "max_execution_time = 300" >> /usr/local/etc/php/conf.d/timeouts.ini && \
    echo "max_input_time = 120" >> /usr/local/etc/php/conf.d/timeouts.ini

EXPOSE 80
EOF
    success "Dockerfile para Yii2 creado"
}

create_yii3_dockerfile() {
    cat > "$DOCKER_DIR/Dockerfile" << 'EOF'
ARG PHP_VERSION=8.4
FROM php:${PHP_VERSION}-apache

# Actualizar lista de paquetes y instalar dependencias
RUN apt-get update && apt-get install -y \
    libpq-dev \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    zip \
    unzip \
    git \
    curl \
    gnupg \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# Configurar extensiones de PHP - CONFIGURACIÓN CORREGIDA
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) \
        pdo \
        pdo_pgsql \
        pgsql \
        zip \
        gd \
        bcmath \
        opcache \
    && a2enmod rewrite

# Instalar Composer
RUN curl -sS https://getcomposer.org/installer | php -- \
    --install-dir=/usr/local/bin \
    --filename=composer

# Configurar Composer para evitar timeouts
RUN composer config -g process-timeout 1200 && \
    composer config -g repo.packagist composer https://packagist.org

COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
RUN a2ensite 000-default.conf
RUN chown -R www-data:www-data /var/www/html
WORKDIR /var/www/html

# Configuraciones PHP optimizadas
RUN echo "memory_limit = 512M" > /usr/local/etc/php/conf.d/memory.ini && \
    echo "upload_max_filesize = 128M" >> /usr/local/etc/php/conf.d/uploads.ini && \
    echo "post_max_size = 128M" >> /usr/local/etc/php/conf.d/uploads.ini && \
    echo "max_execution_time = 300" >> /usr/local/etc/php/conf.d/timeouts.ini && \
    echo "max_input_time = 120" >> /usr/local/etc/php/conf.d/timeouts.ini && \
    echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini && \
    echo "opcache.memory_consumption=256" >> /usr/local/etc/php/conf.d/opcache.ini

EXPOSE 80
EOF
    success "Dockerfile para Yii3 creado"
}

create_laravel_dockerfile() {
    cat > "$DOCKER_DIR/Dockerfile" << 'EOF'
ARG PHP_VERSION=8.3
FROM php:${PHP_VERSION}-apache

# Actualizar lista de paquetes y instalar dependencias
RUN apt-get update && apt-get install -y \
    libpq-dev \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    zip \
    unzip \
    git \
    curl \
    gnupg \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# Configurar extensiones de PHP - CONFIGURACIÓN CORREGIDA
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) \
        pdo \
        pdo_pgsql \
        pgsql \
        zip \
        gd \
        bcmath \
        opcache \
    && a2enmod rewrite

# Instalar Composer
RUN curl -sS https://getcomposer.org/installer | php -- \
    --install-dir=/usr/local/bin \
    --filename=composer

# Configurar Composer para evitar timeouts
RUN composer config -g process-timeout 1200 && \
    composer config -g repo.packagist composer https://packagist.org

# Extensiones adicionales para Laravel
RUN docker-php-ext-install exif && docker-php-ext-enable exif

COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
RUN a2ensite 000-default.conf
RUN chown -R www-data:www-data /var/www/html
WORKDIR /var/www/html

# Configuraciones PHP optimizadas
RUN echo "memory_limit = 512M" > /usr/local/etc/php/conf.d/memory.ini && \
    echo "upload_max_filesize = 128M" >> /usr/local/etc/php/conf.d/uploads.ini && \
    echo "post_max_size = 128M" >> /usr/local/etc/php/conf.d/uploads.ini && \
    echo "max_execution_time = 300" >> /usr/local/etc/php/conf.d/timeouts.ini && \
    echo "max_input_time = 120" >> /usr/local/etc/php/conf.d/timeouts.ini && \
    echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini

EXPOSE 80
EOF
    success "Dockerfile para Laravel creado"
}

# Crear docker-compose.yml MEJORADO
create_docker_compose() {
    process "Creando docker-compose.yml..."
    
    # Configurar volumen según el tipo de proyecto
    local volume_config="./src/${PROJECT_NAME}:/var/www/html"
    
    cat > "$DOCKER_DIR/docker-compose.yml" << EOF
version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        PHP_VERSION: \${PHP_VERSION}
    ports:
      - "\${WEB_PORT}:80"
    volumes:
      - ${volume_config}
      - ./apache-logs:/var/log/apache2
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend-network
    env_file:
      - .env
    container_name: ${PROJECT_NAME}-web
    restart: unless-stopped
    dns:
      - 8.8.8.8
      - 8.8.4.4
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    image: postgres:15
    environment:
      POSTGRES_DB: \${POSTGRES_DB}
      POSTGRES_USER: \${POSTGRES_USER}
      POSTGRES_PASSWORD: \${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./postgres-backups:/backups
    networks:
      - backend-network
    container_name: ${PROJECT_NAME}-db
    restart: unless-stopped
    ports:
      - "\${DB_EXTERNAL_PORT}:5432"
    dns:
      - 8.8.8.8
      - 8.8.4.4
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U \${POSTGRES_USER} -d \${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s

networks:
  backend-network:
    driver: bridge

volumes:
  pgdata:
    driver: local
EOF

    if [ ! -f "$DOCKER_DIR/docker-compose.yml" ]; then
        error "No se pudo crear el archivo docker-compose.yml"
        return 1
    fi
    
    chmod 644 "$DOCKER_DIR/docker-compose.yml"
    success "Archivo docker-compose.yml creado"
    return 0
}

# Función para ejecutar comandos en el directorio docker
run_in_docker_dir() {
    local cmd="$1"
    
    if [ ! -d "$DOCKER_DIR" ]; then
        error "Directorio $DOCKER_DIR no encontrado"
        return 1
    fi
    
    # Verificar permisos antes de continuar
    if ! check_and_fix_permissions "$DOCKER_DIR"; then
        error "No se puede acceder a $DOCKER_DIR por problemas de permisos"
        return 1
    fi
    
    cd "$DOCKER_DIR" || { error "No se puede acceder al directorio $DOCKER_DIR"; return 1; }
    eval "$cmd"
    local result=$?
    cd "$CURRENT_DIR" || return 1
    return $result
}

# Función MEJORADA para esperar a que PostgreSQL esté listo
wait_for_postgres() {
    process "Esperando a que PostgreSQL esté listo..."
    local max_attempts=30
    local attempt=1
    
    while [ $attempt -le $max_attempts ]; do
        if run_in_docker_dir "docker-compose exec -T db pg_isready -U postgres > /dev/null 2>&1"; then
            success "PostgreSQL está listo después de $attempt intentos"
            
            # Esperar un poco más para asegurar que esté completamente listo
            sleep 5
            
            # Verificar que la base de datos específica existe, si no crearla
            process "Verificando base de datos ${PROJECT_NAME}_db..."
            if ! run_in_docker_dir "docker-compose exec -T db psql -U postgres -d ${PROJECT_NAME}_db -c 'SELECT 1' > /dev/null 2>&1"; then
                process "Creando base de datos ${PROJECT_NAME}_db..."
                if run_in_docker_dir "docker-compose exec -T db createdb -U postgres ${PROJECT_NAME}_db"; then
                    success "Base de datos ${PROJECT_NAME}_db creada exitosamente"
                else
                    error "Error creando la base de datos ${PROJECT_NAME}_db"
                    return 1
                fi
            else
                success "Base de datos ${PROJECT_NAME}_db ya existe"
            fi
            
            sleep 2
            return 0
        fi
        
        if [ $attempt -eq 1 ]; then
            process "Esperando a que PostgreSQL se inicialice..."
        else
            process "Intento $attempt/$max_attempts - PostgreSQL aún no está listo..."
        fi
        
        sleep 3
        attempt=$((attempt + 1))
    done
    
    error "PostgreSQL no está respondiendo después de $max_attempts intentos"
    run_in_docker_dir 'docker-compose logs db'
    return 1
}

# Construir y levantar contenedores CON MEJOR MANEJO DE ERRORES
build_docker_containers() {
    process "Construyendo contenedores Docker..."
    
    if [ ! -d "$DOCKER_DIR" ]; then
        error "El directorio $DOCKER_DIR no existe. No se pueden construir los contenedores."
        return 1
    fi
    
    # Verificar permisos antes de continuar
    if ! check_and_fix_permissions "$DOCKER_DIR"; then
        error "No se pueden construir los contenedores por problemas de permisos"
        return 1
    fi
    
    # Parar contenedores existentes
    process "Deteniendo contenedores existentes..."
    if ! run_in_docker_dir 'docker-compose down 2>/dev/null'; then
        warning "No se pudieron detener contenedores existentes (puede ser normal si no hay contenedores)"
    fi
    
    # Construir imágenes con mejor manejo de errores
    process "Construyendo imágenes Docker..."
    
    # Primero intentar construir sin cache para detectar errores temprano
    if run_in_docker_dir "docker-compose build --no-cache --build-arg PHP_VERSION=${PHP_VERSION} 2>&1 | tee build.log"; then
        success "Imágenes construidas exitosamente sin cache"
    else
        error "Error construyendo las imágenes Docker sin cache"
        process "Analizando errores de construcción..."
        
        # Mostrar los últimos errores del log
        if [ -f "$DOCKER_DIR/build.log" ]; then
            error "Últimas líneas del log de construcción:"
            tail -20 "$DOCKER_DIR/build.log" | while read -r line; do
                echo "  $line"
            done
        fi
        
        # Intentar con cache como fallback
        warning "Intentando construcción con cache..."
        if ! run_in_docker_dir "docker-compose build --build-arg PHP_VERSION=${PHP_VERSION}"; then
            error "Error crítico en la construcción de imágenes Docker"
            return 1
        fi
    fi
    
    # Levantar contenedores
    process "Iniciando contenedores..."
    if ! run_in_docker_dir 'docker-compose up -d'; then
        error "Error iniciando contenedores"
        run_in_docker_dir 'docker-compose logs'
        return 1
    fi
    
    # Esperar a que PostgreSQL esté listo
    if ! wait_for_postgres; then
        error "La base de datos no se inicializó correctamente"
        return 1
    fi
    
    # Verificar estado de los contenedores
    process "Verificando estado de los contenedores..."
    if run_in_docker_dir 'docker-compose ps | grep -q "Up"'; then
        success "Contenedores Docker listos y ejecutándose"
        return 0
    else
        error "Los contenedores no se iniciaron correctamente"
        run_in_docker_dir 'docker-compose ps'
        return 1
    fi
}

# Ejecutar comandos en el contenedor web con reintentos MEJORADO
exec_in_web() {
    local cmd="$1"
    local max_attempts=3
    local attempt=1
    
    sleep 10
    
    while [ $attempt -le $max_attempts ]; do
        process "Ejecutando comando (intento $attempt/$max_attempts)..."
        
        if run_in_docker_dir "docker-compose exec -T web bash -c \"$cmd\""; then
            return 0
        fi
        
        if [ $attempt -lt $max_attempts ]; then
            warning "Intento $attempt falló. Reintentando en 10 segundos..."
            sleep 10
        fi
        
        attempt=$((attempt + 1))
    done
    
    error "Error ejecutando comando después de $max_attempts intentos: $cmd"
    return 1
}

# Función MEJORADA para crear proyectos con Composer
create_project_with_composer() {
    local framework_cmd="$1"
    local project_name="$2"
    local install_dir="$3"
    
    process "Descargando proyecto $framework_cmd..."
    
    exec_in_web "composer config -g process-timeout 1200"
    exec_in_web "composer config -g repo.packagist composer https://packagist.org"
    exec_in_web "composer clear-cache"
    
    # Opciones específicas por framework
    if [[ "$FRAMEWORK" == yii2* ]]; then
        local composer_options=(
            "--prefer-dist --no-progress --no-interaction"
            "--prefer-dist --no-dev --no-progress --no-interaction"
            "--prefer-source --no-progress --no-interaction"
        )
    else
        local composer_options=(
            "--prefer-dist --no-dev --no-progress --no-interaction"
            "--prefer-dist --no-progress --no-interaction"
            "--prefer-source --no-progress --no-interaction"
        )
    fi
    
    for options in "${composer_options[@]}"; do
        process "Intentando con opciones: $options"
        
        # Limpiar directorio temporal si existe
        exec_in_web "rm -rf /tmp/${project_name} 2>/dev/null || true"
        
        if exec_in_web "composer create-project $options $framework_cmd /tmp/${project_name}"; then
            # VERIFICAR que el proyecto se creó correctamente
            if exec_in_web "[ -d /tmp/${project_name} ] && [ -f /tmp/${project_name}/composer.json ]"; then
                success "Proyecto descargado correctamente"
                
                # Mover a la ubicación final
                exec_in_web "rm -rf ${install_dir}/* 2>/dev/null || true"
                exec_in_web "sh -c 'mv /tmp/${project_name}/* ${install_dir}/ 2>/dev/null || true'"
                exec_in_web "sh -c 'mv /tmp/${project_name}/.* ${install_dir}/ 2>/dev/null || true'"
                exec_in_web "rm -rf /tmp/${project_name}"
                
                # Instalar dependencias si es necesario
                if exec_in_web "[ ! -d ${install_dir}/vendor ] && [ -f ${install_dir}/composer.json ]"; then
                    process "Instalando dependencias..."
                    if exec_in_web "cd ${install_dir} && composer install --no-dev --no-progress --no-interaction"; then
                        success "Dependencias instaladas correctamente"
                    else
                        warning "No se pudieron instalar las dependencias automáticamente"
                    fi
                fi
                
                return 0
            fi
        fi
        
        warning "Intento falló con opciones: $options"
        exec_in_web "rm -rf /tmp/${project_name} 2>/dev/null || true"
    done
    
    return 1
}

# Crear proyecto Yii2 Basic
create_yii2_basic_project() {
    process "Creando proyecto Yii2 Basic: ${PROJECT_NAME}"
    
    if ! create_project_with_composer "yiisoft/yii2-app-basic" "${PROJECT_NAME}" "/var/www/html"; then
        error "Error al crear proyecto Yii2 Basic después de múltiples intentos"
        return 1
    fi
    
    # Configuraciones adicionales para Yii2 Basic
    exec_in_web "chown -R www-data:www-data /var/www/html"
    exec_in_web "chmod -R 755 /var/www/html/runtime"
    exec_in_web "chmod -R 755 /var/www/html/web/assets"
    
    success "Proyecto Yii2 Basic '${PROJECT_NAME}' creado correctamente"
    return 0
}

# Crear proyecto Yii2 Advanced
create_yii2_advanced_project() {
    process "Creando proyecto Yii2 Advanced: ${PROJECT_NAME}"
    
    if ! create_project_with_composer "yiisoft/yii2-app-advanced" "${PROJECT_NAME}" "/var/www/html"; then
        error "Error al crear proyecto Yii2 Advanced después de múltiples intentos"
        return 1
    fi
    
    # Configuraciones adicionales para Yii2 Advanced
    exec_in_web "chown -R www-data:www-data /var/www/html"
    exec_in_web "chmod -R 755 /var/www/html/frontend/runtime"
    exec_in_web "chmod -R 755 /var/www/html/backend/runtime"
    exec_in_web "chmod -R 755 /var/www/html/frontend/web/assets"
    exec_in_web "chmod -R 755 /var/www/html/backend/web/assets"
    
    # Inicializar el proyecto advanced
    process "Inicializando Yii2 Advanced..."
    if exec_in_web "cd /var/www/html && php init --env=Development --overwrite=All"; then
        success "Yii2 Advanced inicializado correctamente"
    else
        warning "No se pudo inicializar Yii2 Advanced automáticamente"
    fi
    
    success "Proyecto Yii2 Advanced '${PROJECT_NAME}' creado correctamente"
    return 0
}

# Crear proyecto Yii3
create_yii3_project() {
    process "Creando proyecto Yii3: ${PROJECT_NAME}"
    
    if ! create_project_with_composer "yiisoft/yii-project-template" "${PROJECT_NAME}" "/var/www/html"; then
        error "Error al crear proyecto Yii3 después de múltiples intentos"
        return 1
    fi
    
    exec_in_web "chown -R www-data:www-data /var/www/html"
    
    success "Proyecto Yii3 '${PROJECT_NAME}' creado correctamente"
    return 0
}

# Crear proyecto Laravel
create_laravel_project() {
    process "Creando proyecto Laravel: ${PROJECT_NAME}"
    
    if ! create_project_with_composer "laravel/laravel" "${PROJECT_NAME}" "/var/www/html"; then
        error "Error al crear proyecto Laravel después de múltiples intentos"
        return 1
    fi
    
    exec_in_web "chown -R www-data:www-data /var/www/html"
    exec_in_web "chmod -R 775 /var/www/html/storage"
    exec_in_web "chmod -R 775 /var/www/html/bootstrap/cache"
    
    # Configurar .env para Laravel
    process "Configurando Laravel..."
    exec_in_web "cd /var/www/html && cp .env.example .env 2>/dev/null || true"
    
    exec_in_web "cd /var/www/html && cat > .env << 'ENDFILE'
APP_NAME=${PROJECT_NAME}
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:${WEB_PORT}

DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432
DB_DATABASE=${PROJECT_NAME}_db
DB_USERNAME=postgres
DB_PASSWORD=password

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME=\"\${APP_NAME}\"
ENDFILE"
    
    exec_in_web "cd /var/www/html && php artisan key:generate"
    
    success "Proyecto Laravel '${PROJECT_NAME}' creado correctamente"
    return 0
}

# Crear el proyecto según el framework seleccionado
create_framework_project() {
    process "Iniciando creación del proyecto ${PROJECT_NAME} con ${FRAMEWORK}..."
    
    process "Probando conexión a internet desde el contenedor..."
    if ! exec_in_web "curl -s --connect-timeout 30 https://packagist.org > /dev/null"; then
        warning "El contenedor no puede conectarse a Packagist. Esto puede causar problemas."
        exec_in_web "cat /etc/resolv.conf"
    else
        success "Conexión a internet verificada desde el contenedor"
    fi
    
    case "$FRAMEWORK" in
        "yii2-basic")
            create_yii2_basic_project
            ;;
        "yii2-advanced")
            create_yii2_advanced_project
            ;;
        "yii3")
            create_yii3_project
            ;;
        "laravel")
            create_laravel_project
            ;;
        *)
            error "Framework no válido: $FRAMEWORK"
            return 1
            ;;
    esac
}

# Configuración MEJORADA de base de datos
configure_database() {
    process "Configurando base de datos para $FRAMEWORK..."
    
    sleep 10
    
    case "$FRAMEWORK" in
        "yii2-basic")
            configure_yii2_basic_db
            ;;
        "yii2-advanced")
            configure_yii2_advanced_db
            ;;
        "yii3")
            configure_yii3_db
            ;;
        "laravel")
            configure_laravel_db
            ;;
    esac
}

configure_laravel_db() {
    process "Configurando base de datos para Laravel..."
    
    process "Verificando conexión a la base de datos..."
    if exec_in_web "cd /var/www/html && php -r \"
try {
    \\\$pdo = new PDO('pgsql:host=db;port=5432;dbname=${PROJECT_NAME}_db', 'postgres', 'password');
    \\\$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo 'Conexión a BD exitosa' . PHP_EOL;
} catch (PDOException \\\$e) {
    echo 'Error de conexión: ' . \\\$e->getMessage() . PHP_EOL;
    exit(1);
}
\""; then
        success "Conexión a la base de datos verificada"
    else
        error "No se pudo conectar a la base de datos"
        return 1
    fi
    
    process "Ejecutando migraciones de Laravel..."
    if exec_in_web "cd /var/www/html && php artisan migrate --force"; then
        success "Migraciones de Laravel ejecutadas correctamente"
    else
        warning "Las migraciones de Laravel fallaron o no son necesarias"
    fi
    return 0
}

configure_yii3_db() {
    process "Configurando base de datos para Yii3..."
    if exec_in_web "cd /var/www/html && php ./yii migrate/up --interactive=0"; then
        success "Migraciones de Yii3 ejecutadas correctamente"
    else
        warning "Las migraciones de Yii3 fallaron o no son necesarias"
    fi
    return 0
}

# Configuración MEJORADA para Yii2 Basic
configure_yii2_basic_db() {
    process "Configurando base de datos para Yii2 Basic..."
    
    # Primero verificar que Yii2 esté instalado correctamente
    process "Verificando instalación de Yii2 Basic..."
    if ! exec_in_web "[ -f /var/www/html/vendor/yiisoft/yii2/Yii.php ]"; then
        error "Yii2 Basic no está instalado correctamente. No se puede configurar la base de datos."
        info "Instala las dependencias manualmente:"
        echo "  cd $DOCKER_DIR && docker-compose exec web composer install"
        return 1
    fi
    
    process "Configurando conexión a base de datos para Yii2 Basic..."
    exec_in_web "cd /var/www/html && cp config/db.php config/db.php.backup 2>/dev/null || true"
    
    exec_in_web "cd /var/www/html && cat > config/db.php << 'ENDFILE'
<?php

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'pgsql:host=db;port=5432;dbname=${PROJECT_NAME}_db',
    'username' => 'postgres',
    'password' => 'password',
    'charset' => 'utf8',
];
ENDFILE"
    
    # Deshabilitar GII en producción o si no está instalado
    exec_in_web "cd /var/www/html && cp config/web.php config/web.php.backup 2>/dev/null || true"
    exec_in_web "cd /var/www/html && sed -i \"s/'modules' => \[/'modules' => \[\\n    /*\\n    'gii' => [\\n        'class' => 'yii\\\gii\\\Module',\\n    ],\\n    */\\n/g\" config/web.php 2>/dev/null || true"
    
    process "Intentando ejecutar migraciones de Yii2 Basic..."
    if exec_in_web "cd /var/www/html && php yii migrate/up --interactive=0"; then
        success "Migraciones de Yii2 Basic ejecutadas correctamente"
    else
        warning "Las migraciones de Yii2 Basic fallaron o no son necesarias"
    fi
    
    return 0
}

# Configuración para Yii2 Advanced
configure_yii2_advanced_db() {
    process "Configurando base de datos para Yii2 Advanced..."
    
    # Verificar instalación
    if ! exec_in_web "[ -f /var/www/html/vendor/yiisoft/yii2/Yii.php ]"; then
        error "Yii2 Advanced no está instalado correctamente."
        return 1
    fi
    
    # Configurar base de datos común
    exec_in_web "cd /var/www/html && cat > common/config/main-local.php << 'ENDFILE'
<?php
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'pgsql:host=db;port=5432;dbname=${PROJECT_NAME}_db',
            'username' => 'postgres',
            'password' => 'password',
            'charset' => 'utf8',
        ],
    ],
];
ENDFILE"
    
    # Configurar base de datos para frontend y backend
    for app in frontend backend; do
        exec_in_web "cd /var/www/html && cat > ${app}/config/main-local.php << 'ENDFILE'
<?php
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'pgsql:host=db;port=5432;dbname=${PROJECT_NAME}_db',
            'username' => 'postgres',
            'password' => 'password',
            'charset' => 'utf8',
        ],
    ],
];
ENDFILE"
    done
    
    process "Ejecutando migraciones de Yii2 Advanced..."
    if exec_in_web "cd /var/www/html && php yii migrate/up --interactive=0"; then
        success "Migraciones de Yii2 Advanced ejecutadas correctamente"
    else
        warning "Las migraciones de Yii2 Advanced fallaron o no son necesarias"
    fi
    
    return 0
}

# Mostrar resumen final MEJORADO
show_final_summary() {
    echo ""
    success "🎉 ¡PROYECTO CREADO EXITOSAMENTE!"
    echo "=================================="
    echo ""
    info "📊 RESUMEN FINAL:"
    echo "-----------------"
    echo "  📂 Proyecto: $PROJECT_NAME"
    echo "  🚀 Framework: $FRAMEWORK"
    echo "  🐘 PHP: $PHP_VERSION"
    echo "  🌐 URL: http://localhost:${WEB_PORT}"
    echo "  🗄️  Base de datos: localhost:${DB_PORT}"
    echo "  📁 Directorio: $DOCKER_DIR/src/$PROJECT_NAME/"
    echo ""
    
    # Información específica por framework
    case "$FRAMEWORK" in
        "yii2-advanced")
            info "🌐 URLs de Yii2 Advanced:"
            echo "  Frontend: http://localhost:${WEB_PORT}"
            echo "  Backend: http://localhost:${WEB_PORT}/backend/web"
            ;;
        *)
            info "🌐 URL de la aplicación:"
            echo "  http://localhost:${WEB_PORT}"
            ;;
    esac
    echo ""
    
    info "🚀 COMANDOS ÚTILES:"
    echo "------------------"
    echo "  Iniciar proyecto: cd $DOCKER_DIR && docker-compose up -d"
    echo "  Detener proyecto: cd $DOCKER_DIR && docker-compose down"
    echo "  Ver logs: cd $DOCKER_DIR && docker-compose logs"
    echo "  Acceder a la consola: cd $DOCKER_DIR && docker-compose exec web bash"
    echo ""
    
    info "🔗 CONEXIÓN A LA BASE DE DATOS:"
    echo "------------------------------"
    echo "  Host: localhost"
    echo "  Puerto: ${DB_PORT}"
    echo "  Base de datos: ${PROJECT_NAME}_db"
    echo "  Usuario: postgres"
    echo "  Contraseña: password"
    echo ""
    
    # Instrucciones específicas por framework
    case "$FRAMEWORK" in
        "yii2-basic"|"yii2-advanced")
            info "🔧 INSTRUCCIONES ESPECÍFICAS PARA YII2:"
            echo "-------------------------------------"
            echo "  Si hay problemas con dependencias:"
            echo "    cd $DOCKER_DIR && docker-compose exec web composer install"
            if [ "$FRAMEWORK" = "yii2-advanced" ]; then
                echo "  Para inicializar el proyecto:"
                echo "    cd $DOCKER_DIR && docker-compose exec web php init"
            fi
            echo "  Para ejecutar migraciones:"
            echo "    cd $DOCKER_DIR && docker-compose exec web php yii migrate/up --interactive=0"
            echo "  Para instalar módulos de desarrollo:"
            echo "    cd $DOCKER_DIR && docker-compose exec web composer require --dev yiisoft/yii2-gii"
            echo "    cd $DOCKER_DIR && docker-compose exec web composer require --dev yiisoft/yii2-debug"
            echo ""
            ;;
        "yii3")
            info "🔧 INSTRUCCIONES ESPECÍFICAS PARA YII3:"
            echo "-------------------------------------"
            echo "  Para ejecutar migraciones: cd $DOCKER_DIR && docker-compose exec web php ./yii migrate/up --interactive=0"
            echo ""
            ;;
        "laravel")
            info "🔧 INSTRUCCIONES ESPECÍFICAS PARA LARAVEL:"
            echo "----------------------------------------"
            echo "  Para ejecutar migraciones: cd $DOCKER_DIR && docker-compose exec web php artisan migrate"
            echo "  Para generar key: cd $DOCKER_DIR && docker-compose exec web php artisan key:generate"
            echo ""
            ;;
    esac
    
    info "📝 PRÓXIMOS PASOS:"
    echo "-----------------"
    echo "  1. Accede a la URL mostrada arriba para ver tu aplicación"
    echo "  2. Configura la base de datos si es necesario"
    echo "  3. ¡Comienza a desarrollar!"
    echo ""
}

# Función principal
main() {
    clear
    echo "========================================"
    echo "  GENERADOR DE PROYECTOS CON DOCKER v1.1"
    echo "========================================"
    echo ""
    
    check_docker_installation
    check_docker_permissions
    check_internet_connection
    
    select_framework
    
    get_project_name
    
    if ! create_directory_structure; then
        error "Error creando la estructura de directorios"
        exit 1
    fi
    
    if ! create_env_file; then
        error "Error creando el archivo .env"
        exit 1
    fi
    
    if ! create_apache_config; then
        error "Error creando la configuración de Apache"
        exit 1
    fi
    
    if ! create_dockerfile; then
        error "Error creando el Dockerfile"
        exit 1
    fi
    
    if ! create_docker_compose; then
        error "Error creando docker-compose.yml"
        exit 1
    fi
    
    if build_docker_containers; then
        process "Esperando inicialización completa de servicios..."
        sleep 20
        
        if create_framework_project; then
            process "Configurando la aplicación..."
            if configure_database; then
                show_final_summary
            else
                warning "Proyecto creado pero la configuración de BD tuvo problemas menores"
                show_final_summary
            fi
        else
            error "Error al crear el proyecto del framework"
            exit 1
        fi
    else
        error "Error al construir los contenedores Docker"
        exit 1
    fi
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi
-- RISK326	integrity_check
-- contains(user_agent, "integrity=false") or contains(user_agent, "integrity=False"
DROP TABLE team_kingkong.tpap_risk326_breaches;

-- CREATE TABLE team_kingkong.tpap_risk326_breaches AS
INSERT INTO team_kingkong.tpap_risk326_breaches
SELECT DISTINCT B.*, C.category
, IF(D.upi_subtype IS NOT NULL, D.upi_subtype, IF(C.category = 'LITE_MANDATE', 'UPI_LITE_MANDATE', '')) AS upi_subtype
, D.integrity
, 'integrity_check'  AS rule_name
, 'user agent intergrity = false' AS breach_reason FROM
    (SELECT txn_id,
    MAX(CASE WHEN participant_type = 'PAYER' THEN vpa END) AS payer_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN vpa END) AS payee_vpa,
    MAX(DATE(created_on)) as txn_date,
    MAX(amount) AS txn_amount,
    MAX(created_on) AS txn_time
    FROM switch.txn_participants_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND DATE(created_on) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31' 
    GROUP BY 1)B
inner join
    (select txn_id, category
    from switch.txn_info_snapshot_v3
    where DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    and DATE(created_on) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31')C
on B.txn_id = C.txn_id
INNER JOIN
    (SELECT txnid
    , regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') AS upi_subtype
    , json_extract_scalar(request, '$.requestPayload.txnType') AS txnType
    , json_extract_scalar(request, '$.requestPayload.integrity') AS integrity -- true UNKNOWN false
    FROM tpap_hss.upi_switchv2_dwh_risk_data_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND json_extract_scalar(response, '$.action_recommended') <> 'BLOCK'
    AND regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') = 'UPI_TRANSACTION'
    AND json_extract_scalar(request, '$.requestPayload.integrity') <> 'true')D
ON B.txn_id = D.txnid
;

SELECT MONTH(txn_date), COUNT(*) FROM team_kingkong.tpap_risk326_breaches GROUP BY 1 LIMIT 10;
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":x-connect: Boost Days - What's on this week! :x-connect:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Let's get ready to dive into another great week here in the Auckland office! \n \n See below for what's in store:"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-23: Tuesday, 23rd September",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":coffee: *Xero Café:* Café-style beverages and sweet treats.\n:pineapple: *Barista Special:* Peach and Pineapple Tea \n:tomato: *Breakfast:* Provided from *8.30am* in the All Hands kitchen \n :nail_care: *tipsity nails:* Book in with the lovely Emma to get your fresh claws, link is <https://docs.google.com/spreadsheets/d/1pTGAD8oFXmPF890Uzj4d-Crfch8muuzEzDnNyBA9ReY/edit?gid=1100887842#gid=1100887842|*here*> "
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-25: Thursday, 25th September",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":coffee: *Xero Café:* Café-style beverages and sweet treats.\n:pineapple: *Barista Special:* Peach and Pineapple Tea \n:pie: *Light Lunch*: Provided from *12:30pm* in the All Hands kitchen \n :ai: *AI Explore Event:* Join your fellow Xero's in All Hands for the AI Xplore online learning event about investing in you by equipping you with essential AI skills and knowledge, so every one of us can confidently unlock the potential of AI.\n *Snacks and refreshments* will be provided in All Hands. <https://meet.google.com/stream/f94ad206-dc30-474a-a8d3-b821b77d692b|*Here*> is the link if you cant make it to *All Hands*. \n Plus, keep an eye out for competitions and prizes!"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "*What else?*"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Feedback on our Boost offerings? We want to hear to it. Let us know what you love by filling out our form <https://docs.google.com/forms/d/e/1FAIpQLScGOSeS5zUI8WXEl0K4WGoQUkmpIHzAjLlEKWBob4sMPhDXmA/viewform|*here*>! :feedback_:"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Stay tuned to this channel for more details, check out the <https://calendar.google.com/calendar/u/0?cid=eGVyby5jb21fMXM4M3NiZzc1dnY0aThpY2FiZDZvZ2xncW9AZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ|*Auckland Social Calendar.*>\n\nLove,\nWX :wx:"
			}
		}
	]
}
Option Explicit 
 
Public Function ReverseString(Text As String) 
     
    ReverseString = StrReverse(Text) 
     
End Function 
-- RISK314	oc69_mcc_4812_4814_collect_limit	
-- MCC 4812 / 4814 (prepaid mobile recharge) in collect mode shall be restricted to maximum of Rs. 5,000 respectively (including from verified merchants).

DROP TABLE team_kingkong.tpap_risk314_breaches;

-- CREATE TABLE team_kingkong.tpap_risk314_breaches AS
INSERT INTO team_kingkong.tpap_risk314_breaches
SELECT DISTINCT B.*, C.category
, IF(D.upi_subtype IS NOT NULL, D.upi_subtype, IF(C.category = 'LITE_MANDATE', 'UPI_LITE_MANDATE', '')) AS upi_subtype
, D.txnType
, 'oc69_mcc_4812_4814_collect_limit'  AS rule_name
, 'payee_mcc in (4812, 4814) & txnType = COLLECT & amt >5k' AS breach_reason FROM
    (SELECT txn_id,
    MAX(CASE WHEN participant_type = 'PAYER' THEN vpa END) AS payer_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN vpa END) AS payee_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN mcc END) AS payee_mcc,
    MAX(DATE(created_on)) as txn_date,
    MAX(amount) AS txn_amount,
    MAX(created_on) AS txn_time
    FROM switch.txn_participants_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND DATE(created_on) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31' 
    GROUP BY 1
    HAVING MAX(CASE WHEN participant_type = 'PAYEE' THEN mcc END) IN ('4812', '4814')
    AND MAX(amount) > 5000)B
inner join
    (select txn_id, category
    from switch.txn_info_snapshot_v3
    where DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    and DATE(created_on) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31') C
on B.txn_id = C.txn_id
INNER JOIN
    (SELECT txnid
    , regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') AS upi_subtype
    , json_extract_scalar(request, '$.requestPayload.txnType') AS txnType
    FROM tpap_hss.upi_switchv2_dwh_risk_data_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND json_extract_scalar(response, '$.action_recommended') <> 'BLOCK'
    AND json_extract_scalar(request, '$.requestPayload.txnType') = 'COLLECT'
    AND regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') = 'UPI_TRANSACTION')D
ON B.txn_id = D.txnid
;
-- RISK156	upi_mcc_7407_decline_intent	Block if Initiation mode is 04 or 05 Payeemcc is 7407
DROP TABLE team_kingkong.tpap_risk156_breaches;

-- CREATE TABLE team_kingkong.tpap_risk156_breaches AS
INSERT INTO team_kingkong.tpap_risk156_breaches
SELECT DISTINCT B.*, C.category
, C.initiationMode as initiationMode_switch -- ,  D.initiationMode as initiationMode_tpaphss
, IF(D.upi_subtype IS NOT NULL, D.upi_subtype, IF(C.category = 'LITE_MANDATE', 'UPI_LITE_MANDATE', '')) AS upi_subtype
, 'upi_mcc_7407_decline_intent'  AS rule_name
, 'payee_mcc = 7407 & init mode in 04, 05' AS breach_reason FROM
    (SELECT txn_id,
    MAX(CASE WHEN participant_type = 'PAYER' THEN vpa END) AS payer_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN vpa END) AS payee_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN mcc END) AS payee_mcc,
    MAX(DATE(created_on)) as txn_date,
    MAX(amount) AS txn_amount,
    MAX(created_on) AS txn_time
    FROM switch.txn_participants_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND DATE(created_on) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31' 
    GROUP BY 1
    HAVING MAX(CASE WHEN participant_type = 'PAYEE' THEN mcc END) = '7407')B
inner join
    (select txn_id, category
    , json_extract_scalar(extended_info, '$.initiationMode') as initiationMode
    from switch.txn_info_snapshot_v3
    where DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    and DATE(created_on) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND json_extract_scalar(extended_info, '$.initiationMode') IN ('04', '05')) C
on B.txn_id = C.txn_id
INNER JOIN
    (SELECT txnid
    , regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') AS upi_subtype
    FROM tpap_hss.upi_switchv2_dwh_risk_data_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-01-01' AND DATE'2025-01-31'
    AND json_extract_scalar(response, '$.action_recommended') <> 'BLOCK'
    AND JSON_EXTRACT_SCALAR(request, '$.requestPayload.initiationMode') IN ('04', '05')
    AND regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') = 'UPI_TRANSACTION')D
ON B.txn_id = D.txnid
;
Polymarket clone solutions designed for entrepreneurs who want to launch their own decentralized prediction market platform.

💡 Key Features:

Market creation & participation modules

Smart contract-powered transactions

User-friendly dashboards

High-level security protocols

This solution is perfect for startups aiming to enter the prediction market space quickly with minimal risks.
{% render 'specification-table' %}
{{ product.metafields.custom.more_info | metafield_tag }}
-- RISK108	upi_intent_paytmqr_decline_oc76
-- intent (initiation mode 04/05) is declined for VPA like VPA like paytmqr 

DROP TABLE team_kingkong.tpap_risk108_breaches;

CREATE TABLE team_kingkong.tpap_risk108_breaches AS
-- INSERT INTO team_kingkong.tpap_risk108_breaches
SELECT DISTINCT B.*, C.category
, C.initiationMode as initiationMode_switch -- ,  D.initiationMode as initiationMode_tpaphss
, IF(D.upi_subtype IS NOT NULL, D.upi_subtype, IF(C.category = 'LITE_MANDATE', 'UPI_LITE_MANDATE', '')) AS upi_subtype
, 'upi_intent_paytmqr_decline_oc76'  AS rule_name
, 'payee_vpa contains "paytmqr" and init mode in 04, 05' AS breach_reason FROM
    (SELECT txn_id,
    MAX(CASE WHEN participant_type = 'PAYER' THEN vpa END) AS payer_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN vpa END) AS payee_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN mcc END) AS payee_mcc,
    MAX(DATE(created_on)) as txn_date,
    MAX(amount) AS txn_amount,
    MAX(created_on) AS txn_time
    FROM switch.txn_participants_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    AND DATE(created_on) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15' 
    GROUP BY 1)B
inner join
    (select txn_id, category
    , json_extract_scalar(extended_info, '$.initiationMode') as initiationMode
    from switch.txn_info_snapshot_v3
    where DATE(dl_last_updated) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    and DATE(created_on) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    -- and upper(status) = 'SUCCESS' AND category IN ('VPA2MERCHANT', 'VPA2VPA')
    ) C
on B.txn_id = C.txn_id
INNER JOIN
    (SELECT txnid
    , regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') AS upi_subtype
    FROM tpap_hss.upi_switchv2_dwh_risk_data_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    AND (lower(regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '')) LIKE '%@paytm%'
    or lower(regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '')) like '%@pt%')
    AND regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '') IS NOT NULL
    AND regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '') <> ''
    AND json_extract_scalar(response, '$.action_recommended') <> 'BLOCK'
    )D
ON B.txn_id = D.txnid
WHERE lower(payee_vpa) LIKE '%paytmqr%'
AND initiationMode IN ('04', '05')
;
-- RISK161	upi_oc141A_mcc6540_gift
DROP TABLE team_kingkong.tpap_risk161_breaches;

CREATE TABLE team_kingkong.tpap_risk161_breaches AS
-- INSERT INTO team_kingkong.tpap_risk161_breaches
SELECT DISTINCT B.*, C.category
, C.initiationMode as initiationMode_switch -- ,  D.initiationMode as initiationMode_tpaphss
, IF(D.upi_subtype IS NOT NULL, D.upi_subtype, IF(C.category = 'LITE_MANDATE', 'UPI_LITE_MANDATE', '')) AS upi_subtype
, D.txnType
, 'upi_oc141A_mcc6540_gift'  AS rule_name
, CASE
    WHEN payee_mcc = '6540' AND initiationMode = '00' AND txnType NOT IN ('PAY', 'DEBIT') 
        THEN 'Invalid txnType for initiationMode 00 and MCC 6540'
    WHEN payee_mcc = '6540' AND initiationMode NOT IN ('00', '10', '04', '05', '01', '02', '11') 
        THEN 'Invalid initiationMode for MCC 6540'
    ELSE NULL
END AS breach_reason FROM
    (SELECT txn_id,
    MAX(CASE WHEN participant_type = 'PAYER' THEN vpa END) AS payer_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN vpa END) AS payee_vpa,
    MAX(CASE WHEN participant_type = 'PAYEE' THEN mcc END) AS payee_mcc,
    MAX(DATE(created_on)) as txn_date,
    MAX(amount) AS txn_amount,
    MAX(created_on) AS txn_time
    FROM switch.txn_participants_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    AND DATE(created_on) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15' 
    GROUP BY 1)B
inner join
    (select txn_id, category
    , json_extract_scalar(extended_info, '$.initiationMode') as initiationMode
    from switch.txn_info_snapshot_v3
    where DATE(dl_last_updated) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    and DATE(created_on) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    -- and upper(status) = 'SUCCESS' AND category IN ('VPA2MERCHANT', 'VPA2VPA')
    ) C
on B.txn_id = C.txn_id
INNER JOIN
    (SELECT txnid
    , regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') AS upi_subtype
    , json_extract_scalar(request, '$.requestPayload.txnType') AS txnType
    FROM tpap_hss.upi_switchv2_dwh_risk_data_snapshot_v3
    WHERE DATE(dl_last_updated) BETWEEN DATE'2025-09-01' AND DATE'2025-09-15'
    AND (lower(regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '')) LIKE '%@paytm%'
    or lower(regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '')) like '%@pt%')
    AND regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '') IS NOT NULL
    AND regexp_replace(cast(json_extract(request, '$.requestPayload.payerVpa') as varchar), '"', '') <> ''
    AND json_extract_scalar(response, '$.action_recommended') <> 'BLOCK'
    -- AND regexp_replace(cast(json_extract(request, '$.requestPayload.payerType') AS varchar),'"','') = 'PERSON'
    -- AND regexp_replace(cast(json_extract(request, '$.requestPayload.payeeType') AS varchar),'"','') = 'PERSON'
    -- AND JSON_EXTRACT_SCALAR(request, '$.requestPayload.initiationMode') = '04'
    -- AND json_extract_scalar(request, '$.requestPayload.merchantGenre') = 'OFFLINE'
    -- AND regexp_replace(cast(json_extract(request, '$.evaluationType') as varchar), '"', '') = 'UPI_TRANSACTION'
    )D
ON B.txn_id = D.txnid
WHERE (payee_mcc = '6540') AND
((initiationMode ='00' AND txnType NOT IN ('PAY','DEBIT')) OR 
(payee_mcc = '6540' AND initiationMode NOT IN ('00', '10', '04', '05', '01', '02', '11')))
;
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sunshine: Boost Days - What's On This Week :sunshine:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n\n Good morning Melbourne, hope you all had a fabulous weekend and enjoyed the sunny weather. Please see below for what's on store this week. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Xero Café :coffee:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n :new-thing: *This week we are offering some yummy Chocolate and Blueberry muffins & Coconut Drops :coconut:* \n\n :coffee: *Weekly Café Special:* _Iced Vanilla Latte_"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": " Wednesday, 17th September :calendar-date-17:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": " \n\n :gah-update: *September GAH*: Join us live at 9am in the Wominjeka Breakout Space on Level 3 for the Global All Hands. \n:lunch::flag-it: *Light Lunch*: An Italian Lunch from 12pm in the Wominjeka Breakout Space. Menu is in the :thread:"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Thursday, 18th Septemer :calendar-date-18:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":pancakes: *Breakfast*: from *8:30am-10:30am* in the Wominjeka Breakout Space.     \n\n  "
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Friday, 19th September :calendar-date-19:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "*Social Happy Hour:* Join us for drinks and nibbles from 4.00pm -5.30pm in the Level -3 Wominjeka Breakout Space :cheese: \n\n\n *What Else?* \n ":tino_rangatiratanga: *Te Wiki o Te Reo Māori*: Celebrate Māori language week with the #maoripacific-erg, head to their channel to see how you can engage and use your reo this week! \n\n*Feedback on our Boost Offerings?* We want to hear more. Let us know what you love by filling out our form <https://docs.google.com/forms/d/e/1FAIpQLScGOSeS5zUI8WXEl0K4WGoQUkmpIHzAjLlEKWBob4sMPhDXmA/viewform|here.>  Stay tuned to this channel, and make sure you're subscribed to the <https://calendar.google.com/calendar/u/0?cid=Y19xczkyMjk5ZGlsODJzMjA4aGt1b3RnM2t1MEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t|*Melbourne Social Calendar*> :party-wx: "
			}
		},
		{
			"type": "divider"
		}
	]
}
For startups and enterprises, the biggest benefit is time-to-market. The faster you launch, the quicker you can attract users and liquidity. If you’re exploring this space, it’s worth checking how these companies design exchange platforms, handle security, and support regulatory compliance.
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sunshine: Boost Days - What's On This Week :sunshine:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n\n Good morning Melbourne, hope you all had a fabulous weekend and enjoyed the sunny weather. Please see below for what's on store this week. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Xero Café :coffee:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n :new-thing: *This week we are offering some yummy Chocolate and Blueberry muffins & Coconut Drops :coconut:* \n\n :coffee: *Weekly Café Special:* _Iced Vanilla Latte_"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": " Wednesday, 17th Septmber :calendar-date-17:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": " \n\n :gah-update: *September GAH*: Join us live at 9am in the Wominjeka Breakout Space on Level 3 for the Global All Hands. \n:lunch::flag-th: *Light Lunch*: A Thai Lunch from 12pm in the Wominjeka Breakout Space. Menu is in the :thread:"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Thursday, 18th Septemer :calendar-date-18:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":pancakes: *Breakfast*: from *8:30am-10:30am* in the Wominjeka Breakout Space.     \n\n  "
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Friday, 19th September :calendar-date-19:",
				"emoji": true
			}
		},
		{:tino_rangatiratanga: Te Wiki o Te Reo Māori: Celebrate Māori language week with the #maoripacific-erg, head to their channel to see how you can engage and use your reo this week!
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sunshine: Boost Days - What's On This Week :sunshine:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n\n Good morning Melbourne, hope you all had a fabulous weekend and enjoyed the sunny weather. Please see below for what's on store this week. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Xero Café :coffee:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n :new-thing: *This week we are offering some yummy Chocolate and Blueberry muffins & Coconut Drops :coconut:* \n\n :coffee: *Weekly Café Special:* _Iced Vanilla Latte_"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": " Wednesday, 17th Septmber :calendar-date-17:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": " \n\n :gah-update: *September GAH*: Join us live at 9am in the Wominjeka Breakout Space on Level 3 for the Global All Hands. \n:lunch::flag-th: *Light Lunch*: A Thai Lunch from 12pm in the Wominjeka Breakout Space. Menu is in the :thread:"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Thursday, 18th Septemer :calendar-date-18:",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":pancakes: *Breakfast*: from *8:30am-10:30am* in the Wominjeka Breakout Space.     \n\n  "
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "Friday, 19th September :calendar-date-19:",
				"emoji": true
			}
		},
		{
khi click vào nut tăng giảm số trong thì call
timeout = setTimeout(function () {
  jQuery("[name='update_cart']").trigger("click");
}, 1000);

$(document.body).on('added_to_cart', function( event, fragments ) {
		var cartCount = $(fragments['span.mega-menu-woo-cart-count']).text();

		$('.cart_count').each(function(){
			$(this).text(cartCount);
		});
	}).on( 'updated_cart_totals', function(){
		$.ajax({
			url: '/wp-admin/admin-ajax.php',
			type: 'POST',
			dataType: 'json',
			data: { 'action': 'get-cart-total' },
			success: function( data ) {
				$('.cart-subtotal td').html( data.subtotal );
				//$('.woocommerce-shipping-totals td').html( data.shipping );
				$('.order-total td').html( data.total );
                console.log(2);
                $('.custom-order-total-price').html( data.total );
			}
		});
	});

add_action( 'wp_ajax_get-cart-total', 'get_cart_total' ); // wp_ajax_{ЗНАЧЕНИЕ ПАРАМЕТРА ACTION!!}
add_action( 'wp_ajax_nopriv_get-cart-total', 'get_cart_total' );  // wp_ajax_nopriv_{ЗНАЧЕНИЕ ACTION!!}
// первый хук для авторизованных, второй для не авторизованных пользователей

function get_cart_total(){
	wp_die( json_encode([
		'shipping' => WC()->cart->get_cart_shipping_total(),
		'subtotal' => WC()->cart->get_cart_subtotal(),
		'total' => WC()->cart->get_total(),
	]) );
}

khi click vào nut tăng giảm số trong thì call
timeout = setTimeout(function () {
  jQuery("[name='update_cart']").trigger("click");
}, 1000);

$(document.body).on('added_to_cart', function( event, fragments ) {
		var cartCount = $(fragments['span.mega-menu-woo-cart-count']).text();

		$('.cart_count').each(function(){
			$(this).text(cartCount);
		});
	}).on( 'updated_cart_totals', function(){
		$.ajax({
			url: '/wp-admin/admin-ajax.php',
			type: 'POST',
			dataType: 'json',
			data: { 'action': 'get-cart-total' },
			success: function( data ) {
				$('.cart-subtotal td').html( data.subtotal );
				//$('.woocommerce-shipping-totals td').html( data.shipping );
				$('.order-total td').html( data.total );
                console.log(2);
                $('.custom-order-total-price').html( data.total );
			}
		});
	});

add_action( 'wp_ajax_get-cart-total', 'get_cart_total' ); // wp_ajax_{ЗНАЧЕНИЕ ПАРАМЕТРА ACTION!!}
add_action( 'wp_ajax_nopriv_get-cart-total', 'get_cart_total' );  // wp_ajax_nopriv_{ЗНАЧЕНИЕ ACTION!!}
// первый хук для авторизованных, второй для не авторизованных пользователей

function get_cart_total(){
	wp_die( json_encode([
		'shipping' => WC()->cart->get_cart_shipping_total(),
		'subtotal' => WC()->cart->get_cart_subtotal(),
		'total' => WC()->cart->get_total(),
	]) );
}

<?php
/**
 * Checkout Form
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/checkout/form-checkout.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see https://docs.woocommerce.com/document/template-structure/
 * @package WooCommerce/Templates
 * @version 3.5.0
 */

if (!defined('ABSPATH')) {
    exit;
}

$product_types = [];

function print_shopping_bag( $cart_item_key, $cart_item ) {
    $_product = apply_filters('woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key);
    $product_id = apply_filters('woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key);

    if ($_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters('woocommerce_cart_item_visible', true, $cart_item, $cart_item_key)) {
        $product_permalink = apply_filters('woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink($cart_item) : '', $cart_item, $cart_item_key);
        ?>
		<div class="woocommerce-cart-form__cart-item <?php echo esc_attr(apply_filters('woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key)); ?>">
			<div class="product-item-thumbnail">
				<img src="<?php
				$image = wp_get_attachment_image_src( get_post_thumbnail_id( $product_id ), 'single-post-thumbnail' );
				echo $image[0];
				?>" alt="<?= esc_html($_product->get_name()) ?>">
			</div>

			<div class="product-item-info">
				<div class="product-item-info-left">
					<div class="name">
						<a href="<?= $product_permalink ?>">
							<?= $_product->get_name() ?>
						</a>
					</div>

					<?php
					do_action('woocommerce_after_cart_item_name', $cart_item, $cart_item_key);

					// Meta data.
					echo wc_get_formatted_cart_item_data($cart_item); // PHPCS: XSS ok.

					// Backorder notification.
					if ($_product->backorders_require_notification() && $_product->is_on_backorder($cart_item['quantity'])) {
						echo wp_kses_post(apply_filters('woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__('Available on backorder', 'woocommerce') . '</p>', $product_id));
					}
					?>
					<div class="product-item-info-quantity"><?php echo   $cart_item['quantity'] ?> Items</div>
				</div>
				<div class="product-item-info-price">
					<?php echo apply_filters('woocommerce_cart_item_price', WC()->cart->get_product_price($_product), $cart_item, $cart_item_key); // PHPCS: XSS ok. ?>
				</div>
			</div>
		</div>
        <?php
    }
}

foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
    $classes = esc_attr(apply_filters('woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key));
    $classes = trim( str_replace( 'cart_item', '', $classes ) );

    if( !empty( $classes ) ) {
        $product_types['individual'][$cart_item_key] = $cart_item;
    } else {
        $product_types['public'][$cart_item_key] = $cart_item;
    }
}
?>

<div class="woocommerce_pages checkout_page">
    <div class="woo_container ">
    	<div class="rst-progress-wrap">
        	<div class="rst-progress">
            	<div class="rst-progress-item active">
            		<span class="dot"></span>
                    <p>Information</p>
           		 </div>
                 <div class="rst-progress-item">
            		<span class="dot"></span>
                    <p>Payment Method</p>
           		 </div>
                 <div class="rst-progress-item">
            		<span class="dot"></span>
                    <p>Review & Pay</p>
           		 </div>
            </div>
        </div>
		<div class="woo_container_left">
       	 
        	<?php do_action('woocommerce_before_checkout_form', $checkout); ?>

			<form name="checkout"
				  method="post"
				  class="checkout woocommerce-checkout "
				  action="<?php echo esc_url(wc_get_checkout_url()); ?>"
				  enctype="multipart/form-data"
			>

				<?php // If checkout registration is disabled and not logged in, the user cannot checkout.
				if (!$checkout->is_registration_enabled() && $checkout->is_registration_required() && !is_user_logged_in()) {
					echo esc_html(apply_filters('woocommerce_checkout_must_be_logged_in_message', __('You must be logged in to checkout.', 'woocommerce')));
					return;
				} ?>
                
				<div class="billing_shipping_block next-block" id="billing-shipping-section">
					<?php if ($checkout->get_checkout_fields()) : ?>

						<?php do_action('woocommerce_checkout_before_customer_details'); ?>


						<?php do_action('woocommerce_checkout_billing'); ?>


						<?php do_action('woocommerce_checkout_after_customer_details'); ?>

					<?php endif; ?>
					<?php do_action( 'woocommerce_checkout_shipping' ); ?>
                    <div class="billing_shipping_action">
                    	<a href="<?php echo wc_get_cart_url(); ?>" class="return_to_cart"><svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5 3.5L5.5 8.5L10.5 13.5" stroke="#415479" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Return to cart</a>
                        <a href="#" class="click_save">Save & continue</a>
                    </div>
				</div>
				
				<div class="payment_block next-block" id="payment-section">
					<h3 class="rst-title-block payment_title "  data-toggle="collapse" href="#collapsePayment" role="button" aria-expanded="false" aria-controls="collapsePayment">
						Payment method
						<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.5595 20.0669L17.8661 11.3736C16.8395 10.3469 15.1595 10.3469 14.1328 11.3736L5.43945 20.0669" stroke="#415479" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg></svg>
					</h3>
					<p class="rst-description-block">All transactions are secure and encrypted.</p>
					<div id="collapsePayment" class="collapse show">
						<div class="payment-inner-wrap">
							<?php do_action('woocommerce_after_checkout_form', $checkout); ?>
						</div>
					</div>
					<div class="billing_shipping_action">
                    	<span></span>
                        <a href="#" class="click_save">Continue to secure payment</a>
                    </div>
				</div>
				<div class="review_pay_block next-block" id="review-pay-section">
					<h3 class="rst-title-block payment_title"  data-toggle="collapse" href="#collapseReviewpay" role="button" aria-expanded="false" aria-controls="collapseReviewpay">
						Review & Pay
						<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.5595 20.0669L17.8661 11.3736C16.8395 10.3469 15.1595 10.3469 14.1328 11.3736L5.43945 20.0669" stroke="#415479" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg></svg>
					</h3>
					<p class="rst-description-block">Double-check your items, shipping, and payment method before placing your secure payment.</p>
					<div id="collapseReviewpay" class="collapse show">
						<div class="payment-inner-wrap">
							<div class="rst-Reviewpay-lists">
								<div class="rst-Reviewpay-item">
									<div class="rst-Reviewpay-item-label">
										Shipping Address
									</div>
									<div class="rst-Reviewpay-item-description">
										<div>Michel Kerbela</div>
										<div>info@healthviber@gmail.com</div>
										<div>AL 35013, United States</div>
										<a href="#billing-shipping-section" class="edit"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 20H21" stroke="#415479" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.5 3.49998C16.8978 3.10216 17.4374 2.87866 18 2.87866C18.2786 2.87866 18.5544 2.93353 18.8118 3.04014C19.0692 3.14674 19.303 3.303 19.5 3.49998C19.697 3.69697 19.8532 3.93082 19.9598 4.18819C20.0665 4.44556 20.1213 4.72141 20.1213 4.99998C20.1213 5.27856 20.0665 5.55441 19.9598 5.81178C19.8532 6.06915 19.697 6.303 19.5 6.49998L7 19L3 20L4 16L16.5 3.49998Z" stroke="#415479" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
									</div>
								</div>
								<div class="rst-Reviewpay-item">
									<div class="rst-Reviewpay-item-label">
										Payment Method
									</div>
									<div class="rst-Reviewpay-item-description">
										<div>Credit card</div>
										<div>4000 1000 0000 0008</div>
										<div>CVV: 000</div>
										<a href="#billing-shipping-section" class="edit"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 20H21" stroke="#415479" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.5 3.49998C16.8978 3.10216 17.4374 2.87866 18 2.87866C18.2786 2.87866 18.5544 2.93353 18.8118 3.04014C19.0692 3.14674 19.303 3.303 19.5 3.49998C19.697 3.69697 19.8532 3.93082 19.9598 4.18819C20.0665 4.44556 20.1213 4.72141 20.1213 4.99998C20.1213 5.27856 20.0665 5.55441 19.9598 5.81178C19.8532 6.06915 19.697 6.303 19.5 6.49998L7 19L3 20L4 16L16.5 3.49998Z" stroke="#415479" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
									</div>
								</div>
								<div class="rst-Reviewpay-item">
									<div class="rst-Reviewpay-item-label">
										Shipping Method
									</div>
									<div class="rst-Reviewpay-item-description">
										<div>Standard Shipping</div>
										<a href="#billing-shipping-section" class="edit"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 20H21" stroke="#415479" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.5 3.49998C16.8978 3.10216 17.4374 2.87866 18 2.87866C18.2786 2.87866 18.5544 2.93353 18.8118 3.04014C19.0692 3.14674 19.303 3.303 19.5 3.49998C19.697 3.69697 19.8532 3.93082 19.9598 4.18819C20.0665 4.44556 20.1213 4.72141 20.1213 4.99998C20.1213 5.27856 20.0665 5.55441 19.9598 5.81178C19.8532 6.06915 19.697 6.303 19.5 6.49998L7 19L3 20L4 16L16.5 3.49998Z" stroke="#415479" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
									</div>
								</div>
							</div>
						</div>
					</div>
				</div>
				<div class="link_buttons">
					<span class="go_paid">
						<?= __( 'Place my order', 'woocommerce' ) ?>
					</span>
				</div>

			</form>
		</div>

		<div class="woo_container_right">
        	<h2 class="rst-title-cart">Order Summary</h2>
			<div class="cart-info">

				<div class="table_block item_block">
					<div class="woocommerce-cart-form__list-cart">
					<?php
                        if( !empty( $product_types['public'] ) ) {
                            foreach ( $product_types['public'] as $cart_item_key => $cart_item ) {
                                print_shopping_bag( $cart_item_key, $cart_item );
                            }
                        } if( !empty( $product_types['individual'] ) ) {
                            foreach ( $product_types['individual'] as $cart_item_key => $cart_item ) {
                                print_shopping_bag( $cart_item_key, $cart_item );
                            }
                        } ?>
					</div>	
					<?php do_action('woocommerce_checkout_before_order_review_heading'); ?>

					<?php do_action('woocommerce_checkout_before_order_review'); ?>

					<div id="order_review" class="woocommerce-checkout-review-order collapse show inner">
                    	 <?php if ( wc_coupons_enabled() ) { ?>
						<form class="woocommerce-coupon-form" action="<?php echo esc_url(wc_get_checkout_url()); ?>" method="post">
							<div class="coupon">
								<label for="coupon_code">
									<?php esc_html_e( 'Have a coupon?', 'woocommerce' ); ?>
								</label>
								<div class="form_coupone">
									<input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Apply coupon code', 'woocommerce' ); ?>" /> <button type="submit" class="button<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_html_e( 'Apply', 'woocommerce' ); ?></button>
								</div>
								<?php
									 $discount = WC()->cart->get_discount_total();
									  if ( $discount > 0 ) {
								?>
								<div class="has-Coupon">
									<span></span><div>You <strong>saved <?php echo wc_price( $discount ); ?></strong> with this coupon!</div>
								</div>
								<?php
									  }
								?>
                                <?php do_action( 'woocommerce_cart_coupon' ); ?>
							</div>
						</form>
                    <?php } ?>
						<?php do_action('woocommerce_checkout_order_review'); ?>
                        
					</div>
					<div class="rst-checkout-action">
                        <span class="to_checkout go_paid">
                            Place my order
                        </span>
                        <a class="to_shop" href="<?= get_permalink( wc_get_page_id( 'shop' ) ) ?>">
                                Continue Shopping
                        </a>
                    </div>
                    <!--
					<div class="checkout_block">
						<div class="item">
							<span class="go_paid">
								PLACE MY ORDER
							</span>
						</div>

						<div class="item">
							<a class="to_shop" href="<?= get_permalink( wc_get_page_id( 'shop' ) ) ?>">
								Continue Shopping
							</a>
						</div>
					</div>
                    -->
				</div>
				<div class="rst-single-meta-link">
                    <ul>
                        <li><a href="/contact-us"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <g clip-path="url(#clip0_2339_1840)">
                        <path d="M8 0C3.57841 0 0 3.578 0 8C0 12.4215 3.578 16 8 16C12.4216 16 16 12.422 16 8C16 3.57841 12.422 0 8 0ZM8 14.8837C4.20431 14.8837 1.11628 11.7957 1.11628 8C1.11628 4.20428 4.20431 1.11628 8 1.11628C11.7957 1.11628 14.8837 4.20428 14.8837 8C14.8837 11.7957 11.7957 14.8837 8 14.8837Z" fill="#415479"></path>
                        <path d="M7.76516 10.1226C7.32288 10.1226 6.96484 10.4911 6.96484 10.9334C6.96484 11.3652 7.31234 11.7442 7.76516 11.7442C8.21797 11.7442 8.57597 11.3652 8.57597 10.9334C8.57597 10.4911 8.20741 10.1226 7.76516 10.1226Z" fill="#415479"></path>
                        <path d="M7.90262 3.9834C6.481 3.9834 5.82812 4.82587 5.82812 5.39449C5.82812 5.80518 6.17563 5.99474 6.45994 5.99474C7.02859 5.99474 6.79694 5.18387 7.87103 5.18387C8.39753 5.18387 8.81878 5.41555 8.81878 5.89996C8.81878 6.46859 8.22906 6.79502 7.88156 7.08987C7.57616 7.35309 7.17603 7.78487 7.17603 8.69049C7.17603 9.23806 7.32347 9.39602 7.75519 9.39602C8.27116 9.39602 8.37647 9.16437 8.37647 8.96424C8.37647 8.41668 8.387 8.10077 8.96619 7.64796C9.2505 7.42684 10.1456 6.71074 10.1456 5.7209C10.1456 4.73105 9.2505 3.9834 7.90262 3.9834Z" fill="#415479"></path>
                        </g>
                        <defs>
                        <clipPath id="clip0_2339_1840">
                        <rect width="16" height="16" fill="white"></rect>
                        </clipPath>
                        </defs>
                        </svg>Ask a question</a></li>
                        <li><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M15.5 10C15.224 10 15 10.224 15 10.5V14H1V8H6.5C6.776 8 7 7.776 7 7.5C7 7.224 6.776 7 6.5 7H1V5H6.5C6.776 5 7 4.776 7 4.5C7 4.224 6.776 4 6.5 4H1C0.448 4 0 4.448 0 5V14C0 14.552 0.448 15 1 15H15C15.552 15 16 14.552 16 14V10.5C16 10.224 15.776 10 15.5 10Z" fill="#415479"></path>
                        <path d="M4.5 10H2.5C2.224 10 2 10.224 2 10.5C2 10.776 2.224 11 2.5 11H4.5C4.776 11 5 10.776 5 10.5C5 10.224 4.776 10 4.5 10Z" fill="#415479"></path>
                        <path d="M15.697 2.53975L12.197 1.03975C12.07 0.98675 11.929 0.98675 11.802 1.03975L8.302 2.53975C8.119 2.61875 8 2.79975 8 2.99975V4.99975C8 7.75075 9.017 9.35875 11.751 10.9338C11.828 10.9777 11.914 10.9998 12 10.9998C12.086 10.9998 12.172 10.9777 12.249 10.9338C14.983 9.36275 16 7.75475 16 4.99975V2.99975C16 2.79975 15.881 2.61875 15.697 2.53975ZM15 4.99975C15 7.30875 14.236 8.57975 12 9.91975C9.764 8.57675 9 7.30575 9 4.99975V3.32975L12 2.04375L15 3.32975V4.99975Z" fill="#415479"></path>
                        <path d="M13.8127 4.10886C13.5977 3.93886 13.2837 3.97186 13.1097 4.18686L11.5377 6.15286L10.9157 5.22286C10.7607 4.99286 10.4497 4.93186 10.2227 5.08386C9.99365 5.23686 9.93065 5.54786 10.0837 5.77686L11.0837 7.27686C11.1727 7.40986 11.3187 7.49186 11.4787 7.49986C11.4857 7.49986 11.4937 7.49986 11.4997 7.49986C11.6507 7.49986 11.7947 7.43186 11.8907 7.31186L13.8907 4.81186C14.0627 4.59586 14.0287 4.28186 13.8127 4.10886Z" fill="#415479"></path></svg>Secure Payment</li>
                        <li><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <g clip-path="url(#clip0_2339_1490)">
                        <path d="M15.8614 7.70499L15.0781 5.34399C14.8748 4.73033 14.3114 4.33366 13.6434 4.33366H11.5461L11.6228 3.70866C11.6568 3.43866 11.5768 3.17133 11.4038 2.97499C11.2311 2.77933 10.9774 2.66699 10.7071 2.66699H2.62811C2.09477 2.66699 1.61077 3.09799 1.54911 3.62466L1.50644 3.95799C1.48344 4.14066 1.61211 4.30766 1.79477 4.33099C1.97977 4.35766 2.14477 4.22533 2.16777 4.04266L2.21077 3.70566C2.23377 3.50733 2.42877 3.33366 2.62811 3.33366H10.7071C10.7871 3.33366 10.8568 3.36299 10.9038 3.41599C10.9514 3.46999 10.9718 3.54399 10.9614 3.62666L10.1808 10.0007H1.43011C1.43011 9.83533 1.31177 9.69066 1.14344 9.66999C0.960441 9.64666 0.794108 9.77699 0.771775 9.95966L0.647441 10.962C0.615441 11.233 0.697108 11.5007 0.871441 11.6963C1.04577 11.8927 1.29177 12.0007 1.56344 12.0007H2.20877C2.21377 12.3317 2.32311 12.6403 2.53844 12.883C2.79544 13.1737 3.16144 13.334 3.56811 13.334C4.33077 13.334 5.02411 12.7457 5.18011 12.0007H10.9558C10.9608 12.3317 11.0701 12.64 11.2848 12.8827C11.5421 13.1737 11.9081 13.334 12.3151 13.334C13.0774 13.334 13.7708 12.7457 13.9271 12.0007H14.6448C15.1841 12.0007 15.6581 11.579 15.7238 11.0413L15.9798 8.95366C16.0328 8.52133 15.9931 8.10133 15.8618 7.70533L15.8614 7.70499ZM15.1464 7.66699H13.1378L13.2961 6.37433C13.2984 6.35733 13.3258 6.33366 13.3394 6.33366H14.7041L15.1464 7.66699ZM11.4648 5.00033H13.6438C14.0254 5.00033 14.3321 5.21233 14.4454 5.55399L14.4831 5.66699H13.3394C12.9871 5.66699 12.6778 5.94199 12.6348 6.29299L12.4714 7.62633C12.4491 7.80899 12.5041 7.99033 12.6224 8.12399C12.7404 8.25699 12.9121 8.33333 13.0944 8.33333H15.3191C15.3394 8.50866 15.3408 8.68833 15.3181 8.87199L15.1798 9.99999H10.8521L11.4644 4.99999L11.4648 5.00033ZM11.0981 11.3337H10.6888L10.7704 10.667H11.6418C11.4084 10.84 11.2194 11.069 11.0981 11.3337ZM10.0174 11.3337H5.17111C5.11844 11.1313 5.02444 10.9437 4.88411 10.785C4.84478 10.7407 4.79877 10.7053 4.75478 10.667H10.0994L10.0174 11.3337ZM2.34811 11.3337H1.56311C1.48311 11.3337 1.41611 11.3057 1.36911 11.253C1.32044 11.1987 1.29944 11.1227 1.30877 11.0413L1.35511 10.667H2.88344C2.65211 10.839 2.46644 11.0673 2.34777 11.3337H2.34811ZM4.54677 11.793C4.48878 12.267 4.04044 12.667 3.56777 12.667C3.35444 12.667 3.16644 12.5867 3.03711 12.4407C2.90577 12.2927 2.84844 12.0913 2.87477 11.8743C2.93311 11.4003 3.38144 11.0003 3.85411 11.0003C4.06744 11.0003 4.25577 11.0807 4.38477 11.2267C4.51611 11.3747 4.57344 11.576 4.54677 11.793ZM13.2938 11.793C13.2354 12.267 12.7871 12.667 12.3148 12.667C12.1014 12.667 11.9131 12.5867 11.7838 12.4407C11.6524 12.2927 11.5951 12.0913 11.6218 11.8743C11.6801 11.4003 12.1284 11.0003 12.6008 11.0003C12.8141 11.0003 13.0024 11.0807 13.1318 11.2267C13.2631 11.3747 13.3204 11.576 13.2938 11.793ZM14.6448 11.3337H13.9181C13.8654 11.1313 13.7714 10.9437 13.6311 10.785C13.5918 10.7407 13.5458 10.7053 13.5018 10.667H15.0984L15.0624 10.9597C15.0381 11.159 14.8428 11.3337 14.6448 11.3337Z" fill="#415479"></path>
                        <path d="M3.01 8.66683C3.01 8.4825 2.861 8.3335 2.67667 8.3335H0.333333C0.149 8.3335 0 8.4825 0 8.66683C0 8.85116 0.149 9.00016 0.333333 9.00016H2.67667C2.861 9.00016 3.01 8.85116 3.01 8.66683Z" fill="#415479"></path>
                        <path d="M1.36458 6.66699C1.18025 6.66699 1.03125 6.81633 1.03125 7.00033C1.03125 7.18433 1.18025 7.33366 1.36458 7.33366H2.88492C3.06925 7.33366 3.21825 7.18433 3.21825 7.00033C3.21825 6.81633 3.06925 6.66699 2.88492 6.66699H1.36458Z" fill="#415479"></path>
                        <path d="M0.723958 5.66667H3.41729C3.60162 5.66667 3.75062 5.51733 3.75062 5.33333C3.75062 5.14933 3.60162 5 3.41729 5H0.723958C0.539625 5 0.390625 5.14933 0.390625 5.33333C0.390625 5.51733 0.539625 5.66667 0.723958 5.66667Z" fill="#415479"></path>
                        </g>
                        <defs>
                        <clipPath id="clip0_2339_1490">
                        <rect width="16" height="16" fill="white"></rect>
                        </clipPath>
                        </defs>
                            </svg>Fast Shipping</li>
                    </ul>
                </div>
				<!--
				<div class="shopping_bag item_block">
					<h3 class="collapsed"
						data-toggle="collapse"
						href="#collapseShippingBag"
						role="button"
						aria-expanded="false"
						aria-controls="collapseShippingBag"
					>
						<?= __( 'Shopping Bag', 'woocommerce' ) ?>
						<svg fill="#197ED0" height="22px" width="22px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 407.437 407.437" xml:space="preserve"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <polygon points="386.258,91.567 203.718,273.512 21.179,91.567 0,112.815 203.718,315.87 407.437,112.815 "></polygon> </g></svg>
					</h3>

					<div id="collapseShippingBag" class="collapse inner">
                        <?php
                        if( !empty( $product_types['public'] ) ) {
                            foreach ( $product_types['public'] as $cart_item_key => $cart_item ) {
                                print_shopping_bag( $cart_item_key, $cart_item );
                            }
                        } if( !empty( $product_types['individual'] ) ) {
                            foreach ( $product_types['individual'] as $cart_item_key => $cart_item ) {
                                print_shopping_bag( $cart_item_key, $cart_item );
                            }
                        } ?>
					</div>
				</div>
				-->

			</div>
			<div class="checkout-right-info">
			    <?php do_action('after_woocommerce_cart_item')?>
			</div>
		</div>

    </div>




    <?php do_action('woocommerce_checkout_after_order_review'); ?>

</div>
# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("patients/", views.patient_list, name="patient_list"),
]
<!-- patients.html -->
<h1>Hospital Patient Records</h1>

<ul>
    {% for patient in patients %}
        <li>
            <strong>{{ patient.first_name }} {{ patient.last_name }}</strong><br>
            Diagnosis: {{ patient.diagnosis }}
        </li>
    {% endfor %}
</ul>
# views.py
from django.shortcuts import render
from .models import Patient

def patient_list(request):
    patients = Patient.objects.all()
    return render(request, "patients.html", {"patients": patients})
from django.db import models

class Patient(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    age = models.IntegerField()
    diagnosis = models.TextField()
    admitted_on = models.DateField(auto_now_add=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"
setwd("//files.wustl.edu/Shares/DOM/ONC/Hirbe_Lab/Diana/UBR5 KO RNASeq/analysis/HOM VS WT_2")
Counts <- read.csv("Counts.csv")
# Remove duplicate rows from Counts
Counts <- Counts[!duplicated(Counts[, 1]), ]
rownames(Counts) <- Counts[, 1]
Counts<- Counts [, -1]

# Calculate row means
row_means <- rowMeans(Counts)

# Order genes by row means in descending order
ordered_counts <- Counts[rev(order(row_means)), ]
#alternative code to the above is (ordered_counts <- Counts[order(row_means, decreasing = TRUE), ])
# Filter out rows with row means less than 10
filtered_counts <- ordered_counts[rowMeans(ordered_counts) >= 10, ]
#save filtered data frame
write.csv(filtered_counts, "filtered_counts.csv")

#prepare metadata telling R the conditions (columns) 
metadata <- data.frame( 
  
  sample_id = colnames(filtered_counts),  # Assuming you have loaded the filtered expression data 
  
  condition = c(rep("UBR5 WT", 3), rep("UBR5 HOM", 3)),  # Treatment conditions 
  
  replicate = c(1, 2, 3, 1, 2, 3)  # Sample replicates 
  
) 

metadata$condition <- factor(metadata$condition, levels = c("UBR5 WT", "UBR5 HOM"))

#Load DESEQ2 for normalization
library(DESeq2) 

#Use the DESeqDataSetFromMatrix function from DESeq2 to create a DESeqDataSet object
dds <- DESeqDataSetFromMatrix(countData = filtered_counts,
                              colData = metadata,
                              design = ~ condition)



#Perform normalization and estimation of dispersions: Use the DESeq() function to perform normalization and estimation of dispersions.

dds <- DESeq(dds)
results <- results(dds, alpha = 0.05)
DEGs <- subset(results, abs(log2FoldChange) > 1 & padj < 0.05)


#save the de_genes data frame
write.csv(DEGs, file = "DEG_HOM_VS_WT.csv",)
write.csv(results, file = "DeseqResults_HOM_VS_WT.csv",)



#create volcano plot
library(ggplot2)

# Add column to classify genes as DEG or not
results_df <- as.data.frame(results)
results_df$gene <- rownames(results_df)
results_df$threshold <- "Unchanged"
results_df$threshold[results_df$padj < 0.05 & abs(results_df$log2FoldChange) > 1] <- "DEG"


library(ggrepel)


# Volcano plot
ggplot(results_df, aes(x = log2FoldChange, y = -log10(padj), color = threshold)) +
  geom_point(alpha = 0.6, size = 1.5) +
  scale_color_manual(values = c("Unchanged" = "grey", "DEG" = "red")) +
  theme_minimal(base_size = 14) +
  labs(title = "Volcano Plot: HOM vs WT",
       x = "log2 Fold Change (HOM vs WT)",
       y = "-log10 Adjusted p-value",
       color = "Gene status") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "black") +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black")


# Select top 50 significant genes by padj
top100 <- results_df[order(results_df$padj), ][1:100, ]

# Volcano plot
ggplot(results_df, aes(x = log2FoldChange, y = -log10(padj), color = threshold)) +
  geom_point(alpha = 0.6, size = 1.5) +
  scale_color_manual(values = c("Unchanged" = "grey", "DEG" = "red")) +
  theme_minimal(base_size = 14) +
  labs(title = "Volcano Plot: HOM vs WT",
       x = "log2 Fold Change (HOM vs WT)",
       y = "-log10 Adjusted p-value",
       color = "Gene status") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "black") +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
  geom_text_repel(data = top100,
                  aes(label = gene),
                  size = 3,
                  max.overlaps = Inf,
                  box.padding = 0.3,
                  point.padding = 0.2,
                  segment.color = "grey50")

write.csv(top100, file = "Top100_HOM_vs_WT.csv", row.names = FALSE)


# Define genes of interest
genes_of_interest <- c("Egfr", "Hsp90ab1", "Map2k2", "Cerk", "Pdgfra", "Tyk2", "Jak1",
                       "Yap1", "Taz", "Kdr", "Aurka", "Pten", "Csf1r","Ptch1", "Smo", "Gli2", "Gli3", "Wnt10a", "Rac2", "Rspo2", "Apc",
                       "Cd274", "Pdcd1", "Id1", "Id3", "Cdh1", "Cdc73", "Hrpt2","Csf1","Golph3", "Cdk1", "Acsl4", "Ptk2b", "Akt1", "Akt2", "Akt3", "Pik3ca", "Pik3c2a", "Pik3cb" , "Pik3c3", "Pik3c2b", "Pik3cd", "Atmin", "Cdkn1a", "Cdk9", "Rela", "Nfkb1", "Nfkb2", "Capza1", "Stat1", "Stat3", "Irf1", "Irf3")

# Subset DEGs for these genes (case-sensitive match!)
genes_subset <- results_df[rownames(results_df) %in% genes_of_interest, ]

# Save genes of interest with stats
write.csv(genes_subset, file = "GenesOfInterest_HOM_vs_WT.csv", row.names = TRUE)

ggplot(results_df, aes(x = log2FoldChange, y = -log10(padj), color = threshold)) +
  geom_point(alpha = 0.6, size = 1.5) +
  scale_color_manual(values = c("Unchanged" = "grey", "DEG" = "red")) +
  theme_minimal(base_size = 14) +
  labs(title = "Volcano Plot: HET vs WT",
       x = "log2 Fold Change (HET vs WT)",
       y = "-log10 Adjusted p-value",
       color = "Gene status") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "black") +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
  geom_text_repel(
    data = genes_subset,
    aes(label = gene),
    color = "black",       # <-- force label text to black
    size = 3,
    max.overlaps = Inf,
    box.padding = 0.3,
    point.padding = 0.2,
    segment.color = "grey50"
  )


# Subset DEGs only
DEGs_df <- as.data.frame(DEGs)
DEGs_df$gene <- rownames(DEGs_df)

# Find overlap between DEGs and genes of interest
genes_subset <- DEGs_df[rownames(DEGs_df) %in% genes_of_interest, ]

# Save overlapping genes with stats
write.csv(genes_subset, file = "GenesOfInterest_DEGs_HOM_vs_WT.csv", row.names = TRUE)

# Volcano plot with labels ONLY for genes of interest that are DEGs
ggplot(results_df, aes(x = log2FoldChange, y = -log10(padj), color = threshold)) +
  geom_point(alpha = 0.6, size = 1.5) +
  scale_color_manual(values = c("Unchanged" = "grey", "DEG" = "red")) +
  theme_minimal(base_size = 14) +
  labs(title = "Volcano Plot: HET vs WT",
       x = "log2 Fold Change (HET vs WT)",
       y = "-log10 Adjusted p-value",
       color = "Gene status") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "black") +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
  geom_text_repel(
    data = genes_subset,
    aes(label = gene),
    color = "black",       # labels in black
    size = 5,
    max.overlaps = Inf,
    box.padding = 0.3,
    point.padding = 0.2,
    segment.color = "grey50"
  )





if (!requireNamespace("clusterProfiler", quietly = TRUE)) {
  BiocManager::install("clusterProfiler")
}
if (!requireNamespace("msigdbr", quietly = TRUE)) {
  install.packages("msigdbr")
}
library(clusterProfiler)
library(msigdbr)


# Convert results to dataframe
res_df <- as.data.frame(results)

# Remove NA log2FC
res_df <- res_df[!is.na(res_df$log2FoldChange), ]

# Create named vector: names = gene symbols, values = log2FC
gene_list <- res_df$log2FoldChange
names(gene_list) <- rownames(res_df)

# Sort decreasing for clusterProfiler
gene_list <- sort(gene_list, decreasing = TRUE)


# Mouse Hallmark gene sets
hallmark_sets <- msigdbr(species = "Mus musculus", category = "H")  # H = Hallmark

# Use as two-column dataframe: gs_name (pathway), gene_symbol
term2gene <- hallmark_sets[, c("gs_name", "gene_symbol")]

# Make sure your DESeq2 results have no NA log2FC
res_df <- as.data.frame(results)
res_df <- res_df[!is.na(res_df$log2FoldChange), ]

# Named vector: names = gene symbols, values = log2FC
gene_list <- res_df$log2FoldChange
names(gene_list) <- rownames(res_df)
gene_list <- sort(gene_list, decreasing = TRUE)


gsea_res <- GSEA(
  geneList = gene_list,
  TERM2GENE = term2gene,  # <- must be dataframe, not list
  pvalueCutoff = 0.1,
  verbose = FALSE
)

# View top pathways
head(as.data.frame(gsea_res))

# Save results
write.csv(as.data.frame(gsea_res), "GSEA_Hallmark_Mouse_HOM_vs_WT.csv", row.names = FALSE)

library(enrichplot)

# Convert GSEA results to dataframe
gsea_df <- as.data.frame(gsea_res)

# Suppose the top (and only) enriched pathway:
top_pathway <- gsea_df$ID[5]  # or use $Description if you prefer

# Classic GSEA plot for the top pathway
gseaplot2(
  gsea_res,
  geneSetID = top_pathway,   # pathway ID
  title = gsea_df$Description[5],  # nice descriptive title
  color = "red"
)
#PLOT HALLMARK PATHWAYS
library(ggplot2)

# Convert GSEA results to dataframe
gsea_df <- as.data.frame(gsea_res)

# Order pathways by NES (normalized enrichment score)
gsea_df <- gsea_df[order(gsea_df$NES, decreasing = TRUE), ]

# Plot ALL enriched pathways
ggplot(gsea_df, aes(x = reorder(Description, NES), y = NES, fill = -log10(p.adjust))) +
  geom_col() +
  coord_flip() +
  labs(
    title = "GSEA: All Enriched Hallmark Pathways",
    x = "Pathway",
    y = "Normalized Enrichment Score (NES)",
    fill = "-log10 adj p-value"
  ) +
  theme_minimal(base_size = 14)


#plot GSEA KEGG, GO, REACTOME --------------------------
# Prepare ranked gene list with Entrez IDs for GSEA
# --------------------------
library(clusterProfiler)
library(org.Mm.eg.db)
library(ReactomePA)

# Convert gene symbols to Entrez IDs
entrez_map <- bitr(names(gene_list), fromType="SYMBOL", toType="ENTREZID", OrgDb=org.Mm.eg.db)
gene_list_df <- merge(entrez_map, data.frame(log2FC = gene_list), by.x="SYMBOL", by.y="row.names")
gene_list_df <- gene_list_df[!duplicated(gene_list_df$ENTREZID), ]
gene_list_named <- gene_list_df$log2FC
names(gene_list_named) <- gene_list_df$ENTREZID

# Sort decreasing for GSEA
gene_list_named <- sort(gene_list_named, decreasing = TRUE)

# --------------------------
# 1) GSEA: KEGG Pathways
# --------------------------
gsea_kegg <- gseKEGG(
  geneList = gene_list_named,
  organism = "mmu",
  minGSSize = 10,
  pvalueCutoff = 0.1,
  verbose = TRUE
)

# Save KEGG GSEA results
write.csv(as.data.frame(gsea_kegg), "GSEA_KEGG_HOM_vs_WT.csv", row.names = FALSE)

# Top 30 KEGG pathways barplot
library(enrichplot)
library(ggplot2)

# Convert gseaResult to dataframe to see top pathways
gsea_df <- as.data.frame(gsea_kegg)

# Select top 30 pathways by NES or pvalue
top30 <- gsea_df[order(gsea_df$NES, decreasing = TRUE)[1:30], ]

# Ridgeplot (shows enrichment distribution for multiple pathways)
ridgeplot(gsea_kegg, showCategory = 30) +
  ggtitle("GSEA: KEGG Top 30 Pathways") +
  theme_minimal(base_size = 14)

# Optional: classic GSEA plot for the top pathway
top_pathway <- top30$ID[1]
gseaplot2(gsea_kegg, geneSetID = top_pathway,
          title = top30$Description[1], color = "red")


# --------------------------
# 2) GSEA: GO Biological Process (BP)
# --------------------------
gsea_go_bp <- gseGO(
  geneList = gene_list_named,
  OrgDb = org.Mm.eg.db,
  ont = "ALL",
  keyType = "ENTREZID",
  minGSSize = 10,
  maxGSSize = 500,
  pvalueCutoff = 0.1,
  verbose = TRUE
)

# Save GO BP GSEA results
write.csv(as.data.frame(gsea_go_bp), "GSEA_GO_BP_HOM_vs_WT.csv", row.names = FALSE)

# Top 30 GO BP pathways barplot
barplot(gsea_go_bp, showCategory = 30, title = "GSEA: GO BP Top 30 Pathways")

# --------------------------
# 3) GSEA: Reactome Pathways
# --------------------------
gsea_reactome <- gsePathway(
  geneList = gene_list_named,
  organism = "mouse",
  minGSSize = 10,
  pvalueCutoff = 0.1,
  verbose = TRUE
)

# Save Reactome GSEA results
write.csv(as.data.frame(gsea_reactome), "GSEA_Reactome_HOM_vs_WT.csv", row.names = FALSE)

# Top 30 Reactome pathways barplot
barplot(gsea_reactome, showCategory = 30, title = "GSEA: Reactome Top 30 Pathways")

# --------------------------


library(ggplot2)
library(dplyr)

# Convert GSEA Reactome results to dataframe
gsea_reactome_df <- as.data.frame(gsea_reactome)

# Select top 30 pathways by NES magnitude
top30_reactome <- gsea_reactome_df %>%
  arrange(desc(abs(NES))) %>%
  slice(1:30)

# Reorder for plotting (highest NES on top)
top30_reactome$Description <- factor(top30_reactome$Description, levels = rev(top30_reactome$Description))

# Plot barplot: NES on x-axis, pathways on y-axis, fill by -log10(padj)
ggplot(top30_reactome, aes(x = NES, y = Description, fill = -log10(p.adjust))) +
  geom_bar(stat = "identity") +
  scale_fill_gradient(low = "red", high = "darkred") +
  theme_minimal(base_size = 14) +
  labs(title = "GSEA: Top 30 Reactome Pathways",
       x = "Normalized Enrichment Score (NES)",
       y = "",
       fill = "-log10(adj.p)")



#ORA Enrichment analysis
### --- DEG-based Over-Representation Analysis (ORA) ---

library(clusterProfiler)
library(org.Mm.eg.db)
library(msigdbr)
library(ReactomePA)
library(enrichplot)
library(ggplot2)
library(dplyr)

# Subset DEGs you already defined
DEGs_df <- as.data.frame(DEGs)
DEGs_df$gene <- rownames(DEGs_df)

# Convert SYMBOL -> ENTREZ
deg_entrez <- bitr(
  DEGs_df$gene,
  fromType = "SYMBOL",
  toType   = "ENTREZID",
  OrgDb    = org.Mm.eg.db
)

# Remove duplicates
deg_entrez <- deg_entrez[!duplicated(deg_entrez$ENTREZID), ]


### --- ORA: GO Biological Process ---
ego_bp <- enrichGO(
  gene          = deg_entrez$ENTREZID,
  OrgDb         = org.Mm.eg.db,
  keyType       = "ENTREZID",
  ont           = "BP",   # Biological Process
  pAdjustMethod = "BH",
  pvalueCutoff  = 0.05,
  qvalueCutoff  = 0.2,
  readable      = TRUE    # back to SYMBOL
)

# Save results
write.csv(as.data.frame(ego_bp), "ORA_GO_BP_HET_vs_WT.csv", row.names = FALSE)

# Plot top 20
dotplot(ego_bp, showCategory = 20) + ggtitle("ORA: GO Biological Process (DEGs)")


### --- ORA: KEGG Pathways ---
ekegg <- enrichKEGG(
  gene          = deg_entrez$ENTREZID,
  organism      = "mmu",
  pvalueCutoff  = 0.05
)

# Save results
write.csv(as.data.frame(ekegg), "ORA_KEGG_HET_vs_WT.csv", row.names = FALSE)

# Plot top 20
dotplot(ekegg, showCategory = 20) + ggtitle("ORA: KEGG Pathways (DEGs)")


### --- ORA: Reactome Pathways ---
ereact <- enrichPathway(
  gene          = deg_entrez$ENTREZID,
  organism      = "mouse",
  pvalueCutoff  = 0.05,
  readable      = TRUE
)

# Save results
write.csv(as.data.frame(ereact), "ORA_Reactome_HET_vs_WT.csv", row.names = FALSE)

# Plot top 20
dotplot(ereact, showCategory = 20) + ggtitle("ORA: Reactome Pathways (DEGs)")


### --- ORA: Hallmark Gene Sets ---
hallmark_sets <- msigdbr(species = "Mus musculus", category = "H")
term2gene <- hallmark_sets[, c("gs_name", "entrez_gene")]
term2gene$entrez_gene <- as.character(term2gene$entrez_gene)

ora_hallmark <- enricher(
  gene          = deg_entrez$ENTREZID,
  TERM2GENE     = term2gene,
  pvalueCutoff  = 0.05
)

# Save results
write.csv(as.data.frame(ora_hallmark), "ORA_Hallmark_HET_vs_WT.csv", row.names = FALSE)

# Plot top 20
dotplot(ora_hallmark, showCategory = 20) + ggtitle("ORA: Hallmark Pathways (DEGs)")


### --- DEG-based ORA: Up vs Downregulated DEGs ---


# Split DEGs
up_DEGs   <- rownames(DEGs[DEGs$log2FoldChange > 1, ])
down_DEGs <- rownames(DEGs[DEGs$log2FoldChange < -1, ])

# Convert SYMBOL -> ENTREZ for both
up_entrez <- bitr(up_DEGs, fromType="SYMBOL", toType="ENTREZID", OrgDb=org.Mm.eg.db)
up_entrez <- up_entrez[!duplicated(up_entrez$ENTREZID), ]

down_entrez <- bitr(down_DEGs, fromType="SYMBOL", toType="ENTREZID", OrgDb=org.Mm.eg.db)
down_entrez <- down_entrez[!duplicated(down_entrez$ENTREZID), ]


### --- ORA: GO Biological Process ---
ego_up <- enrichGO(gene=up_entrez$ENTREZID, OrgDb=org.Mm.eg.db, keyType="ENTREZID",
                   ont="BP", pAdjustMethod="BH", pvalueCutoff=0.05, qvalueCutoff=0.2, readable=TRUE)
ego_down <- enrichGO(gene=down_entrez$ENTREZID, OrgDb=org.Mm.eg.db, keyType="ENTREZID",
                     ont="BP", pAdjustMethod="BH", pvalueCutoff=0.05, qvalueCutoff=0.2, readable=TRUE)

write.csv(as.data.frame(ego_up), "ORA_GO_BP_Upregulated.csv", row.names=FALSE)
write.csv(as.data.frame(ego_down), "ORA_GO_BP_Downregulated.csv", row.names=FALSE)

dotplot(ego_up, showCategory=20) + ggtitle("ORA: GO BP (Upregulated)")
dotplot(ego_down, showCategory=20) + ggtitle("ORA: GO BP (Downregulated)")
                     

### --- ORA: Hallmark Gene Sets ---
hallmark_sets <- msigdbr(species="Mus musculus", category="H")
term2gene <- hallmark_sets[, c("gs_name", "entrez_gene")]
term2gene$entrez_gene <- as.character(term2gene$entrez_gene)

ora_hallmark_up <- enricher(gene=up_entrez$ENTREZID, TERM2GENE=term2gene, pvalueCutoff=0.05)
ora_hallmark_down <- enricher(gene=down_entrez$ENTREZID, TERM2GENE=term2gene, pvalueCutoff=0.05)

write.csv(as.data.frame(ora_hallmark_up), "ORA_Hallmark_Upregulated.csv", row.names=FALSE)
write.csv(as.data.frame(ora_hallmark_down), "ORA_Hallmark_Downregulated.csv", row.names=FALSE)

dotplot(ora_hallmark_up, showCategory=20) + ggtitle("ORA: Hallmark (Upregulated)")
dotplot(ora_hallmark_down, showCategory=20) + ggtitle("ORA: Hallmark (Downregulated)")


### --- ORA: Reactome ---
ereact_up <- enrichPathway(gene=up_entrez$ENTREZID, organism="mouse", pvalueCutoff=0.05, readable=TRUE)
ereact_down <- enrichPathway(gene=down_entrez$ENTREZID, organism="mouse", pvalueCutoff=0.05, readable=TRUE)

write.csv(as.data.frame(ereact_up), "ORA_Reactome_Upregulated.csv", row.names=FALSE)
write.csv(as.data.frame(ereact_down), "ORA_Reactome_Downregulated.csv", row.names=FALSE)

dotplot(ereact_up, showCategory=20) + ggtitle("ORA: Reactome (Upregulated)")
dotplot(ereact_down, showCategory=20) + ggtitle("ORA: Reactome (Downregulated)")



### --- ORA: KEGG ---
ekegg_up <- enrichKEGG(gene=up_entrez$ENTREZID, organism="mmu", pvalueCutoff=0.05)
ekegg_down <- enrichKEGG(gene=down_entrez$ENTREZID, organism="mmu", pvalueCutoff=0.05)

write.csv(as.data.frame(ekegg_up), "ORA_KEGG_Upregulated.csv", row.names=FALSE)
write.csv(as.data.frame(ekegg_down), "ORA_KEGG_Downregulated.csv", row.names=FALSE)

dotplot(ekegg_up, showCategory=20) + ggtitle("ORA: KEGG (Upregulated)")
dotplot(ekegg_down, showCategory=20) + ggtitle("ORA: KEGG (Downregulated)")



#Heatmap
ifna_genes <- c(
  "Serpine2","Sntb1","Mmp14","Tnc","Fstl1","Vcan","Il15","Scg2","Ecm1","Vegfa",
  "Cxcl12","Dst","Tgfbr3","Ptx3","Pcolce","Spock1","Adam12","Tagln","Loxl1","Cdh6",
  "Pvr","Gadd45b","Gadd45a","Rhob","Rgs4","Fzd8","Tfpi2","Vegfc","Oxtr","Dab2",
  "Lum","Col16a1","Tnfrsf11b","Fap","Matn2","Snai2","Cxcl5","Calu","Capg","Emp3",
  "Nnmt","Gpc1","Tnfaip3","Nid2","Mcm7","Slit3","Slit2","Matn3","Fmod","Edil3",
  "Dkk1","Qsox1","Copa","Cxcl15","Crlf1","Grem1","Fbln5","Sgcb","Sgcg","Sgcd",
  "Plod2","Plod3","Foxc2","Sdc1","Sdc4","Dpysl3","Tnfrsf12a","Pdlim4","Mfap5","Col5a3",
  "P3h1","Cadm1","Fstl3","Efemp2","Cap2","Gpx7","Cthrc1","Basp1","Glipr1","Lrrc15",
  "Pcolce2","Colgalt1","Postn","Htra1","Pmepa1","Myl9","Slc6a8","Magee1","Wipf1","Fermt2",
  "Abi3bp","Ntm","Tpm4","Ecm2","Anpep","Gm21451","Acta2","Aplp1","Areg","Bdnf",
  "Bgn","Bmp1","Cald1","Serpinh1","Cd44","Cdh2","Col11a1","Col12a1","Col3a1","Col4a1",
  "Col4a2","Col5a1","Col5a2","Col6a2","Col6a3","Col7a1","Col8a2","Col1a1","Col1a2","Comp",
  "Ccn1","Sfrp4","Sfrp1","Mylk","Dcn","Eln","Eno2","Fas","Fbln1","Fbln2",
  "Fbn1","Fbn2","Fgf2","Ccn2","Flna","Fn1","Fuca1","Gas1","Gja1","Id2",
  "Igfbp2","Igfbp3","Igfbp4","Il6","Inhba","Itga2","Itga5","Itgav","Itgb1","Itgb3",
  "Itgb5","Jun","Lgals1","Lox","Lrp1","Mest","Mgp","Mmp2","Mmp3","Msx1","Notch2",
  "Pdgfrb","Pfn2","Serpine1","Plaur","Pmp22","Prrx1","Ppib","Pthlh","Sat1","Sparc",
  "Spp1","Tgfb1","Tgm2","Thbs1","Thbs2","Thy1","Timp1","Timp3","Tpm1","Tpm2",
  "Vcam1","Vim","Wnt5a","Cdh11","Nt5e","Gem","Lama1","Plod1","Lama3","Lama2",
  "Lamc2","Lamc1","Tgfbi"
)



# Get normalized counts from DESeq2
norm_counts <- counts(dds, normalized=TRUE)

# Subset for IFN-α response genes (keep only genes present in your dataset)
ifna_counts <- norm_counts[rownames(norm_counts) %in% ifna_genes, ]

# Optionally, z-score normalize each gene for heatmap visualization
ifna_counts_z <- t(scale(t(ifna_counts)))


# Create annotation for columns
ann_col <- data.frame(
  Condition = metadata$condition
)
rownames(ann_col) <- metadata$sample_id


library(pheatmap)

# Make sure columns are in your desired order
desired_order <- c("sample.WT_1", "sample.WT_2", "sample.WT_3",
                   "sample.neg.neg_1", "sample.neg.neg_2", "sample.neg.neg_3")
ifna_counts_z <- ifna_counts_z[, desired_order]

# Make sure annotation matches
ann_col <- ann_col[desired_order, , drop = FALSE]

# Heatmap
pheatmap(ifna_counts_z,
         annotation_col = ann_col,
         show_rownames = TRUE,
         show_colnames = TRUE,
         cluster_rows = TRUE,
         cluster_cols = FALSE,   # keep the column order fixed
         scale = "row",
         fontsize_row = 8,
         main = "Interferon Alpha Response Genes")


class NW_PayslipGenerateReport
{
    public static System.IO.Stream getPayslipReport(date _from, date _to, hcmWorkerRecid worker)
    {
        NWPY_PayslipReportContract contract = new NWPY_PayslipReportContract();
        SRSPrintDestinationSettings settings;
        SrsReportEMailDataContract  emailContract;
        System.IO.MemoryStream      _strem;
        SysMailerMessageBuilder mailer = new SysMailerMessageBuilder();
        SysMailerSMTP smtp = new SysMailerSMTP();
        Filename filename;
        Array arrayfiles;
        System.Byte[] reportBytes = new System.Byte[0]();
        SRSProxy srsProxy;
        SrsReportRunService srsreportRunService = new SrsReportRunService();
        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;
        Map reportParametersMap;
        SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();
        SrsReportRunController controller = new SrsReportRunController();

        filename = 'Payslip.PDF';
        contract.ParmFromDate(_from);
        contract.parmToDate(_to);
        contract.parmEmployee(worker);

        controller.parmReportName(ssrsReportStr(NWPY_PayslipReport, PrecisionDesign2));
        controller.parmShowDialog(false);
        controller.parmReportContract().parmRdpContract(contract);
        settings = controller.parmReportContract().parmPrintSettings();
        settings.printMediumType(SRSPrintMediumType::File);
        settings.fileFormat(SRSReportFileFormat::PDF);
        settings.overwriteFile(true);
        settings.fileName(filename);
        controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());
        controller.parmReportContract().parmReportExecutionInfo(executionInfo);
        srsreportRunService.getReportDataContract(controller.parmReportContract().parmReportName());
        srsreportRunService.preRunReport(controller.parmReportContract());
        reportParametersMap =  srsreportRunService.createParamMapFromContract(controller.parmReportContract());
        parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);
        srsProxy = SRSProxy::constructWithConfiguration(controller.parmReportContract().parmReportServerConfig());
        reportBytes = srsProxy.renderReportToByteArray(controller.parmReportContract().parmReportPath(),
                        parameterValueArray,
                        settings.fileFormat(),
                        settings.deviceInfo());
        if(reportBytes)
        {
            _strem = new System.IO.MemoryStream(reportBytes);
        }
        return _strem;
    }

}
textToTranslate = "Syed Ali Nayyar Nasir";

targetLang = "ar";

// Arabic

apiKey = "AIzaSyCtqtqWGfnZ1EAYXD9pGhQoZ6QtkflC270";

// replace with your actual key

url = "https://translation.googleapis.com/language/translate/v2?key=" + apiKey;

params = Map();

params.put("q",textToTranslate);

params.put("target",targetLang);

params.put("source","en");

// optional

headers = Map();

headers.put("Content-Type","application/x-www-form-urlencoded");

response = invokeurl

[

	url :url

	type :POST

	parameters:params

	headers:headers

];

info response;

translation = response.get("data").get("translations").get(0).get("translatedText");

info translation;
 
Metaverse development helps startups cut costs by building virtual spaces instead of physical ones. It boosts customer engagement with immersive 3D experiences and seamless global networking. Startups can explore new revenue through NFTs and digital assets. By adopting future-ready tech, they attract investors and drive rapid growth.
1️⃣ Ver qué paquete es
bash
apt list --upgradable
Esto te mostrará el nombre y la versión nueva disponible.

2️⃣ Actualizarlo
Si quieres actualizar solo ese paquete:

bash
sudo apt install nombre-del-paquete
(reemplaza nombre-del-paquete por el que te mostró el comando anterior)

Si prefieres actualizar todo lo pendiente (aunque sea solo uno):

bash
sudo apt update
sudo apt upgrade
o, para que no te pregunte confirmación:

bash
sudo apt update && sudo apt upgrade -y
💡 Tip extra para Mint/Debian: Si quieres que también se actualicen dependencias que cambian de versión o paquetes que requieren eliminar otros, usa:

bash
sudo apt full-upgrade
1️⃣ Repositorio de pgAdmin4 sin fichero de Publicación
Ese error significa que el repo ya no es válido o no está preparado para tu versión de Linux Mint. Solución: quitarlo o corregirlo.

Para quitarlo:

bash
sudo rm /etc/apt/sources.list.d/pgadmin4.list
sudo apt update
(Si el archivo tiene otro nombre, revisa todos con ls /etc/apt/sources.list.d/ y elimina el que contenga pgadmin)

Si quieres mantenerlo, revisa la documentación oficial de pgAdmin para añadir el repo correcto para tu versión.

2️⃣ Error de GPG con Visual Studio Code (NO_PUBKEY EB3E94ADBE1229CF)
Esto pasa porque falta la clave pública para verificar el repo de Microsoft.

Solución rápida:

bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EB3E94ADBE1229CF
o, con el método moderno (recomendado):

bash
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /usr/share/keyrings/microsoft.gpg > /dev/null
Luego edita el archivo del repo:

bash
sudo nano /etc/apt/sources.list.d/vscode.list
y cambia la línea para que use la clave:

Código
deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/code stable main
Guarda, cierra y actualiza:

bash
sudo apt update
sudo apt update
sudo apt install plasma-discover
green on black por Felix Hummel
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
# ~/.zshrc

# Si vienes de bash, quizás necesites cambiar tu $PATH.
# export PATH=$HOME/bin:$HOME/.local/bin:/usr/local/bin:$PATH

# Path a tu instalación de Oh My Zsh
export ZSH="$HOME/.oh-my-zsh"

# Tema: Powerlevel10k (instalado manualmente en ~/.powerlevel10k)
# ZSH_THEME="robbyrussell"

# Enable Powerlevel10k instant prompt. Debe estar al inicio del archivo
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

# Alias para ani-cli en Zsh
alias ani-es="ani-cli --dub"
alias ani-es-continuar="ani-cli -c --dub"
alias ani-es-calidad="ani-cli --dub --quality-select"

# Lista de plugins - SOLO UNA DEFINICIÓN
plugins=(
  git
  zsh-autosuggestions
  zsh-syntax-highlighting
  sudo
  history-substring-search
  colored-man-pages
  composer
  laravel
  docker
  extract
)

source $ZSH/oh-my-zsh.sh

# Cargar Powerlevel10k (instalado manualmente)
source ~/.powerlevel10k/powerlevel10k.zsh-theme

# Cargar configuración de Powerlevel10k
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

# Tus funciones personalizadas...
function indicadores() {
  cd /var/www/html/jobran/indicadores/ && ls -lt --color=auto
}
function proyectos() {
  cd /var/www/html/jobran/ && ls -lt --color=auto
}

php-server() {
  local framework=$1
  local port=${2:-8000}
  local ruta=$3
  case "$framework" in
    yii2)
      ruta=${ruta:-backend/web}
      php -S localhost:$port -t "$ruta"
      ;;
    laravel)
      ruta=${ruta:-public}
      php -S localhost:$port -t "$ruta"
      ;;
    *)
      echo "⚠️ Framework no reconocido: '$framework'"
      echo "Usa: yii2 o laravel"
      ;;
  esac
}

# Activar globbing avanzado
setopt extendedglob
setopt globdots
setopt nomatch

# Alias Laravel
alias art="php artisan"
alias tinker="php artisan tinker"
alias serve="php artisan serve"
alias migrate="php artisan migrate"
alias seed="php artisan db:seed"
alias fresh="php artisan migrate:fresh --seed"

# Alias para el menú de comandos
alias cmd="comandos"
alias ayuda="comandos"

# Alias Composer
alias cdu="composer dump-autoload"
alias ci="composer install"
alias cu="composer update"

# Alias PostgreSQL
alias psqlc="psql -h localhost -U postgres -W"
alias pgstart="sudo systemctl start postgresql"
alias pgstop="sudo systemctl stop postgresql"
alias pgrestart="sudo systemctl restart postgresql"
alias pgstatus="sudo systemctl status postgresql"
alias psql-iniciar="psql -h localhost -U postgres -W"

# 🔧 ALIAS ÚTILES

# Navegación mejorada
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias ll='ls -la'
alias la='ls -A'
alias l='ls -CF'

# Seguridad
alias rm='rm -i'           # Confirmar antes de eliminar
alias cp='cp -i'           # Confirmar antes de sobrescribir
alias mv='mv -i'           # Confirmar antes de mover

# Desarrollo (alias adicionales)
alias c='composer'

# Git simplificado
alias gs='git status'
alias ga='git add'
alias gc='git commit -m'
alias gp='git push'
alias gl='git log --oneline --graph'

# Sistema
alias update='sudo apt update && sudo apt upgrade -y'
alias reboot='sudo reboot'
alias shutdown='sudo shutdown -h now'
alias ports='sudo netstat -tulpn'

# Crear y entrar a directorio
mkcd() {
    mkdir -p "$1" && cd "$1"
}

# Buscar archivo por contenido
findin() {
    grep -r "$1" . --color=always
}



# ═══════════════════════════════════════════════════════════════
# MENÚ INTERACTIVO DE COMANDOS
# ═══════════════════════════════════════════════════════════════

comandos() {
  local option
  local cmd
  local args
  while true; do
    clear
    echo "╔═══════════════════════════════════════════════════════════╗"
    echo "║           📚 MENÚ DE COMANDOS - ZSHRC                     ║"
    echo "╠═══════════════════════════════════════════════════════════╣"
    echo "║  1.  🎬 Ani-cli (Anime)                                   ║"
    echo "║  2.  🚀 Laravel & Composer                                ║"
    echo "║  3.  📁 Navegación y Archivos                             ║"
    echo "║  4.  🔧 Tmux (Gestión de sesiones)                        ║"
    echo "║  5.  🐘 PostgreSQL                                        ║"
    echo "║  6.  🌐 PHP Server (Yii2/Laravel)                         ║"
    echo "║  7.  🛡️ Sistema y Seguridad                               ║"
    echo "║  8.  📊 Git                                               ║"
    echo "║  9.  📋 Todos los comandos                                ║"
    echo "║  0.  Salir                                                ║"
    echo "╚═══════════════════════════════════════════════════════════╝"
    echo ""
    read "option?Selecciona una opción [0-9]: "

    case $option in
      1)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  🎬 ANI-CLI - Ver Anime                                   ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. ani-es              → Ver anime en español latino     ║"
        echo "║  2. ani-es-continuar    → Continuar viendo anime          ║"
        echo "║  3. ani-es-calidad      → Elegir calidad de video         ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-3] o Enter para volver: "
        case $cmd in
          1) ani-es ;;
          2) ani-es-continuar ;;
          3) ani-es-calidad ;;
          *) ;;
        esac
        ;;
      2)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  🚀 LARAVEL & COMPOSER                                    ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. art                 → php artisan                     ║"
        echo "║  2. tinker              → php artisan tinker              ║"
        echo "║  3. serve               → php artisan serve               ║"
        echo "║  4. migrate             → php artisan migrate             ║"
        echo "║  5. seed                → php artisan db:seed             ║"
        echo "║  6. fresh               → migrate:fresh --seed            ║"
        echo "║  7. cdu                 → composer dump-autoload          ║"
        echo "║  8. ci                  → composer install                ║"
        echo "║  9. cu                  → composer update                 ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-9] o Enter para volver: "
        case $cmd in
          1) art ;;
          2) tinker ;;
          3) serve ;;
          4) migrate ;;
          5) seed ;;
          6) fresh ;;
          7) cdu ;;
          8) ci ;;
          9) cu ;;
          *) ;;
        esac
        ;;
      3)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  📁 NAVEGACIÓN Y ARCHIVOS                                 ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. ..                  → Subir 1 nivel                   ║"
        echo "║  2. ...                 → Subir 2 niveles                 ║"
        echo "║  3. ....                → Subir 3 niveles                 ║"
        echo "║  4. ll                  → ls -la (lista detallada)        ║"
        echo "║  5. la                  → ls -A (todos menos . y ..)      ║"
        echo "║  6. l                   → ls -CF (formato columnas)       ║"
        echo "║  7. indicadores         → Ir a carpeta indicadores        ║"
        echo "║  8. proyectos           → Ir a carpeta proyectos          ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-8] o Enter para volver: "
        case $cmd in
          1) .. ;;
          2) ... ;;
          3) .... ;;
          4) ll ;;
          5) la ;;
          6) l ;;
          7) indicadores ;;
          8) proyectos ;;
          *) ;;
        esac
        ;;
      4)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  🔧 TMUX - GESTIÓN DE SESIONES                            ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. tmux-nuevo          → Nueva sesión                    ║"
        echo "║  2. tmux-listar         → Listar sesiones activas         ║"
        echo "║  3. tmux-conectar       → Última sesión                   ║"
        echo "║  4. tmux-dev            → Sesión 'dev'                    ║"
        echo "║  5. tmux-work           → Sesión 'work'                   ║"
        echo "║  6. tmux-prod           → Sesión 'prod'                   ║"
        echo "║  7. tmux-ayuda          → Mostrar ayuda completa          ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-7] o Enter para volver: "
        case $cmd in
          1) tmux-nuevo ;;
          2) tmux-listar ;;
          3) tmux-conectar ;;
          4) tmux-dev ;;
          5) tmux-work ;;
          6) tmux-prod ;;
          7) tmux-ayuda ;;
          *) ;;
        esac
        ;;
      5)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  🐘 POSTGRESQL                                            ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. psqlc               → Conectar a PostgreSQL           ║"
        echo "║  2. pgstart             → Iniciar servicio                ║"
        echo "║  3. pgstop              → Detener servicio                ║"
        echo "║  4. pgrestart           → Reiniciar servicio              ║"
        echo "║  5. pgstatus            → Ver estado del servicio         ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-5] o Enter para volver: "
        case $cmd in
          1) psqlc ;;
          2) pgstart ;;
          3) pgstop ;;
          4) pgrestart ;;
          5) pgstatus ;;
          *) ;;
        esac
        ;;
      6)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  🌐 PHP SERVER - Yii2 / Laravel                           ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. php-server laravel                                    ║"
        echo "║  2. php-server laravel [puerto]                           ║"
        echo "║  3. php-server yii2                                       ║"
        echo "║  4. php-server yii2 [puerto]                              ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-4] o Enter para volver: "
        case $cmd in
          1) php-server laravel ;;
          2) read "args?Puerto: "; php-server laravel $args ;;
          3) php-server yii2 ;;
          4) read "args?Puerto: "; php-server yii2 $args ;;
          *) ;;
        esac
        ;;
      7)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  🛡️ SISTEMA Y SEGURIDAD                                   ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. update              → Actualizar sistema              ║"
        echo "║  2. reboot              → Reiniciar sistema               ║"
        echo "║  3. shutdown            → Apagar sistema                  ║"
        echo "║  4. ports               → Ver puertos abiertos            ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-4] o Enter para volver: "
        case $cmd in
          1) update ;;
          2) reboot ;;
          3) shutdown ;;
          4) ports ;;
          *) ;;
        esac
        ;;
      8)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  📊 GIT - CONTROL DE VERSIONES                            ║"
        echo "╠═══════════════════════════════════════════════════════════╣"
        echo "║  1. gs                  → git status                      ║"
        echo "║  2. ga                  → git add                         ║"
        echo "║  3. gc                  → git commit                      ║"
        echo "║  4. gp                  → git push                        ║"
        echo "║  5. gl                  → git log (grafo)                 ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        read "cmd?Ejecutar comando [1-5] o Enter para volver: "
        case $cmd in
          1) gs ;;
          2) ga ;;
          3) read "args?Mensaje: "; gc "$args" ;;
          4) gp ;;
          5) gl ;;
          *) ;;
        esac
        ;;
      9)
        clear
        echo "╔═══════════════════════════════════════════════════════════╗"
        echo "║  📋 TODOS LOS COMANDOS - RESUMEN COMPLETO                 ║"
        echo "╚═══════════════════════════════════════════════════════════╝"
        echo ""
        echo "🎬 ANI-CLI:    ani-es | ani-es-continuar | ani-es-calidad"
        echo "🚀 LARAVEL:    art | tinker | serve | migrate | seed | fresh | cdu | ci | cu"
        echo "📁 NAVEGACIÓN: .. | ... | .... | ll | la | l | mkcd | findin | indicadores | proyectos"
        echo "🔧 TMUX:       tmux-nuevo | tmux-listar | tmux-conectar | tmux-dev | tmux-work"
        echo "🐘 POSTGRESQL: psqlc | pgstart | pgstop | pgrestart | pgstatus"
        echo "🌐 PHP SERVER: php-server laravel|yii2 [puerto] [ruta]"
        echo "🛡️ SISTEMA:    update | reboot | shutdown | ports"
        echo "📊 GIT:        gs | ga | gc | gp | gl"
        echo ""
        read "Presiona Enter para continuar..."
        ;;
      0)
        clear
        return
        ;;
      *)
        echo "Opción no válida. Presiona Enter para intentar..."
        read
        ;;
    esac
  done
}

# ═══════════════════════════════════════════════════════════════
# TMUX - Alias con nombres descriptivos
# ═══════════════════════════════════════════════════════════════

# --- GESTIÓN DE SESIONES ---
alias tmux-nuevo='tmux'                              # Nueva sesión (auto-nombrada)
alias tmux-nuevo-sesion='tmux new -s'                # Nueva sesión con nombre (uso: tmux-nuevo-sesion nombre)
alias tmux-conectar='tmux attach'                    # Reconectar a última sesión
alias tmux-conectar-sesion='tmux attach -t'          # Reconectar a sesión específica (uso: tmux-conectar-sesion nombre)
alias tmux-listar='tmux ls'                          # Listar sesiones activas
alias tmux-matar='tmux kill-session -t'              # Matar sesión (uso: tmux-matar nombre)
alias tmux-matar-todas='tmux kill-server'            # Matar todas las sesiones

# --- ATAJOS RÁPIDOS DE SESIONES ---
alias tmux-dev='tmux new -s dev'                     # Sesión de desarrollo
alias tmux-work='tmux new -s work'                   # Sesión de trabajo
alias tmux-prod='tmux attach -t prod 2>/dev/null || tmux new -s prod'  # Sesión de producción (conecta o crea)

# --- FUNCIONES PARA GESTIÓN DE PANELES Y VENTANAS ---
# Dividir pantalla verticalmente (izquierda/derecha)
tmux-split-v() { tmux split-window -h -t "${1:-}"; }
# Dividir pantalla horizontalmente (arriba/abajo)
tmux-split-h() { tmux split-window -v -t "${1:-}"; }
# Moverse entre paneles
tmux-pane-izq() { tmux select-pane -L -t "${1:-}"; }
tmux-pane-der() { tmux select-pane -R -t "${1:-}"; }
tmux-pane-arriba() { tmux select-pane -U -t "${1:-}"; }
tmux-pane-abajo() { tmux select-pane -D -t "${1:-}"; }

# --- UTILIDADES ---
alias tmux-recargar='tmux source ~/.tmux.conf'             # Recargar configuración
alias tmux-info='tmux info'                                # Información de configuración
alias tmux-debug='tmux list-sessions; echo "---"; tmux list-windows'  # Debug: ver sesiones y ventanas

# --- AYUDA RÁPIDA ---
tmux-ayuda() {
  echo "╔═══════════════════════════════════════════════════════════╗"
  echo "║                    TMUX - COMANDOS                        ║"
  echo "╠═══════════════════════════════════════════════════════════╣"
  echo "║ SESIONES:                                                 ║"
  echo "║   tmux-nuevo           → Nueva sesión                     ║"
  echo "║   tmux-nuevo-sesion X  → Nueva sesión llamada X           ║"
  echo "║   tmux-conectar        → Última sesión                    ║"
  echo "║   tmux-conectar-sesion X → Conectar a sesión X            ║"
  echo "║   tmux-listar          → Listar sesiones                  ║"
  echo "║   tmux-matar X         → Matar sesión X                   ║"
  echo "╠═══════════════════════════════════════════════════════════╣"
  echo "║ ATAJOS:                                                   ║"
  echo "║   tmux-dev             → Sesión 'dev'                     ║"
  echo "║   tmux-work            → Sesión 'work'                    ║"
  echo "║   tmux-prod            → Sesión 'prod'                    ║"
  echo "╠═══════════════════════════════════════════════════════════╣"
  echo "║ DENTRO DE TMUX (Prefijo: Ctrl+b):                         ║"
  echo "║   % → Split vertical  |  \" → Split horizontal            ║"
  echo "║   flechas → Mover paneles  |  z → Maximizar               ║"
  echo "║   c → Nueva ventana  |  n/p → Siguiente/anterior          ║"
  echo "║   d → Desconectar  |  s → Cambiar sesión                  ║"
  echo "║   [ → Scroll  |  ] → Pegar  |  ? → Ayuda                  ║"
  echo "╚═══════════════════════════════════════════════════════════╝"
}

# Mensaje de bienvenida
echo "
╔═══════════════════════════════════════════════════════════╗
║  Bienvenido! Escribe 'cmd' o 'ayuda' para ver el menú     ║
╚═══════════════════════════════════════════════════════════╝
"

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

# The next line updates PATH for the Google Cloud SDK.
if [ -f '/home/jdrodriguezg/google-cloud-sdk/path.zsh.inc' ]; then . '/home/jdrodriguezg/google-cloud-sdk/path.zsh.inc'; fi

# The next line enables shell command completion for gcloud.
if [ -f '/home/jdrodriguezg/google-cloud-sdk/completion.zsh.inc' ]; then . '/home/jdrodriguezg/google-cloud-sdk/completion.zsh.inc'; fi
📌 Globbing en Zsh — Chuleta Rápida
Patrón	Qué hace	Ejemplo
*	Coincide con cualquier cadena (excepto /)	ls *.txt → todos los .txt
?	Coincide con un solo carácter	ls file?.txt → file1.txt, fileA.txt
[abc]	Coincide con uno de los caracteres listados	ls file[12].txt → file1.txt, file2.txt
[a-z]	Coincide con un rango de caracteres	ls file[a-c].txt → filea.txt, fileb.txt
^patrón	Niega el patrón	ls ^*.log → todo menos .log
**	Coincide recursivamente en subdirectorios	ls 
**/*.md → todos los .md en cualquier carpeta
*(.)	Solo archivos regulares	ls *(.)
*(/)	Solo directorios	ls *(/)
*(Lk+100)	Archivos de más de 100 KB	ls *(Lk+100)
*(m-1)	Archivos modificados en el último día	ls *(.m-1)
*(om)	Ordenar por fecha de modificación	ls *(om)
*(oc)	Ordenar por fecha de creación	ls *(oc)
*(On)	Ordenar por nombre	ls *(On)
*(u:usuario:)	Archivos de un usuario específico	ls *(u:jobran:)
💡 Consejos rápidos
Puedes combinar filtros:

zsh
ls **/*.txt(.m-7)   # .txt modificados en los últimos 7 días, en cualquier carpeta
Usa setopt extendedglob en tu ~/.zshrc para habilitar patrones más avanzados.

El globbing de Zsh puede reemplazar muchos usos de find, grep y sort en tareas rápidas.
Item Discount
@PT-1406 or @PT-184 or @PT-1741 or @PT-1742 or @PT-1760 or @PT-1761 or @PT-1740 or @PT-1759 or @PT-1758 or @PT-1745 or @PT-1755 or @PT-1743 or @PT-1757 or @PT-1756 or @PT-2357 or @PT-187 or @PT-186 or @PT-188 or @PT-185 or @PT-189 or @PT-2362 or @PT-2354 or @PT-391 or @PT-257 or @PT-253 or @PT-256 or @PT-254 or @PT-263 or @PT-2497 or @PT-2498 or @PT-2513 or @PT-2514 or @PT-2515 or @PT-2516 or @PT-2517 or @PT-2512 or @PT-2525 or @PT-2526 or @PT-2365 or @PT-2527 or @PT-7648 

Transcation Discount
@PT-10657 or @PT-180 or @PT-1409 or @PT-1410 or @PT-1413 or @PT-1414 or @PT-1415 or @PT-1416 or @PT-1762 or @PT-1417 or @PT-1418 or @PT-1421 or @PT-1747 or @PT-1748 or @PT-182 or @PT-1420 or @PT-1749 or @PT-1751 or @PT-1753 or @PT-1763 or @PT-183 or @PT-179 or @PT-1750 or @PT-1754 or @PT-2361 or @PT-2363 or @PT-2364 or @PT-2358 or @PT-2353 or @PT-1775 

Transfer Out
@PT-1429 or @PT-1425 or @PT-1423 or @PT-1424 or @PT-1405 or @PT-1370 or @PT-1422 or @PT-1404 or @PT-6373 or @PT-6374 or @PT-1411 or @PT-4125 or @PT-4126 or @PT-6369 or @PT-6371 or @PT-6368 or @PT-8633 or @PT-4139 or @PT-10071

Transfer In
@PT-4091 or @PT-9307 or @PT-9306 or @PT-9308 or @PT-9309 or @PT-1843 or @PT-287 

Promotion
@PT-1291 or @PT-524 or @PT-522 or @PT-74 or @PT-382 or @PT-383 or @PT-384 or @PT-77 or @PT-79 or @PT-88 or @PT-89 or @PT-11638 or @PT-9281 or @PT-73 or @PT-75 or @PT-81 or @PT-83 or @PT-85 or @PT-86 or @PT-338 or @PT-78 or @PT-80 or @PT-332 or @PT-6437 or @PT-6454 or @PT-82 or @PT-65 or @PT-392 or @PT-10717 or @PT-10715 or @PT-12604 or @PT-12606 or @PT-12601 or @PT-12603 or @PT-12605 or @PT-10719

Tax
@PT-9974 or @PT-241 or @PT-242 or @PT-1313 or @PT-1312 or @PT-1308 or @PT-1310 or @PT-1311 or @PT-513 or @PT-514 or @PT-515 or @PT-516 or @PT-517 or @PT-1150 or @PT-1292 or @PT-1293 or @PT-1294 or @PT-1295 or @PT-1298 or @PT-1299 

Web Report
@PT-12558 or @PT-12559 or @PT-12560 or @PT-10630 or @PT-10474 or @PT-10631 or @PT-10632 or @PT-6258 or @PT-6259 or @PT-6260 or @PT-7481 or @PT-7580 or @PT-7581 or @PT-7582 or @PT-7608 or @PT-7609 or @PT-7610 or @PT-7611 or @PT-7590 or @PT-7595 or @PT-7598 or @PT-7600 or @PT-7602 or @PT-7603 or @PT-7604 or @PT-7586 or @PT-7587 or @PT-7588 or @PT-7573 or @PT-7576 or @PT-7577 or @PT-7578 or @PT-7584 or @PT-7583 

Display Report
@PT-1188 or @PT-1189 or @PT-1190 or @PT-1191 or @PT-1192 or @PT-1193 or @PT-1194 or @PT-1195 or @PT-1196 or @PT-1197 or @PT-1198 or @PT-1199 or @PT-1200 or @PT-1201 or @PT-1202 or @PT-1203 or @PT-1204 or @PT-1205 or @PT-1206 or @PT-1207 or @PT-1208 or @PT-1209 or @PT-1210 or @PT-1211 or @PT-1212 or @PT-1213 or @PT-1214 or @PT-1215 or @PT-1216 or @PT-1217 or @PT-1218 or @PT-1219 or @PT-1220 or @PT-1221 or @PT-1222 or @PT-1223 or @PT-1224 or @PT-1225 or @PT-1226 or @PT-1227 or @PT-1228 or @PT-1229 or @PT-1230 or @PT-1231 or @PT-1232 or @PT-1233 or @PT-1234 or @PT-1235

Gift
@PT-1184 or @PT-1 or @PT-319 or @PT-5 or @PT-1185 or @PT-63 or @PT-1186 or @PT-1187 or @PT-3 or @PT-4 or @PT-512 or @PT-807 or @PT-1811 or @PT-10449 or @PT-9950 or @PT-321 or @PT-1285 or @PT-10844 or @PT-10499 or @PT-6 or @PT-331 or @PT-12133 or @PT-330 or @PT-8 or @PT-11560 or @PT-11595 

Returns
@PT-344 or @PT-197 or @PT-1060 or @PT-196 or @PT-347 or @PT-346 or @PT-909 or @PT-6834 or @PT-6837 or @PT-6836 or @PT-938 or @PT-8661 or @PT-908 or @PT-12003 or @PT-3500 or  @PT-345 or @PT-333 or @PT-6423 or @PT-976 or @PT-290 or @PT-350 or @PT-367 or @PT-978 or @PT-997 or @PT-977 or @PT-998 or @PT-6838 or @PT-9870 or @PT-10789 or @PT-3497 or @PT-14221 or @PT-4723 or @PT-9688 or @PT-9996 or @PT-16773 or @PT-15283 or @PT-11628 or @PT-6839 or @PT-194 or @PT-10843 or @PT-12177

CRM
@PT-212 or @PT-1360 or @PT-8565 or @PT-8564 or @PT-8563 or @PT-8561 or @PT-208 or @PT-209 or @PT-9937 or @PT-9938 or @PT-297 or @PT-296 or @PT-294 or @PT-232 or @PT-223 or @PT-1365 or @PT-233 or @PT-234 or @PT-236 or @PT-238 or @PT-306 or @PT-307 or @PT-1362 or @PT-229 or @PT-10839 or @PT-467 or @PT-215 or @PT-1363 or @PT-462 or @PT-222 or @PT-465 or @PT-214 or @PT-292 or @PT-293 or @PT-295 or @PT-299 or @PT-291 or @PT-288 or @PT-3154 or @PT-216 or @PT-9928 or @PT-9941 or @PT-298 or @PT-240 or @PT-459 or @PT-1156 or @PT-13490 or @PT-13488  or @PT-13774

Safe Cash Management & Adjust Stock
@PT-161 or @PT-157 or @PT-9981 or @PT-650 or @PT-649 or @PT-651 or @PT-156 or @PT-160 or @PT-652 or @PT-653 or @PT-159 or @PT-158 

Terminal
@PT-594 or @PT-146 or @PT-139 or @PT-151 or @PT-150 or @PT-149 or @PT-152 or @PT-137 or @PT-153 or @PT-144 or @PT-586 or @PT-142 or @PT-140 or @PT-154 or @PT-155 or @PT-138

Transfer Out History, Application log, Top Menu Buttons, Log on to Locations, Cancel from Search Quote screen, Create a Quote using the Sale Menu 'Quote' button, Search quote which will not return any results, Void Quote, Reprint Archive, Item Exchange
@PT-11823 or @PT-5463 or @PT-1767 or @PT-1768 or @PT-1769 or @PT-1085 or @PT-2019 or @PT-1947 or @PT-2032 or @PT-2028 or @PT-12134 or @PT-1317 or @PT-1318 or 

Print Report
@PT-1236 or @PT-1237 or @PT-1238 or @PT-1239 or @PT-1240 or @PT-1241 or @PT-1242 or @PT-1243 or @PT-1244 or @PT-1245 or @PT-1246 or @PT-1247 or @PT-1248 or @PT-1249 or @PT-1250 or @PT-1251 or @PT-1252 or @PT-1253 or @PT-1254 or @PT-1255 or @PT-1256 or @PT-1257 or @PT-1258 or @PT-1259 or @PT-1260 or @PT-1261 or @PT-1262 or @PT-1263 or @PT-1264 or @PT-1265 or @PT-1266 or @PT-1267 or @PT-1276 or @PT-1277 or @PT-1278 or @PT-1279 or @PT-1280 or @PT-1281 or @PT-1282 or @PT-1283 or @PT-1268 or @PT-1269 or @PT-1270 or @PT-1271 or @PT-1272 or @PT-1273 or @PT-1274 or @PT-1275

Rich Product
@PT-460 or @PT-269 or @PT-8130 or @PT-267 or @PT-10493 or @PT-10494 or @PT-10495 or @PT-266 or @PT-1158 or @PT-198 or @PT-10492 or @PT-247 or @PT-1604 or @PT-268 or @PT-1606 or @PT-1605 or @PT-310 or @PT-311 or @PT-312 or @PT-313 or @PT-3151 or @PT-7756 or @PT-7757 or @PT-10850 or @PT-10894 or @PT-6529 or @PT-6544 or @PT-6545 or @PT-15820 or @PT-274 

CustomerDepositAccountEnquiry, Customer Deposit Account Payment, Department Sale, Employee Sale
@PT-2342 or @PT-2343 or @PT-2345 or @PT-2347 or @PT-2350 or @PT-2351 or @PT-9201 or @PT-9212 or @PT-7018 or @PT-252 or @PT-251 or @PT-1154 or @PT-1155 or @PT-264 or @PT-32 or @PT-519 or @PT-518 or @PT-10864 or @PT-10867

Item Sale
@PT-202 or @PT-1371 or @PT-378 or @PT-337 or @PT-199 or @PT-201 or @PT-248 or @PT-13840 or @PT-246 or @PT-200 or @PT-1920 or @PT-1943 or @PT-324 or @PT-328 or @PT-327 or @PT-8719

Void
@PT-1151 or @PT-1944 or @PT-205 or @PT-204 or @PT-206 or @PT-390 or @PT-176 or @PT-277 or @PT-10709 or @PT-1152 or @PT-177 or @PT-10726

Discount Overlap Restrictions
@PT-2574 or @PT-2618 or @PT-2528 or @PT-2616 or @PT-2575 or @PT-2619 or @PT-2531 or @PT-2617 or @PT-2371 or @PT-2612 or @PT-2568 or @PT-2614 or @PT-2373 or @PT-2613 or @PT-2569 or @PT-2615 or @PT-2576 or @PT-2620 or @PT-2529 or @PT-2577 or @PT-2621 or @PT-2532 or @PT-2578 or @PT-2624 or @PT-2530 or @PT-2622 or @PT-2533 or @PT-2579 or @PT-2625

Price Override, Activate Prices
@PT-273 or @PT-271 or @PT-272 or @PT-278 or @PT-279 or @PT-190 or @PT-6965 or @PT-529 or @PT-530 or @PT-531 or @PT-532 or @PT-526 or @PT-528

Loyalty
@PT-342 or @PT-349 or @PT-339 or @PT-351 or @PT-340 or @PT-226 or @PT-227 or @PT-1419 or @PT-228 or @PT-1884 or @PT-1886 or @PT-11911 or @PT-11912 or @PT-11913 or @PT-10485 

Quantity Sale
@PT-12258 or @PT-12264 or @PT-12261 or @PT-12265 or @PT-12262 or @PT-12263 or @PT-12266 or @PT-6514 or @PT-825 or @PT-250 or @PT-162 or @PT-2585 or @PT-2586 or @PT-2587 or @PT-2588 or @PT-2875 or @PT-2876

Sale with Customer Capture, Sale with Salesperson Capture, Tender With Foreign Currency, Transaction search, Tender with Card - Key Entry, Tender With Foreign Currency, Tender Transactions with User tender limits
@PT-1061 or @PT-1149 or @PT-527 or @PT-1019 or @PT-8658 or @PT-8660 or @PT-8659 or @PT-123 or @PT-388 or @PT-357 or @PT-380 or @PT-1859 or @PT-1861 or @PT-1860

Sign on/off
@PT-885 or @PT-1352 or @PT-1353 or @PT-1354 or @PT-1355 or @PT-1820 or @PT-1819 or @PT-3180 or @PT-9287 or @PT-9289 or @PT-9291 or @PT-5514

Automatic Recall Transaction by User, Store/Recall Transaction by User, Store/Recall Transaction, Transaction Stored On SignOut, Reason Configuration With Witness Capturing
@PT-386 or @PT-387 or @PT-168 or @PT-7866 or @PT-169 or @PT-170 or @PT-1153 or @PT-1812 or @PT-1813 or @PT-12120 or @PT-12121 or @PT-12122 or @PT-12123 or @PT-1063 or @PT-1064 or @PT-1068 or @PT-1069 or @PT-1070 or @PT-1075 or @PT-1078 or @PT-1083 or @PT-1084 or @PT-1076 or @PT-1077

Load the Employee Maintenance screen in the pos application, Load the User Maintenance screen in the pos application
@PT-12504 or @PT-5603 or @PT-5604 or @PT-5605 or @PT-5606 or @PT-5607 or @PT-5608 or @PT-538 or @PT-817 or @PT-820 or @PT-818 or @PT-6974 or @PT-6975

Transaction Discount
@PT-262 or @PT-275 or @PT-276 or @PT-265 or @PT-2496 or @PT-2524 or @PT-2495 or @PT-2518 or @PT-2521 or @PT-2522 or @PT-2523 or @PT-2566 or @PT-255 or @PT-258 or @PT-259 or @PT-260 or @PT-261

Transfer Out Container
@PT-9326 or @PT-9327 or @PT-9328 or @PT-9329

Product with selling options, Tender with Cheque, Stock Adjustments Page
@PT-10758 or @PT-2722 or @PT-2723 or @PT-2724 or @PT-2725 or @PT-1301 or @PT-1302 or @PT-1303 or @PT-1300 or  or @PT-12492 or @PT-12493 or @PT-12494 or @PT-12495 or @PT-12496

-------------------------------------------------
@PT-6370 or @PT-1071 or @PT-12172 or @PT-14725 or @PT-1164 or @PT-12260 or @PT-5498 or @PT-5470 or @PT-5472 or @PT-9933 or @PT-9310 or @PT-533 or @PT-4461 or @PT-4485 or @PT-927 or @PT-929 or @PT-803 or @PT-933 or @PT-806 or @PT-1774 or @PT-9213 or @PT-9215 or @PT-9216 or @PT-9217 or @PT-521

@PT-1765 or @PT-8871 or @PT-3506 or @PT-10704 or  or @PT-10727 or @PT-10731 or @PT-11442 or @PT-8696 or @PT-320 or @PT-325 or @PT-5468 or @PT-11940 or @PT-13504 or @PT-12491 or @PT-14164 or @PT-11627 or @PT-1082 or @PT-1080 or @PT-1081 or @PT-4462 or @PT-10602 or @PT-16727 or @PT-11565 or @PT-145 or @PT-5527 or @PT-1074  or @PT-16116 or @PT-16153 or @PT-5458 or @PT-5459 or @PT-5460 or @PT-5461 or @PT-17038

@PT-10601 or @PT-10741 or @PT-10742 or @PT-11533 or @PT-11955 or @PT-12868 or @PT-12885 or @PT-13458 or @PT-13549 or @PT-14165 or @PT-14172 or @PT-14422 or @PT-14464 or @PT-14484 or @PT-16566 or @PT-16643 or @PT-16644 or @PT-16645 or @PT-16646 or @PT-16683 or @PT-16717 or @PT-17478 or @PT-17655 or @PT-18218 or @PT-18667 or @PT-19509 or @PT-19999 or @PT-20000 or @PT-20001 or @PT-21957 or @PT-22038 or @PT-323 or @PT-5465 or @PT-5467 or @PT-6999 or @PT-7000 or @PT-8632 or @PT-887 or @PT-916 or @PT-9744 or @PT-9934


El comando para copiar una carpeta (directorio) de un lugar a otro de manera rápida desde el terminal en Linux es usar cp con la opción -r (recursiva), ya que así se copian todos los archivos y subdirectorios dentro de la carpeta.
La sintaxis básica es:

cp -r /ruta/de/carpeta_origen /ruta/de/carpeta_destino

Esto copiará la carpeta y su contenido mostrando qué se está copiando. Es la forma rápida y común de copiar carpetas en el terminal Linux. La opción -r es obligatoria para copiar directorios.

cp -rv mi_carpeta ~/Escritorio/

Para copiar carpetas de manera más rápida desde el terminal, el comando básico sigue siendo cp -r, pero hay algunas estrategias y alternativas para hacer la copia más eficiente dependiendo del caso:

Usar opciones como -u con cp para copiar solo archivos nuevos o modificados, evitando copiar todo nuevamente y ahorrando tiempo:

text
cp -ru carpeta_origen carpeta_destino
Cómo funciona
Rsync solo copia los archivos que han cambiado o que no están en el destino, lo que hace que las transferencias sean más rápidas y menos costosas en recursos que otros comandos como cp.

Puede copiar directorios completos, preservar permisos, dueños, grupos y enlaces simbólicos.

También puede reanudar transferencias interrumpidas, lo que es útil para conexiones inestables.

Es muy usado para hacer copias de seguridad o sincronizar directorios entre servidores.

Sintaxis básica:
text
rsync [opciones] origen destino
origen y destino pueden ser rutas locales o remotas (usando SSH).

Ejemplo local:

text
rsync -av --progress carpeta_origen/ carpeta_destino/
Donde:

-a es modo archivo (preserva permisos, enlaces, etc.),

-v para modo verbose (muestra el progreso),

--progress muestra progreso detallado.

El comando

tar cf - carpeta_origen | (cd carpeta_destino && tar xf - )
se utiliza para copiar el contenido de un directorio a otro, mientras se crea y extrae un archivo tar "en vuelo", sin dejar un archivo intermedio en el disco.

Explicación paso a paso:
tar cf - carpeta_origen:

tar es la herramienta Linux para agrupar archivos en un archivo llamado "tarball".

c significa "crear" un archivo tar.

f - indica que el archivo tar resultante se enviará a la salida estándar (representado por -), en lugar de a un archivo en disco.

carpeta_origen es el directorio que se empaqueta.

|

Es un pipe que pasa la salida del comando anterior como entrada al siguiente comando.

(cd carpeta_destino && tar xf - ):

cd carpeta_destino cambia al directorio destino donde queremos extraer los archivos.

&& indica que el siguiente comando se ejecuta solo si el anterior fue exitoso.

tar xf - extrae (x) el contenido del archivo tar que llega por la entrada estándar (f -).
Terminal › Integrated › Suggest: Enabled
activar el chack

code ~/.bashrc
[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path bash)"


code ~/.zshrc
[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path zsh)"
star

Fri Sep 19 2025 16:50:47 GMT+0000 (Coordinated Universal Time)

@freepythoncode ##python #coding #python

star

Fri Sep 19 2025 15:44:32 GMT+0000 (Coordinated Universal Time) https://huggingface.co/Alibaba-NLP/Tongyi-DeepResearch-30B-A3B

@GADJI123

star

Fri Sep 19 2025 12:06:55 GMT+0000 (Coordinated Universal Time)

@usman13

star

Fri Sep 19 2025 10:37:23 GMT+0000 (Coordinated Universal Time) https://maticz.com/zk-tech-development

@carolinemax

star

Fri Sep 19 2025 07:17:23 GMT+0000 (Coordinated Universal Time)

@usman13

star

Thu Sep 18 2025 16:01:46 GMT+0000 (Coordinated Universal Time)

@jrg_300i #docker

star

Thu Sep 18 2025 07:21:38 GMT+0000 (Coordinated Universal Time)

@shubhangi.b

star

Thu Sep 18 2025 06:35:14 GMT+0000 (Coordinated Universal Time) https://www.addustechnologies.com/crypto-trading-bot-development-company

@brucebanner #crypto #trading #bot

star

Thu Sep 18 2025 03:23:13 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Wed Sep 17 2025 13:11:10 GMT+0000 (Coordinated Universal Time) http://www.vbaexpress.com/kb/getarticle.php?kb_id=188

@szkohn #vba

star

Wed Sep 17 2025 09:26:36 GMT+0000 (Coordinated Universal Time)

@shubhangi.b

star

Wed Sep 17 2025 06:47:22 GMT+0000 (Coordinated Universal Time)

@shubhangi.b

star

Wed Sep 17 2025 06:36:49 GMT+0000 (Coordinated Universal Time) https://cryptiecraft.com/polymarket-clone-script/

@evacollins #polymarketclonescript #predictionmarket #decentralized

star

Tue Sep 16 2025 22:37:24 GMT+0000 (Coordinated Universal Time)

@procodefinder

star

Tue Sep 16 2025 10:43:07 GMT+0000 (Coordinated Universal Time)

@shubhangi.b

star

Tue Sep 16 2025 10:34:18 GMT+0000 (Coordinated Universal Time)

@shubhangi.b

star

Mon Sep 15 2025 09:30:20 GMT+0000 (Coordinated Universal Time)

@2late #css

star

Mon Sep 15 2025 07:30:45 GMT+0000 (Coordinated Universal Time) https://cryptiecraft.com/white-label-crypto-exchange-cost/

@RileyQuinn #white-labelexchange costs

star

Sun Sep 14 2025 23:14:59 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Sun Sep 14 2025 11:42:58 GMT+0000 (Coordinated Universal Time) https://alpharive.com/crypto-exchange-development

@Becca #c++ #c#

star

Sun Sep 14 2025 06:21:25 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Sun Sep 14 2025 06:15:27 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Fri Sep 12 2025 06:59:45 GMT+0000 (Coordinated Universal Time)

@vanthien

star

Fri Sep 12 2025 06:59:45 GMT+0000 (Coordinated Universal Time)

@vanthien

star

Fri Sep 12 2025 06:52:54 GMT+0000 (Coordinated Universal Time)

@vanthien

star

Thu Sep 11 2025 21:58:17 GMT+0000 (Coordinated Universal Time)

@Masiaga01

star

Thu Sep 11 2025 21:55:22 GMT+0000 (Coordinated Universal Time)

@Masiaga01

star

Thu Sep 11 2025 21:53:59 GMT+0000 (Coordinated Universal Time)

@Masiaga01

star

Thu Sep 11 2025 21:41:58 GMT+0000 (Coordinated Universal Time)

@Masiaga01

star

Thu Sep 11 2025 21:17:31 GMT+0000 (Coordinated Universal Time)

@1234_5

star

Thu Sep 11 2025 16:50:44 GMT+0000 (Coordinated Universal Time)

@MinaTimo

star

Thu Sep 11 2025 07:18:10 GMT+0000 (Coordinated Universal Time)

@usman13

star

Thu Sep 11 2025 07:11:10 GMT+0000 (Coordinated Universal Time) https://cryptiecraft.com/kucoin-clone-script/

@RileyQuinn #kucoinclone script #kucoinclone #kucoinclone software #kucoinclone app

star

Wed Sep 10 2025 15:23:23 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Wed Sep 10 2025 15:20:17 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Wed Sep 10 2025 15:03:31 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Wed Sep 10 2025 07:31:16 GMT+0000 (Coordinated Universal Time) https://medium.com/illumination/why-entrepreneurs-choose-okx-clone-script-9dbb7bd40d79

@monroealex17

star

Tue Sep 09 2025 16:31:43 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Tue Sep 09 2025 15:10:39 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Tue Sep 09 2025 15:08:06 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Tue Sep 09 2025 15:00:40 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Tue Sep 09 2025 14:22:47 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Tue Sep 09 2025 13:08:28 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Tue Sep 09 2025 11:05:23 GMT+0000 (Coordinated Universal Time)

@Preminda

star

Mon Sep 08 2025 19:41:57 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Mon Sep 08 2025 19:39:36 GMT+0000 (Coordinated Universal Time)

@jrg_300i

star

Mon Sep 08 2025 19:32:14 GMT+0000 (Coordinated Universal Time)

@jrg_300i

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension