---
name: flower-db-access
description: Read-only database access for the Flower ERP system. Allows querying all tables except authentication/authorization tables. Use this skill to inspect business data, analyze trends, debug issues, or generate reports. All write operations are strictly prohibited.
allowed-tools: Bash(ssh:*), Bash(psql:*), Bash(PGPASSWORD:*)
---

# Flower ERP Database Access (Read-Only)

This skill provides read-only access to the Flower ERP PostgreSQL database for data inspection, analysis, and debugging.

## ⚠️ IMPORTANT: Remote Access Required

**This database is hosted on a remote server. You MUST establish an SSH connection first before accessing the database.**

### SSH Connection Details

- **Remote Server**: `8.148.215.233`
- **SSH Port**: `18762`
- **SSH User**: `root`
- **Authentication**: SSH Key (passwordless)
- **Database Host** (on remote): `127.0.0.1`
- **Database Port**: `5432`

### Step 1: Establish SSH Connection

#### Option A: Interactive SSH Session
```bash
# Connect to remote server (SSH key authentication)
ssh -p 18762 root@8.148.215.233

# Once connected, access the database
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower
```

#### Option B: SSH with Command Execution (Recommended for Agents)
```bash
# Execute single query via SSH
ssh -p 18762 root@8.148.215.233 "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c 'YOUR_QUERY'"
```

#### Option C: SSH Tunnel (For Local Development)
```bash
# Create SSH tunnel to access remote database as if it's local
ssh -p 18762 -L 15432:127.0.0.1:5432 root@8.148.215.233 -N

# In another terminal, connect to the tunneled database
PGPASSWORD=postgres psql -h 127.0.0.1 -p 15432 -U postgres -d flower
```

## Database Connection

**After establishing SSH connection**, connect to the database:

```bash
# Connect to the database (on remote server)
psql -h 127.0.0.1 -p 5432 -U postgres -d flower

# Or with password in one line
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "YOUR_QUERY"
```

**Connection Details (on remote server):**
- Host: `127.0.0.1`
- Port: `5432`
- Database: `flower`
- User: `postgres`
- Password: `postgres`

## Access Rules

### ✅ Allowed Operations

- **SELECT queries** on all business tables
- **Data inspection** for debugging and analysis
- **Aggregate queries** for reporting
- **JOIN queries** across business tables

### ❌ Prohibited Operations

1. **All write operations:**
   - INSERT
   - UPDATE
   - DELETE
   - TRUNCATE
   - DROP
   - ALTER
   - CREATE
   - GRANT
   - REVOKE

2. **Prohibited tables (authentication/authorization):**
   - `auth_user`
   - `auth_permission`
   - `auth_group`
   - `auth_group_permissions`
   - `auth_user_groups`
   - `auth_user_user_permissions`
   - `django_content_type`
   - `django_session`
   - `django_admin_log`

**⚠️ CRITICAL:** Never attempt to read or write to authentication-related tables. Violations will be logged and reported.

## Database Schema Overview

### Core Business Tables

#### Basic Info Module (`basic_info` app)
- `basic_info_merchant` - 商户（多租户）
- `basic_info_customer` - 客户
- `basic_info_supplier` - 供应商
- `basic_info_employee` - 员工
- `basic_info_product` - 产品
- `basic_info_productcategory` - 产品分类
- `basic_info_warehouse` - 仓库
- `basic_info_bankaccount` - 银行账户
- `basic_info_merchantsetting` - 商户设置

#### Business Module (`business` app)
- `business_purchaseorder` - 采购订单
- `business_purchaseorderitem` - 采购订单明细
- `business_salesorder` - 销售订单
- `business_salesorderitem` - 销售订单明细
- `business_purchasereturnorder` - 采购退货单
- `business_purchasereturnorderitem` - 采购退货单明细
- `business_salesreturnorder` - 销售退货单
- `business_salesreturnorderitem` - 销售退货单明细
- `business_paymentorder` - 付款单
- `business_receiptorder` - 收款单
- `business_customerbalance` - 客户余额
- `business_supplierbalance` - 供应商余额
- `business_balancechangerecord` - 余额变动记录

#### Stock Module (`stock` app)
- `stock_stockchangerecord` - 库存变动记录
- `stock_stockchangedetail` - 库存变动明细
- `stock_stockfreeze` - 库存冻结记录
- `stock_inventory` - 库存汇总

