14 KiB
name, description, allowed-tools
| name | description | allowed-tools |
|---|---|---|
| flower-db-access | 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. | 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
# 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)
# 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)
# 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:
# 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
-
All write operations:
- INSERT
- UPDATE
- DELETE
- TRUNCATE
- DROP
- ALTER
- CREATE
- GRANT
- REVOKE
-
Prohibited tables (authentication/authorization):
auth_userauth_permissionauth_groupauth_group_permissionsauth_user_groupsauth_user_user_permissionsdjango_content_typedjango_sessiondjango_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:
- Already connected to the remote server via SSH, OR
Quick Examples with SSH
Method 1: Using SSH key authentication
# 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
# 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
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
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
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
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)
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)
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
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
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
- Always use SELECT - Never use INSERT, UPDATE, DELETE, or other modifying commands
- Avoid prohibited tables - Do not query authentication tables
- Use LIMIT - Always add LIMIT clause to prevent large result sets
- Test with EXPLAIN - For complex queries, use EXPLAIN ANALYZE to check performance
Example with EXPLAIN
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
-
Use specific columns instead of *:
SELECT id, name, created_at FROM basic_info_customer; -- Instead of: SELECT * FROM basic_info_customer; -
Add WHERE clauses to filter data:
SELECT * FROM business_salesorder WHERE created_at >= '2024-01-01' LIMIT 100; -
Use indexes effectively:
- Most foreign keys have indexes
created_at,updated_atare commonly indexed- Check with
\d table_nameto see indexes
-
Avoid expensive operations on large tables:
- Be careful with
LIKE '%text%'patterns (cannot use indexes) - Use
ILIKEfor case-insensitive matching - Consider using
LIMITwith text searches
- Be careful with
Useful psql Commands
# 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
-- 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
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
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
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
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
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
# Check if PostgreSQL is running
sudo systemctl status postgresql
# Or check process
ps aux | grep postgres
Permission denied
# Check database permissions
PGPASSWORD=postgres psql -h 127.0.0.1 -p 5432 -U postgres -d flower -c "\du"
Query too slow
# 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:
- STOP - Do not proceed with the operation
- REPORT - Document what happened
- 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.