#### Printing Module (`printing` app)
- `printing_plateorder` - 开版订单
- `printing_printingorder` - 印染订单
- `printing_printingjob` - 印染任务明细
- `printing_printingjobbatchadvancerecord` - 批量操作记录
- `printing_plateordertiiauploadfailure` - 图片上传失败记录

#### Stateflow Module (`stateflow` app)
- `stateflow_process` - 流程定义
- `stateflow_state` - 流程节点
- `stateflow_businessobject` - 业务对象（流程实例）
- `stateflow_stateflowrecord` - 状态流转记录
- `stateflow_stateparameter` - 状态参数
- `stateflow_statelogparameterrecord` - 参数记录

#### Other Modules
- `shipment_shipment` - 发货单
- `settlement_dailysettlement` - 日结记录
- `api_v1_mdyplateorderstaging` - 明道云开版暂存

## Common Query Examples

**Note**: All queries below assume you're either:
1. Already connected to the remote server via SSH, OR

### Quick Examples with SSH

#### Method 1: Using SSH key authentication
```bash
# List all tables
ssh -p 18762 root@8.148.215.233 \
  "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c '\dt'"

# Query with WHERE clause
ssh -p 18762 root@8.148.215.233 \
  "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c 'SELECT * FROM business_salesorder LIMIT 10'"
```

#### Method: SSH with command execution
```bash
# List all tables
ssh -p 18762 root@8.148.215.233 "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c '\dt'"

# Query recent orders
ssh -p 18762 root@8.148.215.233 "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c 'SELECT id, customer_id, sales_date FROM business_salesorder ORDER BY created_at DESC LIMIT 10'"
```


#### List all tables in a schema
```bash
ssh -p 18762 root@8.148.215.233 \
  "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c '\dt'"

# Or if already in SSH session
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\dt"
```

#### Describe table structure
```bash
ssh -p 18762 root@8.148.215.233 \
  "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c '\d business_purchaseorder'"
```

#### Query recent orders
```bash
ssh -p 18762 root@8.148.215.233 \
  "PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c \"
SELECT id, customer_id, sales_date, status, created_at 
FROM business_salesorder 
ORDER BY created_at DESC 
LIMIT 10;
\""
```

### Query with JOIN
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    so.id,
    so.sales_date,
    c.name as customer_name,
    so.status
FROM business_salesorder so
JOIN basic_info_customer c ON so.customer_id = c.id
ORDER BY so.created_at DESC
LIMIT 10;
"
```

### Aggregate query (statistics)
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    DATE(created_at) as date,
    COUNT(*) as order_count,
    SUM(total_amount) as total_sales
FROM business_salesorder
WHERE status = 2  -- APPROVED
GROUP BY DATE(created_at)
ORDER BY date DESC
LIMIT 7;
"
```

### Search text fields (case-insensitive)
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT id, fabric, craft, customer_id
FROM printing_printingorder
WHERE fabric ILIKE '%棉%'
   OR craft ILIKE '%活性%';
"
```

### Query inventory status
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    p.name as product_name,
    w.name as warehouse,
    si.quantity,
    p.unit
FROM stock_inventory si
JOIN basic_info_product p ON si.product_id = p.id
JOIN basic_info_warehouse w ON si.warehouse_id = w.id
WHERE si.quantity > 0
ORDER BY si.quantity DESC;
"
```

### Query workflow progress
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    po.id as plate_order_id,
    po.style_name,
    p.name as process_name,
    s.name as current_state,
    COUNT(sfr.id) as completed_steps
FROM printing_plateorder po
LEFT JOIN stateflow_businessobject bo ON bo.plate_order_id = po.id
LEFT JOIN stateflow_process p ON bo.process_id = p.id
LEFT JOIN stateflow_stateflowrecord sfr ON sfr.business_object_id = bo.id AND sfr.is_cancelled = false
LEFT JOIN stateflow_state s ON sfr.state_id = s.id
GROUP BY po.id, po.style_name, p.name, s.name
ORDER BY po.created_at DESC
LIMIT 10;
"
```

## Safety Guidelines

### Before Running Queries

1. **Always use SELECT** - Never use INSERT, UPDATE, DELETE, or other modifying commands
2. **Avoid prohibited tables** - Do not query authentication tables
3. **Use LIMIT** - Always add LIMIT clause to prevent large result sets
4. **Test with EXPLAIN** - For complex queries, use EXPLAIN ANALYZE to check performance

### Example with EXPLAIN
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
EXPLAIN ANALYZE
SELECT * FROM business_salesorder WHERE customer_id = 1;
"
```

### Query Best Practices

1. **Use specific columns instead of \***:
   ```sql
   SELECT id, name, created_at FROM basic_info_customer;
   -- Instead of: SELECT * FROM basic_info_customer;
   ```

2. **Add WHERE clauses to filter data**:
   ```sql
   SELECT * FROM business_salesorder 
   WHERE created_at >= '2024-01-01'
   LIMIT 100;
   ```

3. **Use indexes effectively**:
   - Most foreign keys have indexes
   - `created_at`, `updated_at` are commonly indexed
   - Check with `\d table_name` to see indexes

4. **Avoid expensive operations on large tables**:
   - Be careful with `LIKE '%text%'` patterns (cannot use indexes)
   - Use `ILIKE` for case-insensitive matching
   - Consider using `LIMIT` with text searches

## Useful psql Commands

```bash
# List all databases
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -c "\l"

# List all tables in current database
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\dt"

# List all schemas
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\dn"

# Describe table structure
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\d table_name"

# List indexes on a table
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\di table_name"

# View table size
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
"

# Exit psql
\q
```

## Multi-Tenant Considerations

**IMPORTANT:** This is a multi-tenant system. All business tables have a `merchant_id` column.

### Always include merchant_id in queries
```sql
-- Good: Filter by merchant
SELECT * FROM business_salesorder 
WHERE merchant_id = 1 
ORDER BY created_at DESC 
LIMIT 10;

-- Bad: Cross-tenant query
SELECT * FROM business_salesorder LIMIT 10;
```

### Check merchant context
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT id, name, type FROM basic_info_merchant;
"
```

## Common Use Cases

### 1. Debug Order Issues
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    o.*,
    c.name as customer_name
FROM business_salesorder o
JOIN basic_info_customer c ON o.customer_id = c.id
WHERE o.id = 123;
"
```

### 2. Check Inventory Levels
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    p.name,
    w.name as warehouse,
    ss.quantity,
    ss.unit
FROM stock_stocksummary ss
JOIN basic_info_product p ON ss.product_id = p.id
JOIN basic_info_warehouse w ON ss.warehouse_id = w.id
WHERE ss.merchant_id = 1
  AND ss.quantity < 100
ORDER BY ss.quantity ASC;
"
```

### 3. Analyze Sales Trends
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    DATE_TRUNC('week', sales_date) as week,
    COUNT(*) as orders,
    SUM(
        (SELECT SUM(quantity * price) 
         FROM business_salesorderitem 
         WHERE sales_order_id = business_salesorder.id)
    ) as revenue
FROM business_salesorder
WHERE merchant_id = 1
  AND status = 2  -- APPROVED
  AND sales_date >= CURRENT_DATE - INTERVAL '4 weeks'
GROUP BY DATE_TRUNC('week', sales_date)
ORDER BY week DESC;
"
```

### 4. Track Printing Job Progress
```bash
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
SELECT 
    po.human_id,
    po.fabric,
    COUNT(pj.id) as job_count,
    SUM(CASE WHEN pj.business_object_id IS NOT NULL THEN 1 ELSE 0 END) as started_jobs
FROM printing_printingorder po
LEFT JOIN printing_printingjob pj ON pj.printing_order_id = po.id
WHERE po.merchant_id = 1
  AND po.is_invalid = false
GROUP BY po.id, po.human_id, po.fabric
ORDER BY po.created_at DESC
LIMIT 20;
"
```

## Troubleshooting

### Connection refused
```bash
# Check if PostgreSQL is running
sudo systemctl status postgresql

# Or check process
ps aux | grep postgres
```

### Permission denied
```bash
# Check database permissions
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\du"
```

### Query too slow
```bash
# Use EXPLAIN to analyze
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "
EXPLAIN (ANALYZE, BUFFERS) 
YOUR_QUERY_HERE;
"
```

## Emergency Contacts

If you encounter any issues or accidentally attempt a write operation:

1. **STOP** - Do not proceed with the operation
2. **REPORT** - Document what happened
3. **CONTACT** - Notify system administrator immediately

---

**Remember:** This skill provides READ-ONLY access for a reason. The integrity of business data is critical. When in doubt, ask for clarification rather than risk data corruption.
