Просмотр исходного кода

创建酒店职位数据表增删改查API
创建酒店集团品牌数据表增删改查API

maxiaolong 4 недель назад
Родитель
Сommit
ef0514a199

+ 204 - 0
README_hotel_positions.md

@@ -0,0 +1,204 @@
+# 酒店职位名称数据表
+
+## 概述
+
+本项目基于 `酒店职位名称20250519.xlsx` 文件中的"汇总版"sheet,创建了标准化的酒店职位数据表。该表包含了酒店行业的标准部门和职位信息,可用于人力资源管理、组织架构设计等用途。
+
+## 数据统计
+
+- **总记录数**: 150条
+- **部门数量**: 9个
+- **职位数量**: 144个不同职位
+- **职级分类**: 3个级别
+
+### 部门分布
+| 部门 | 职位数量 |
+|------|----------|
+| 餐饮部 | 61 |
+| 房务部 | 23 |
+| 市场销售部 | 17 |
+| 人力资源部 | 13 |
+| 财务部 | 13 |
+| 行政办公室 | 8 |
+| 工程部 | 8 |
+| 水疗部 | 4 |
+| 保安部 | 3 |
+
+### 职级分布
+| 职级 | 职位数量 | 占比 |
+|------|----------|------|
+| 经理级 | 120 | 80% |
+| 总监级 | 23 | 15.3% |
+| 总经理级 | 7 | 4.7% |
+
+## 文件说明
+
+### 1. `hotel_positions_ddl.sql`
+PostgreSQL数据库表创建脚本,包含:
+
+- **表结构定义**: 包含所有必要字段和约束
+- **索引创建**: 优化查询性能的索引
+- **中文注释**: 详细的字段和表注释
+- **触发器**: 自动更新`updated_at`字段
+- **统计视图**: 部门和职级统计视图
+- **示例查询**: 常用查询语句示例
+
+### 2. `import_hotel_positions.py`
+数据导入脚本,功能包括:
+
+- 从Excel文件读取数据
+- 数据清理和格式化
+- 批量导入PostgreSQL数据库
+- 导入结果验证和统计
+
+### 3. `read_excel.py` 和 `analyze_more.py`
+数据分析脚本,用于:
+
+- 分析Excel文件结构
+- 统计数据分布
+- 验证数据质量
+
+## 使用方法
+
+### 第一步:创建数据库表
+
+```bash
+# 连接到PostgreSQL数据库
+psql -h localhost -U your_username -d your_database
+
+# 执行DDL脚本
+\i hotel_positions_ddl.sql
+```
+
+### 第二步:导入数据
+
+1. 修改 `import_hotel_positions.py` 中的数据库连接参数:
+
+```python
+connection_params = {
+    'host': 'your_host',
+    'port': 5432,
+    'database': 'your_database_name',
+    'user': 'your_username',
+    'password': 'your_password'
+}
+```
+
+2. 确保Excel文件在当前目录下
+
+3. 运行导入脚本:
+
+```bash
+python import_hotel_positions.py
+```
+
+### 第三步:验证数据
+
+```sql
+-- 查看数据总数
+SELECT COUNT(*) FROM hotel_positions;
+
+-- 查看部门统计
+SELECT * FROM v_hotel_positions_dept_stats;
+
+-- 查看职级统计
+SELECT * FROM v_hotel_positions_level_stats;
+```
+
+## 表结构
+
+### 主要字段
+
+| 字段名 | 类型 | 描述 |
+|--------|------|------|
+| `id` | SERIAL | 主键ID |
+| `sequence_no` | INTEGER | 原Excel序号 |
+| `department_zh` | VARCHAR(10) | 部门中文名称 |
+| `department_en` | VARCHAR(50) | 部门英文名称 |
+| `position_zh` | VARCHAR(20) | 职位中文名称 |
+| `position_en` | VARCHAR(100) | 职位英文名称 |
+| `position_abbr` | VARCHAR(20) | 职位英文缩写(可为空) |
+| `level_zh` | VARCHAR(10) | 职级中文名称 |
+| `level_en` | VARCHAR(30) | 职级英文名称 |
+
+### 审计字段
+
+| 字段名 | 类型 | 描述 |
+|--------|------|------|
+| `created_at` | TIMESTAMP WITH TIME ZONE | 创建时间 |
+| `updated_at` | TIMESTAMP WITH TIME ZONE | 更新时间 |
+| `created_by` | VARCHAR(50) | 创建者 |
+| `updated_by` | VARCHAR(50) | 更新者 |
+| `status` | VARCHAR(20) | 记录状态 |
+
+## 常用查询示例
+
+### 1. 查询特定部门的所有职位
+
+```sql
+SELECT position_zh, position_en, level_zh 
+FROM hotel_positions 
+WHERE department_zh = '餐饮部' AND status = 'active'
+ORDER BY sequence_no;
+```
+
+### 2. 查询高级职位(总监级及以上)
+
+```sql
+SELECT department_zh, position_zh, position_en, level_zh
+FROM hotel_positions 
+WHERE level_zh IN ('总监级', '总经理级') AND status = 'active'
+ORDER BY level_zh DESC, department_zh;
+```
+
+### 3. 查询有英文缩写的职位
+
+```sql
+SELECT department_zh, position_zh, position_en, position_abbr
+FROM hotel_positions 
+WHERE position_abbr IS NOT NULL AND position_abbr != '' 
+  AND status = 'active'
+ORDER BY department_zh;
+```
+
+### 4. 部门职位数量统计
+
+```sql
+SELECT * FROM v_hotel_positions_dept_stats;
+```
+
+### 5. 职级分布统计
+
+```sql
+SELECT * FROM v_hotel_positions_level_stats;
+```
+
+## 维护说明
+
+1. **数据更新**: 当有新的职位或组织结构变化时,更新相应记录的`status`字段
+2. **版本管理**: 建议保留历史数据,通过`status`字段区分有效/无效记录
+3. **定期同步**: 与HR系统定期同步,保持数据一致性
+4. **备份**: 定期备份数据表,确保数据安全
+
+## 依赖要求
+
+### Python环境
+```bash
+pip install pandas openpyxl psycopg2-binary
+```
+
+### PostgreSQL版本
+- PostgreSQL 10.0 或更高版本
+- 支持`COMMENT ON`语句
+- 支持触发器和函数
+
+## 注意事项
+
+1. **字符编码**: 确保数据库和客户端使用UTF-8编码
+2. **空值处理**: `position_abbr`字段允许为空,其他字段均为必填
+3. **索引优化**: 已创建常用查询的索引,如需其他查询模式可添加相应索引
+4. **数据完整性**: 建议添加外键约束连接到其他相关表
+
+## 支持与反馈
+
+如有问题或建议,请联系系统管理员或提交issue。 

+ 33 - 0
analyze_more.py

@@ -0,0 +1,33 @@
+import pandas as pd
+
+# 读取Excel文件
+df = pd.read_excel('酒店职位名称20250519.xlsx', sheet_name='汇总版')
+
+print("=== 更详细的数据分析 ===")
+print(f"总共 {len(df)} 条记录")
+
+print("\n=== 前10行完整数据 ===")
+for i in range(min(10, len(df))):
+    row = df.iloc[i]
+    print(f"第{i+1}行:")
+    for col in df.columns:
+        print(f"  {col}: {row[col]}")
+    print()
+
+print("\n=== 各列唯一值数量 ===")
+for col in df.columns:
+    unique_count = df[col].nunique()
+    print(f"{col}: {unique_count} 个唯一值")
+
+print("\n=== 各列是否有空值 ===")
+for col in df.columns:
+    null_count = df[col].isnull().sum()
+    print(f"{col}: {null_count} 个空值")
+
+print("\n=== 部门统计 ===")
+dept_counts = df['部门(中文)'].value_counts()
+print(dept_counts)
+
+print("\n=== 职级统计 ===")
+level_counts = df['职级(中文)'].value_counts()
+print(level_counts) 

+ 441 - 1
app/api/data_parse/routes.py

@@ -1,6 +1,6 @@
 from flask import jsonify, request, make_response, Blueprint, current_app, send_file
 from app.api.data_parse import bp
-from app.core.data_parse.parse import parse_data, process_business_card, update_business_card, get_business_cards, update_business_card_status, create_talent_tag, get_talent_tag_list, update_talent_tag, delete_talent_tag, query_neo4j_graph, talent_get_tags, talent_update_tags, get_business_card
+from app.core.data_parse.parse import parse_data, process_business_card, update_business_card, get_business_cards, update_business_card_status, create_talent_tag, get_talent_tag_list, update_talent_tag, delete_talent_tag, query_neo4j_graph, talent_get_tags, talent_update_tags, get_business_card, get_hotel_positions_list, add_hotel_positions, update_hotel_positions, query_hotel_positions, delete_hotel_positions, get_hotel_group_brands_list, add_hotel_group_brands, update_hotel_group_brands, query_hotel_group_brands, delete_hotel_group_brands
 from app.config.config import DevelopmentConfig, ProductionConfig
 import logging
 import boto3
@@ -630,3 +630,443 @@ def get_business_card_route(card_id):
     
     return jsonify(result), status_code
 
+@bp.route('/get-hotel-positions-list', methods=['GET'])
+def get_hotel_positions_list_route():
+    """
+    获取酒店职位数据表全部记录的API接口
+    
+    返回:
+        - JSON: 包含酒店职位记录列表和处理状态
+    """
+    try:
+        # 调用业务逻辑函数获取酒店职位列表
+        result = get_hotel_positions_list()
+        
+        # 根据处理结果设置HTTP状态码
+        status_code = 200 if result['success'] else 500
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"获取酒店职位列表时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': [],
+            'count': 0
+        }), 500
+
+@bp.route('/add-hotel-positions', methods=['POST'])
+def add_hotel_positions_route():
+    """
+    新增酒店职位数据表记录的API接口
+    
+    请求参数:
+        - JSON格式,包含以下字段:
+            - department_zh: 部门中文名称 (必填)
+            - department_en: 部门英文名称 (必填)
+            - position_zh: 职位中文名称 (必填)
+            - position_en: 职位英文名称 (必填)
+            - position_abbr: 职位英文缩写 (可选)
+            - level_zh: 职级中文名称 (必填)
+            - level_en: 职级英文名称 (必填)
+            - created_by: 创建者 (可选)
+            - updated_by: 更新者 (可选)
+            - status: 状态 (可选)
+    
+    返回:
+        - JSON: 包含创建结果和职位信息
+    """
+    try:
+        # 获取请求数据
+        data = request.get_json()
+        
+        if not data:
+            return jsonify({
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }), 400
+        
+        # 调用业务逻辑函数处理创建
+        result = add_hotel_positions(data)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 201  # Created
+        elif result['code'] == 400:
+            status_code = 400  # Bad Request
+        elif result['code'] == 409:
+            status_code = 409  # Conflict
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"创建酒店职位记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/update-hotel-positions/<int:position_id>', methods=['PUT'])
+def update_hotel_positions_route(position_id):
+    """
+    修改酒店职位数据表记录的API接口
+    
+    路径参数:
+        - position_id: 职位记录ID
+    
+    请求参数:
+        - JSON格式,可能包含以下字段:
+            - department_zh: 部门中文名称
+            - department_en: 部门英文名称
+            - position_zh: 职位中文名称
+            - position_en: 职位英文名称
+            - position_abbr: 职位英文缩写
+            - level_zh: 职级中文名称
+            - level_en: 职级英文名称
+            - updated_by: 更新者
+            - status: 状态
+    
+    返回:
+        - JSON: 包含更新结果和职位信息
+    """
+    try:
+        # 获取请求数据
+        data = request.get_json()
+        
+        if not data:
+            return jsonify({
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }), 400
+        
+        # 调用业务逻辑函数处理更新
+        result = update_hotel_positions(position_id, data)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 200  # OK
+        elif result['code'] == 400:
+            status_code = 400  # Bad Request
+        elif result['code'] == 404:
+            status_code = 404  # Not Found
+        elif result['code'] == 409:
+            status_code = 409  # Conflict
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"更新酒店职位记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/query-hotel-positions/<int:position_id>', methods=['GET'])
+def query_hotel_positions_route(position_id):
+    """
+    查找指定ID的酒店职位数据表记录的API接口
+    
+    路径参数:
+        - position_id: 职位记录ID
+    
+    返回:
+        - JSON: 包含查找结果和职位信息
+    """
+    try:
+        # 调用业务逻辑函数查找职位记录
+        result = query_hotel_positions(position_id)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 200  # OK
+        elif result['code'] == 404:
+            status_code = 404  # Not Found
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"查找酒店职位记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/delete-hotel-positions/<int:position_id>', methods=['DELETE'])
+def delete_hotel_positions_route(position_id):
+    """
+    删除指定ID的酒店职位数据表记录的API接口
+    
+    路径参数:
+        - position_id: 职位记录ID
+    
+    返回:
+        - JSON: 包含删除结果和被删除的职位信息
+    """
+    try:
+        # 调用业务逻辑函数删除职位记录
+        result = delete_hotel_positions(position_id)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 200  # OK
+        elif result['code'] == 404:
+            status_code = 404  # Not Found
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"删除酒店职位记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/get-hotel-group-brands-list', methods=['GET'])
+def get_hotel_group_brands_list_route():
+    """
+    获取酒店集团子品牌数据表全部记录的API接口
+    
+    返回:
+        - JSON: 包含酒店集团品牌记录列表和处理状态
+    """
+    try:
+        # 调用业务逻辑函数获取酒店集团品牌列表
+        result = get_hotel_group_brands_list()
+        
+        # 根据处理结果设置HTTP状态码
+        status_code = 200 if result['success'] else 500
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"获取酒店集团品牌列表时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': [],
+            'count': 0
+        }), 500
+
+@bp.route('/add-hotel-group-brands', methods=['POST'])
+def add_hotel_group_brands_route():
+    """
+    新增酒店集团子品牌数据表记录的API接口
+    
+    请求参数:
+        - JSON格式,包含以下字段:
+            - group_name_en: 集团英文名称 (必填)
+            - group_name_zh: 集团中文名称 (必填)
+            - brand_name_en: 品牌英文名称 (必填)
+            - brand_name_zh: 品牌中文名称 (必填)
+            - positioning_level_en: 定位级别英文名称 (必填)
+            - positioning_level_zh: 定位级别中文名称 (必填)
+            - created_by: 创建者 (可选)
+            - updated_by: 更新者 (可选)
+            - status: 状态 (可选)
+    
+    返回:
+        - JSON: 包含创建结果和品牌信息
+    """
+    try:
+        # 获取请求数据
+        data = request.get_json()
+        
+        if not data:
+            return jsonify({
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }), 400
+        
+        # 调用业务逻辑函数处理创建
+        result = add_hotel_group_brands(data)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 201  # Created
+        elif result['code'] == 400:
+            status_code = 400  # Bad Request
+        elif result['code'] == 409:
+            status_code = 409  # Conflict
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"创建酒店集团品牌记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/update-hotel-group-brands/<int:brand_id>', methods=['PUT'])
+def update_hotel_group_brands_route(brand_id):
+    """
+    修改酒店集团子品牌数据表记录的API接口
+    
+    路径参数:
+        - brand_id: 品牌记录ID
+    
+    请求参数:
+        - JSON格式,可能包含以下字段:
+            - group_name_en: 集团英文名称
+            - group_name_zh: 集团中文名称
+            - brand_name_en: 品牌英文名称
+            - brand_name_zh: 品牌中文名称
+            - positioning_level_en: 定位级别英文名称
+            - positioning_level_zh: 定位级别中文名称
+            - updated_by: 更新者
+            - status: 状态
+    
+    返回:
+        - JSON: 包含更新结果和品牌信息
+    """
+    try:
+        # 获取请求数据
+        data = request.get_json()
+        
+        if not data:
+            return jsonify({
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }), 400
+        
+        # 调用业务逻辑函数处理更新
+        result = update_hotel_group_brands(brand_id, data)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 200  # OK
+        elif result['code'] == 400:
+            status_code = 400  # Bad Request
+        elif result['code'] == 404:
+            status_code = 404  # Not Found
+        elif result['code'] == 409:
+            status_code = 409  # Conflict
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"更新酒店集团品牌记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/query-hotel-group-brands/<int:brand_id>', methods=['GET'])
+def query_hotel_group_brands_route(brand_id):
+    """
+    查找指定ID的酒店集团子品牌数据表记录的API接口
+    
+    路径参数:
+        - brand_id: 品牌记录ID
+    
+    返回:
+        - JSON: 包含查找结果和品牌信息
+    """
+    try:
+        # 调用业务逻辑函数查找品牌记录
+        result = query_hotel_group_brands(brand_id)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 200  # OK
+        elif result['code'] == 404:
+            status_code = 404  # Not Found
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"查找酒店集团品牌记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+
+@bp.route('/delete-hotel-group-brands/<int:brand_id>', methods=['DELETE'])
+def delete_hotel_group_brands_route(brand_id):
+    """
+    删除指定ID的酒店集团子品牌数据表记录的API接口
+    
+    路径参数:
+        - brand_id: 品牌记录ID
+    
+    返回:
+        - JSON: 包含删除结果和被删除的品牌信息
+    """
+    try:
+        # 调用业务逻辑函数删除品牌记录
+        result = delete_hotel_group_brands(brand_id)
+        
+        # 根据处理结果设置HTTP状态码
+        if result['code'] == 200:
+            status_code = 200  # OK
+        elif result['code'] == 404:
+            status_code = 404  # Not Found
+        else:
+            status_code = 500  # Internal Server Error
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        # 处理未预期的异常
+        error_msg = f"删除酒店集团品牌记录时发生错误: {str(e)}"
+        logger.error(error_msg, exc_info=True)
+        
+        return jsonify({
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }), 500
+

+ 730 - 0
app/core/data_parse/parse.py

@@ -1839,6 +1839,736 @@ def get_business_card(card_id):
         error_msg = f"获取名片记录失败: {str(e)}"
         logging.error(error_msg, exc_info=True)
         
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+# 酒店职位数据模型
+class HotelPosition(db.Model):
+    __tablename__ = 'hotel_positions'
+    
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
+    department_zh = db.Column(db.String(10), nullable=False)
+    department_en = db.Column(db.String(50), nullable=False)
+    position_zh = db.Column(db.String(20), nullable=False)
+    position_en = db.Column(db.String(100), nullable=False)
+    position_abbr = db.Column(db.String(20), nullable=True)
+    level_zh = db.Column(db.String(10), nullable=False)
+    level_en = db.Column(db.String(30), nullable=False)
+    created_at = db.Column(db.DateTime, default=datetime.now, nullable=False)
+    updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
+    created_by = db.Column(db.String(50), default='system')
+    updated_by = db.Column(db.String(50), default='system')
+    status = db.Column(db.String(20), default='active')
+    
+    def to_dict(self):
+        return {
+            'id': self.id,
+            'department_zh': self.department_zh,
+            'department_en': self.department_en,
+            'position_zh': self.position_zh,
+            'position_en': self.position_en,
+            'position_abbr': self.position_abbr,
+            'level_zh': self.level_zh,
+            'level_en': self.level_en,
+            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None,
+            'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.updated_at else None,
+            'created_by': self.created_by,
+            'updated_by': self.updated_by,
+            'status': self.status
+        }
+
+def get_hotel_positions_list():
+    """
+    获取酒店职位数据表的全部记录
+    
+    Returns:
+        dict: 包含操作结果和酒店职位列表的字典
+    """
+    try:
+        # 查询所有酒店职位记录,按部门和职位排序
+        positions = HotelPosition.query.order_by(
+            HotelPosition.department_zh, 
+            HotelPosition.position_zh
+        ).all()
+        
+        # 将所有记录转换为字典格式
+        positions_data = [position.to_dict() for position in positions]
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '获取酒店职位列表成功',
+            'data': positions_data,
+            'count': len(positions_data)
+        }
+    
+    except Exception as e:
+        error_msg = f"获取酒店职位列表失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': [],
+            'count': 0
+        }
+
+def add_hotel_positions(position_data):
+    """
+    新增酒店职位数据表记录
+    
+    Args:
+        position_data (dict): 包含职位信息的字典,包括:
+            - department_zh: 部门中文名称 (必填)
+            - department_en: 部门英文名称 (必填)
+            - position_zh: 职位中文名称 (必填)
+            - position_en: 职位英文名称 (必填)
+            - position_abbr: 职位英文缩写 (可选)
+            - level_zh: 职级中文名称 (必填)
+            - level_en: 职级英文名称 (必填)
+            - created_by: 创建者 (可选,默认为'system')
+            - updated_by: 更新者 (可选,默认为'system')
+            - status: 状态 (可选,默认为'active')
+    
+    Returns:
+        dict: 包含操作结果和创建的职位信息的字典
+    """
+    try:
+        # 验证必填字段
+        required_fields = ['department_zh', 'department_en', 'position_zh', 'position_en', 'level_zh', 'level_en']
+        missing_fields = []
+        
+        for field in required_fields:
+            if field not in position_data or not position_data[field] or not position_data[field].strip():
+                missing_fields.append(field)
+        
+        if missing_fields:
+            return {
+                'code': 400,
+                'success': False,
+                'message': f'缺少必填字段: {", ".join(missing_fields)}',
+                'data': None
+            }
+        
+        # 检查是否已存在相同的职位记录(基于部门和职位的中文名称)
+        existing_position = HotelPosition.query.filter_by(
+            department_zh=position_data['department_zh'].strip(),
+            position_zh=position_data['position_zh'].strip()
+        ).first()
+        
+        if existing_position:
+            return {
+                'code': 409,
+                'success': False,
+                'message': f'职位记录已存在:{position_data["department_zh"]} - {position_data["position_zh"]}',
+                'data': existing_position.to_dict()
+            }
+        
+        # 创建新的职位记录
+        new_position = HotelPosition(
+            department_zh=position_data['department_zh'].strip(),
+            department_en=position_data['department_en'].strip(),
+            position_zh=position_data['position_zh'].strip(),
+            position_en=position_data['position_en'].strip(),
+            position_abbr=position_data.get('position_abbr', '').strip() if position_data.get('position_abbr') else None,
+            level_zh=position_data['level_zh'].strip(),
+            level_en=position_data['level_en'].strip(),
+            created_by=position_data.get('created_by', 'system'),
+            updated_by=position_data.get('updated_by', 'system'),
+            status=position_data.get('status', 'active')
+        )
+        
+        # 保存到数据库
+        db.session.add(new_position)
+        db.session.commit()
+        
+        logging.info(f"成功创建酒店职位记录,ID: {new_position.id}")
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '酒店职位记录创建成功',
+            'data': new_position.to_dict()
+        }
+    
+    except Exception as e:
+        db.session.rollback()
+        error_msg = f"创建酒店职位记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def update_hotel_positions(position_id, position_data):
+    """
+    修改酒店职位数据表记录
+    
+    Args:
+        position_id (int): 职位记录ID
+        position_data (dict): 包含要更新的职位信息的字典,可能包括:
+            - department_zh: 部门中文名称
+            - department_en: 部门英文名称
+            - position_zh: 职位中文名称
+            - position_en: 职位英文名称
+            - position_abbr: 职位英文缩写
+            - level_zh: 职级中文名称
+            - level_en: 职级英文名称
+            - updated_by: 更新者
+            - status: 状态
+    
+    Returns:
+        dict: 包含操作结果和更新后的职位信息的字典
+    """
+    try:
+        # 查找要更新的职位记录
+        position = HotelPosition.query.get(position_id)
+        
+        if not position:
+            return {
+                'code': 404,
+                'success': False,
+                'message': f'未找到ID为{position_id}的职位记录',
+                'data': None
+            }
+        
+        # 检查是否有数据需要更新
+        if not position_data:
+            return {
+                'code': 400,
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }
+        
+        # 如果要更新部门和职位名称,检查是否会与其他记录冲突
+        new_department_zh = position_data.get('department_zh', position.department_zh).strip() if position_data.get('department_zh') else position.department_zh
+        new_position_zh = position_data.get('position_zh', position.position_zh).strip() if position_data.get('position_zh') else position.position_zh
+        
+        # 查找是否存在相同的职位记录(排除当前记录)
+        existing_position = HotelPosition.query.filter(
+            HotelPosition.id != position_id,
+            HotelPosition.department_zh == new_department_zh,
+            HotelPosition.position_zh == new_position_zh
+        ).first()
+        
+        if existing_position:
+            return {
+                'code': 409,
+                'success': False,
+                'message': f'职位记录已存在:{new_department_zh} - {new_position_zh}',
+                'data': existing_position.to_dict()
+            }
+        
+        # 更新职位信息
+        if 'department_zh' in position_data and position_data['department_zh']:
+            position.department_zh = position_data['department_zh'].strip()
+        
+        if 'department_en' in position_data and position_data['department_en']:
+            position.department_en = position_data['department_en'].strip()
+        
+        if 'position_zh' in position_data and position_data['position_zh']:
+            position.position_zh = position_data['position_zh'].strip()
+        
+        if 'position_en' in position_data and position_data['position_en']:
+            position.position_en = position_data['position_en'].strip()
+        
+        if 'position_abbr' in position_data:
+            # 处理position_abbr,可能为空字符串或None
+            if position_data['position_abbr'] and position_data['position_abbr'].strip():
+                position.position_abbr = position_data['position_abbr'].strip()
+            else:
+                position.position_abbr = None
+        
+        if 'level_zh' in position_data and position_data['level_zh']:
+            position.level_zh = position_data['level_zh'].strip()
+        
+        if 'level_en' in position_data and position_data['level_en']:
+            position.level_en = position_data['level_en'].strip()
+        
+        if 'updated_by' in position_data:
+            position.updated_by = position_data['updated_by'] or 'system'
+        
+        if 'status' in position_data:
+            position.status = position_data['status'] or 'active'
+        
+        # 更新时间会自动设置(onupdate=datetime.now)
+        
+        # 保存更新
+        db.session.commit()
+        
+        logging.info(f"成功更新酒店职位记录,ID: {position.id}")
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '酒店职位记录更新成功',
+            'data': position.to_dict()
+        }
+    
+    except Exception as e:
+        db.session.rollback()
+        error_msg = f"更新酒店职位记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def query_hotel_positions(position_id):
+    """
+    查找指定ID的酒店职位数据表记录
+    
+    Args:
+        position_id (int): 职位记录ID
+    
+    Returns:
+        dict: 包含操作结果和职位信息的字典
+    """
+    try:
+        # 根据ID查找职位记录
+        position = HotelPosition.query.get(position_id)
+        
+        if not position:
+            return {
+                'code': 404,
+                'success': False,
+                'message': f'未找到ID为{position_id}的职位记录',
+                'data': None
+            }
+        
+        # 返回找到的记录
+        return {
+            'code': 200,
+            'success': True,
+            'message': '查找职位记录成功',
+            'data': position.to_dict()
+        }
+    
+    except Exception as e:
+        error_msg = f"查找职位记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def delete_hotel_positions(position_id):
+    """
+    删除指定ID的酒店职位数据表记录
+    
+    Args:
+        position_id (int): 职位记录ID
+    
+    Returns:
+        dict: 包含操作结果的字典
+    """
+    try:
+        # 根据ID查找要删除的职位记录
+        position = HotelPosition.query.get(position_id)
+        
+        if not position:
+            return {
+                'code': 404,
+                'success': False,
+                'message': f'未找到ID为{position_id}的职位记录',
+                'data': None
+            }
+        
+        # 保存被删除记录的信息,用于返回
+        deleted_position_info = position.to_dict()
+        
+        # 执行删除操作
+        db.session.delete(position)
+        db.session.commit()
+        
+        logging.info(f"成功删除酒店职位记录,ID: {position_id}")
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '职位记录删除成功',
+            'data': deleted_position_info
+        }
+    
+    except Exception as e:
+        db.session.rollback()
+        error_msg = f"删除职位记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+# 酒店集团子品牌数据模型
+class HotelGroupBrands(db.Model):
+    __tablename__ = 'hotel_group_brands'
+    
+    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
+    group_name_en = db.Column(db.String(60), nullable=False)
+    group_name_zh = db.Column(db.String(20), nullable=False)
+    brand_name_en = db.Column(db.String(40), nullable=False)
+    brand_name_zh = db.Column(db.String(40), nullable=False)
+    positioning_level_en = db.Column(db.String(20), nullable=False)
+    positioning_level_zh = db.Column(db.String(5), nullable=False)
+    created_at = db.Column(db.DateTime, default=datetime.now, nullable=False)
+    updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
+    created_by = db.Column(db.String(50), default='system')
+    updated_by = db.Column(db.String(50), default='system')
+    status = db.Column(db.String(20), default='active')
+    
+    def to_dict(self):
+        return {
+            'id': self.id,
+            'group_name_en': self.group_name_en,
+            'group_name_zh': self.group_name_zh,
+            'brand_name_en': self.brand_name_en,
+            'brand_name_zh': self.brand_name_zh,
+            'positioning_level_en': self.positioning_level_en,
+            'positioning_level_zh': self.positioning_level_zh,
+            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None,
+            'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.updated_at else None,
+            'created_by': self.created_by,
+            'updated_by': self.updated_by,
+            'status': self.status
+        }
+
+def get_hotel_group_brands_list():
+    """
+    获取酒店集团子品牌数据表的全部记录
+    
+    Returns:
+        dict: 包含操作结果和酒店集团品牌列表的字典
+    """
+    try:
+        # 查询所有酒店集团品牌记录,按集团和品牌排序
+        brands = HotelGroupBrands.query.order_by(
+            HotelGroupBrands.group_name_zh, 
+            HotelGroupBrands.brand_name_zh
+        ).all()
+        
+        # 将所有记录转换为字典格式
+        brands_data = [brand.to_dict() for brand in brands]
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '获取酒店集团品牌列表成功',
+            'data': brands_data,
+            'count': len(brands_data)
+        }
+    
+    except Exception as e:
+        error_msg = f"获取酒店集团品牌列表失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': [],
+            'count': 0
+        }
+
+def add_hotel_group_brands(brand_data):
+    """
+    新增酒店集团子品牌数据表记录
+    
+    Args:
+        brand_data (dict): 包含品牌信息的字典,包括:
+            - group_name_en: 集团英文名称 (必填)
+            - group_name_zh: 集团中文名称 (必填)
+            - brand_name_en: 品牌英文名称 (必填)
+            - brand_name_zh: 品牌中文名称 (必填)
+            - positioning_level_en: 定位级别英文名称 (必填)
+            - positioning_level_zh: 定位级别中文名称 (必填)
+            - created_by: 创建者 (可选,默认为'system')
+            - updated_by: 更新者 (可选,默认为'system')
+            - status: 状态 (可选,默认为'active')
+    
+    Returns:
+        dict: 包含操作结果和创建的品牌信息的字典
+    """
+    try:
+        # 验证必填字段
+        required_fields = ['group_name_en', 'group_name_zh', 'brand_name_en', 'brand_name_zh', 'positioning_level_en', 'positioning_level_zh']
+        missing_fields = []
+        
+        for field in required_fields:
+            if field not in brand_data or not brand_data[field] or not brand_data[field].strip():
+                missing_fields.append(field)
+        
+        if missing_fields:
+            return {
+                'code': 400,
+                'success': False,
+                'message': f'缺少必填字段: {", ".join(missing_fields)}',
+                'data': None
+            }
+        
+        # 检查是否已存在相同的品牌记录(基于集团和品牌的中文名称)
+        existing_brand = HotelGroupBrands.query.filter_by(
+            group_name_zh=brand_data['group_name_zh'].strip(),
+            brand_name_zh=brand_data['brand_name_zh'].strip()
+        ).first()
+        
+        if existing_brand:
+            return {
+                'code': 409,
+                'success': False,
+                'message': f'品牌记录已存在:{brand_data["group_name_zh"]} - {brand_data["brand_name_zh"]}',
+                'data': existing_brand.to_dict()
+            }
+        
+        # 创建新的品牌记录
+        new_brand = HotelGroupBrands(
+            group_name_en=brand_data['group_name_en'].strip(),
+            group_name_zh=brand_data['group_name_zh'].strip(),
+            brand_name_en=brand_data['brand_name_en'].strip(),
+            brand_name_zh=brand_data['brand_name_zh'].strip(),
+            positioning_level_en=brand_data['positioning_level_en'].strip(),
+            positioning_level_zh=brand_data['positioning_level_zh'].strip(),
+            created_by=brand_data.get('created_by', 'system'),
+            updated_by=brand_data.get('updated_by', 'system'),
+            status=brand_data.get('status', 'active')
+        )
+        
+        # 保存到数据库
+        db.session.add(new_brand)
+        db.session.commit()
+        
+        logging.info(f"成功创建酒店集团品牌记录,ID: {new_brand.id}")
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '酒店集团品牌记录创建成功',
+            'data': new_brand.to_dict()
+        }
+    
+    except Exception as e:
+        db.session.rollback()
+        error_msg = f"创建酒店集团品牌记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def update_hotel_group_brands(brand_id, brand_data):
+    """
+    修改酒店集团子品牌数据表记录
+    
+    Args:
+        brand_id (int): 品牌记录ID
+        brand_data (dict): 包含要更新的品牌信息的字典,可能包括:
+            - group_name_en: 集团英文名称
+            - group_name_zh: 集团中文名称
+            - brand_name_en: 品牌英文名称
+            - brand_name_zh: 品牌中文名称
+            - positioning_level_en: 定位级别英文名称
+            - positioning_level_zh: 定位级别中文名称
+            - updated_by: 更新者
+            - status: 状态
+    
+    Returns:
+        dict: 包含操作结果和更新后的品牌信息的字典
+    """
+    try:
+        # 查找要更新的品牌记录
+        brand = HotelGroupBrands.query.get(brand_id)
+        
+        if not brand:
+            return {
+                'code': 404,
+                'success': False,
+                'message': f'未找到ID为{brand_id}的品牌记录',
+                'data': None
+            }
+        
+        # 检查是否有数据需要更新
+        if not brand_data:
+            return {
+                'code': 400,
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }
+        
+        # 如果要更新集团和品牌名称,检查是否会与其他记录冲突
+        new_group_name_zh = brand_data.get('group_name_zh', brand.group_name_zh).strip() if brand_data.get('group_name_zh') else brand.group_name_zh
+        new_brand_name_zh = brand_data.get('brand_name_zh', brand.brand_name_zh).strip() if brand_data.get('brand_name_zh') else brand.brand_name_zh
+        
+        # 查找是否存在相同的品牌记录(排除当前记录)
+        existing_brand = HotelGroupBrands.query.filter(
+            HotelGroupBrands.id != brand_id,
+            HotelGroupBrands.group_name_zh == new_group_name_zh,
+            HotelGroupBrands.brand_name_zh == new_brand_name_zh
+        ).first()
+        
+        if existing_brand:
+            return {
+                'code': 409,
+                'success': False,
+                'message': f'品牌记录已存在:{new_group_name_zh} - {new_brand_name_zh}',
+                'data': existing_brand.to_dict()
+            }
+        
+        # 更新品牌信息
+        if 'group_name_en' in brand_data and brand_data['group_name_en']:
+            brand.group_name_en = brand_data['group_name_en'].strip()
+        
+        if 'group_name_zh' in brand_data and brand_data['group_name_zh']:
+            brand.group_name_zh = brand_data['group_name_zh'].strip()
+        
+        if 'brand_name_en' in brand_data and brand_data['brand_name_en']:
+            brand.brand_name_en = brand_data['brand_name_en'].strip()
+        
+        if 'brand_name_zh' in brand_data and brand_data['brand_name_zh']:
+            brand.brand_name_zh = brand_data['brand_name_zh'].strip()
+        
+        if 'positioning_level_en' in brand_data and brand_data['positioning_level_en']:
+            brand.positioning_level_en = brand_data['positioning_level_en'].strip()
+        
+        if 'positioning_level_zh' in brand_data and brand_data['positioning_level_zh']:
+            brand.positioning_level_zh = brand_data['positioning_level_zh'].strip()
+        
+        if 'updated_by' in brand_data:
+            brand.updated_by = brand_data['updated_by'] or 'system'
+        
+        if 'status' in brand_data:
+            brand.status = brand_data['status'] or 'active'
+        
+        # 更新时间会自动设置(onupdate=datetime.now)
+        
+        # 保存更新
+        db.session.commit()
+        
+        logging.info(f"成功更新酒店集团品牌记录,ID: {brand.id}")
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '酒店集团品牌记录更新成功',
+            'data': brand.to_dict()
+        }
+    
+    except Exception as e:
+        db.session.rollback()
+        error_msg = f"更新酒店集团品牌记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def query_hotel_group_brands(brand_id):
+    """
+    查找指定ID的酒店集团子品牌数据表记录
+    
+    Args:
+        brand_id (int): 品牌记录ID
+    
+    Returns:
+        dict: 包含操作结果和品牌信息的字典
+    """
+    try:
+        # 根据ID查找品牌记录
+        brand = HotelGroupBrands.query.get(brand_id)
+        
+        if not brand:
+            return {
+                'code': 404,
+                'success': False,
+                'message': f'未找到ID为{brand_id}的品牌记录',
+                'data': None
+            }
+        
+        # 返回找到的记录
+        return {
+            'code': 200,
+            'success': True,
+            'message': '查找品牌记录成功',
+            'data': brand.to_dict()
+        }
+    
+    except Exception as e:
+        error_msg = f"查找品牌记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def delete_hotel_group_brands(brand_id):
+    """
+    删除指定ID的酒店集团子品牌数据表记录
+    
+    Args:
+        brand_id (int): 品牌记录ID
+    
+    Returns:
+        dict: 包含操作结果的字典
+    """
+    try:
+        # 根据ID查找要删除的品牌记录
+        brand = HotelGroupBrands.query.get(brand_id)
+        
+        if not brand:
+            return {
+                'code': 404,
+                'success': False,
+                'message': f'未找到ID为{brand_id}的品牌记录',
+                'data': None
+            }
+        
+        # 保存被删除记录的信息,用于返回
+        deleted_brand_info = brand.to_dict()
+        
+        # 执行删除操作
+        db.session.delete(brand)
+        db.session.commit()
+        
+        logging.info(f"成功删除酒店集团品牌记录,ID: {brand_id}")
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '品牌记录删除成功',
+            'data': deleted_brand_info
+        }
+    
+    except Exception as e:
+        db.session.rollback()
+        error_msg = f"删除品牌记录失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
         return {
             'code': 500,
             'success': False,

+ 65 - 0
hotel_group_brands_ddl.sql

@@ -0,0 +1,65 @@
+-- ============================================================================
+-- 酒店集团子品牌数据表 DDL
+-- 基于文件: 人才地图-字典20250519.xlsx - 各集团子品牌 sheet
+-- 创建时间: 2025-01-19
+-- 数据规模: 295条记录,27个集团,290个品牌,6个定位级别
+-- ============================================================================
+
+CREATE TABLE hotel_group_brands (
+    -- 主键ID,自增序列
+    id SERIAL PRIMARY KEY,
+  
+    -- 集团信息
+    group_name_en VARCHAR(60) NOT NULL,
+    
+    group_name_zh VARCHAR(20) NOT NULL,
+    
+    -- 品牌信息
+    brand_name_en VARCHAR(40) NOT NULL,
+    
+    brand_name_zh VARCHAR(40) NOT NULL,
+    
+    -- 定位级别信息
+    positioning_level_en VARCHAR(20) NOT NULL,
+    
+    positioning_level_zh VARCHAR(5) NOT NULL,
+    
+    -- 审计字段
+    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
+    
+    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
+    
+    created_by VARCHAR(50) DEFAULT 'system',
+    
+    updated_by VARCHAR(50) DEFAULT 'system',
+    
+    status VARCHAR(20) DEFAULT 'active'
+);
+
+-- ============================================================================
+-- 表注释
+-- ============================================================================
+
+COMMENT ON TABLE hotel_group_brands IS '酒店集团子品牌数据表
+用途:存储全球酒店集团及其子品牌的标准化信息
+数据来源:人才地图-字典20250519.xlsx
+包含内容:27个酒店集团,290个品牌,6个定位级别
+维护说明:定期更新以保持与行业标准一致';
+
+-- ============================================================================
+-- 字段注释
+-- ============================================================================
+
+COMMENT ON COLUMN hotel_group_brands.id IS '主键ID,系统自动生成';
+COMMENT ON COLUMN hotel_group_brands.sequence_no IS '序号,对应Excel中的原始序号,共34个不同序号';
+COMMENT ON COLUMN hotel_group_brands.group_name_en IS '集团英文名称,最大长度50个字符,如:IHG Hotels & Resorts,共27个不同集团';
+COMMENT ON COLUMN hotel_group_brands.group_name_zh IS '集团中文名称,最大长度12个字符,如:洲际酒店集团,共27个不同集团';
+COMMENT ON COLUMN hotel_group_brands.brand_name_en IS '品牌英文名称,最大长度35个字符,如:InterContinental,共290个不同品牌';
+COMMENT ON COLUMN hotel_group_brands.brand_name_zh IS '品牌中文名称,最大长度31个字符,如:洲际酒店及度假村,共294个不同品牌';
+COMMENT ON COLUMN hotel_group_brands.positioning_level_en IS '定位级别英文名称,最大长度14个字符,如:Upper Upscale,共6个级别';
+COMMENT ON COLUMN hotel_group_brands.positioning_level_zh IS '定位级别中文名称,最大长度3个字符,如:超高端,共6个级别';
+COMMENT ON COLUMN hotel_group_brands.created_at IS '记录创建时间,带时区';
+COMMENT ON COLUMN hotel_group_brands.updated_at IS '记录最后更新时间,带时区';
+COMMENT ON COLUMN hotel_group_brands.created_by IS '记录创建者用户标识';
+COMMENT ON COLUMN hotel_group_brands.updated_by IS '记录最后更新者用户标识';
+COMMENT ON COLUMN hotel_group_brands.status IS '记录状态,active=有效,inactive=无效'; 

+ 75 - 0
hotel_positions_ddl.sql

@@ -0,0 +1,75 @@
+-- ============================================================================
+-- 酒店职位名称数据表 DDL
+-- 基于文件: 酒店职位名称20250519.xlsx - 汇总版 sheet
+-- 创建时间: 2025-01-19
+-- 数据规模: 150条记录,9个部门,144个不同职位
+-- ============================================================================
+
+CREATE TABLE hotel_positions (
+    -- 主键ID,自增序列
+    id SERIAL PRIMARY KEY,
+    
+    -- 部门信息
+    department_zh VARCHAR(10) NOT NULL,
+    
+    department_en VARCHAR(50) NOT NULL,
+    
+    -- 职位信息  
+    position_zh VARCHAR(20) NOT NULL,
+    
+    position_en VARCHAR(100) NOT NULL,
+    
+    position_abbr VARCHAR(20) NULL,
+    
+    -- 职级信息
+    level_zh VARCHAR(10) NOT NULL,
+    
+    level_en VARCHAR(30) NOT NULL,
+    
+    -- 审计字段
+    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
+    
+    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
+    
+    created_by VARCHAR(50) DEFAULT 'system',
+    
+    updated_by VARCHAR(50) DEFAULT 'system',
+    
+    status VARCHAR(20) DEFAULT 'active'
+);
+
+-- ============================================================================
+-- 索引定义
+-- ============================================================================
+
+-- 职位索引
+CREATE INDEX idx_hotel_positions_position_zh 
+    ON hotel_positions(position_zh);
+
+-- ============================================================================
+-- 表注释
+-- ============================================================================
+
+COMMENT ON TABLE hotel_positions IS '酒店职位名称标准数据表
+用途:存储酒店行业标准化的部门和职位信息
+数据来源:酒店职位名称20250519.xlsx
+包含内容:9个部门,144个不同职位,3个职级
+维护说明:定期更新以保持与行业标准一致';
+
+-- ============================================================================
+-- 字段详细注释
+-- ============================================================================
+
+COMMENT ON COLUMN hotel_positions.id IS '主键ID,系统自动生成';
+COMMENT ON COLUMN hotel_positions.department_zh IS '部门中文名称,最大长度5个字符,如:餐饮部、房务部、市场销售部等。共9个部门:餐饮部(61)、房务部(23)、市场销售部(17)、人力资源部(13)、财务部(13)、行政办公室(8)、工程部(8)、水疗部(4)、保安部(3)';
+COMMENT ON COLUMN hotel_positions.department_en IS '部门英文名称,最大长度28个字符,如:Food & Beverage Department';
+COMMENT ON COLUMN hotel_positions.position_zh IS '职位中文名称,最大长度13个字符,如:总经理、行政助理经理等。共144个不同职位';
+COMMENT ON COLUMN hotel_positions.position_en IS '职位英文名称,最大长度57个字符,如:General Manager, Executive Assistant Manager。共143个不同英文职位名称';
+COMMENT ON COLUMN hotel_positions.position_abbr IS '职位英文缩写,最大长度11个字符,如:GM、EAM、DGM等,允许为空。共33个不同缩写,115条记录为空值';
+COMMENT ON COLUMN hotel_positions.level_zh IS '职级中文名称,最大长度4个字符,包含:经理级(120人)、总监级(23人)、总经理级(7人)';
+COMMENT ON COLUMN hotel_positions.level_en IS '职级英文名称,最大长度22个字符,如:Manager Level、Director Level、General Manager Level';
+COMMENT ON COLUMN hotel_positions.created_at IS '记录创建时间,带时区';
+COMMENT ON COLUMN hotel_positions.updated_at IS '记录最后更新时间,带时区';
+COMMENT ON COLUMN hotel_positions.created_by IS '记录创建者用户标识';
+COMMENT ON COLUMN hotel_positions.updated_by IS '记录最后更新者用户标识';
+COMMENT ON COLUMN hotel_positions.status IS '记录状态,active=有效,inactive=无效';

BIN
人才地图-字典20250421.xlsx


BIN
人才地图-字典20250519.xlsx


BIN
酒店职位名称20250519.xlsx


+ 840 - 0
酒店职位和品牌_API使用手册.md

@@ -0,0 +1,840 @@
+# 酒店数据管理系统 API 操作说明书
+
+## 概述
+
+本文档详细描述了酒店数据管理系统中 `hotel_positions`(酒店职位)和 `hotel_group_brands`(酒店集团品牌)两个数据表的完整CRUD操作API接口。
+
+### 基础信息
+- **API基础URL**: `/api/data-parse`
+- **数据格式**: JSON
+- **字符编码**: UTF-8
+- **时间格式**: `YYYY-MM-DD HH:MM:SS`
+
+### 通用返回格式
+所有API接口都遵循统一的返回格式:
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "操作成功信息",
+    "data": "具体数据内容"
+}
+```
+
+### HTTP状态码说明
+| 状态码 | 含义 | 说明 |
+|--------|------|------|
+| 200 | OK | 请求成功 |
+| 201 | Created | 资源创建成功 |
+| 400 | Bad Request | 请求参数错误 |
+| 404 | Not Found | 资源不存在 |
+| 409 | Conflict | 资源冲突(重复) |
+| 500 | Internal Server Error | 服务器内部错误 |
+
+---
+
+## 一、酒店职位管理 API (hotel_positions)
+
+### 1.1 获取所有职位记录
+
+#### 基本信息
+- **URL**: `/get-hotel-positions-list`
+- **方法**: `GET`
+- **功能**: 获取酒店职位数据表的全部记录
+
+#### 请求参数
+无需请求参数
+
+#### 响应参数
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| code | integer | 响应状态码 |
+| success | boolean | 操作是否成功 |
+| message | string | 响应消息 |
+| data | array | 职位记录数组 |
+| count | integer | 记录总数 |
+
+#### 职位记录字段说明
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| id | integer | 主键ID |
+| department_zh | string | 部门中文名称 |
+| department_en | string | 部门英文名称 |
+| position_zh | string | 职位中文名称 |
+| position_en | string | 职位英文名称 |
+| position_abbr | string | 职位英文缩写(可为null) |
+| level_zh | string | 职级中文名称 |
+| level_en | string | 职级英文名称 |
+| created_at | string | 创建时间 |
+| updated_at | string | 更新时间 |
+| created_by | string | 创建者 |
+| updated_by | string | 更新者 |
+| status | string | 状态(active/inactive) |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+GET /api/data-parse/get-hotel-positions-list
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "获取酒店职位列表成功",
+    "data": [
+        {
+            "id": 1,
+            "department_zh": "餐饮部",
+            "department_en": "Food & Beverage Department",
+            "position_zh": "总经理",
+            "position_en": "General Manager",
+            "position_abbr": "GM",
+            "level_zh": "总经理级",
+            "level_en": "General Manager Level",
+            "created_at": "2025-01-19 10:00:00",
+            "updated_at": "2025-01-19 10:00:00",
+            "created_by": "system",
+            "updated_by": "system",
+            "status": "active"
+        }
+    ],
+    "count": 1
+}
+```
+
+### 1.2 新增职位记录
+
+#### 基本信息
+- **URL**: `/add-hotel-positions`
+- **方法**: `POST`
+- **功能**: 新增酒店职位记录
+
+#### 请求参数
+| 字段名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| department_zh | string | 是 | 部门中文名称 |
+| department_en | string | 是 | 部门英文名称 |
+| position_zh | string | 是 | 职位中文名称 |
+| position_en | string | 是 | 职位英文名称 |
+| position_abbr | string | 否 | 职位英文缩写 |
+| level_zh | string | 是 | 职级中文名称 |
+| level_en | string | 是 | 职级英文名称 |
+| created_by | string | 否 | 创建者(默认system) |
+| updated_by | string | 否 | 更新者(默认system) |
+| status | string | 否 | 状态(默认active) |
+
+#### 响应参数
+同职位记录字段说明
+
+#### 测试样例
+
+**请求示例:**
+```bash
+POST /api/data-parse/add-hotel-positions
+Content-Type: application/json
+
+{
+    "department_zh": "餐饮部",
+    "department_en": "Food & Beverage Department",
+    "position_zh": "副总经理",
+    "position_en": "Deputy General Manager",
+    "position_abbr": "DGM",
+    "level_zh": "总监级",
+    "level_en": "Director Level",
+    "created_by": "admin"
+}
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "酒店职位记录创建成功",
+    "data": {
+        "id": 151,
+        "department_zh": "餐饮部",
+        "department_en": "Food & Beverage Department",
+        "position_zh": "副总经理",
+        "position_en": "Deputy General Manager",
+        "position_abbr": "DGM",
+        "level_zh": "总监级",
+        "level_en": "Director Level",
+        "created_at": "2025-01-19 15:30:00",
+        "updated_at": "2025-01-19 15:30:00",
+        "created_by": "admin",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+**重复记录错误响应:**
+```json
+{
+    "code": 409,
+    "success": false,
+    "message": "职位记录已存在:餐饮部 - 副总经理",
+    "data": {
+        "id": 100,
+        "department_zh": "餐饮部",
+        "position_zh": "副总经理",
+        "..."
+    }
+}
+```
+
+### 1.3 更新职位记录
+
+#### 基本信息
+- **URL**: `/update-hotel-positions/<int:position_id>`
+- **方法**: `PUT`
+- **功能**: 更新指定ID的职位记录
+
+#### 路径参数
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| position_id | integer | 职位记录ID |
+
+#### 请求参数
+| 字段名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| department_zh | string | 否 | 部门中文名称 |
+| department_en | string | 否 | 部门英文名称 |
+| position_zh | string | 否 | 职位中文名称 |
+| position_en | string | 否 | 职位英文名称 |
+| position_abbr | string | 否 | 职位英文缩写 |
+| level_zh | string | 否 | 职级中文名称 |
+| level_en | string | 否 | 职级英文名称 |
+| updated_by | string | 否 | 更新者 |
+| status | string | 否 | 状态 |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+PUT /api/data-parse/update-hotel-positions/1
+Content-Type: application/json
+
+{
+    "position_abbr": "AGM",
+    "updated_by": "admin"
+}
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "酒店职位记录更新成功",
+    "data": {
+        "id": 1,
+        "department_zh": "餐饮部",
+        "department_en": "Food & Beverage Department",
+        "position_zh": "总经理",
+        "position_en": "General Manager",
+        "position_abbr": "AGM",
+        "level_zh": "总经理级",
+        "level_en": "General Manager Level",
+        "created_at": "2025-01-19 10:00:00",
+        "updated_at": "2025-01-19 16:00:00",
+        "created_by": "system",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+### 1.4 查询指定职位记录
+
+#### 基本信息
+- **URL**: `/query-hotel-positions/<int:position_id>`
+- **方法**: `GET`
+- **功能**: 根据ID查询指定职位记录
+
+#### 路径参数
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| position_id | integer | 职位记录ID |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+GET /api/data-parse/query-hotel-positions/1
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "查找职位记录成功",
+    "data": {
+        "id": 1,
+        "department_zh": "餐饮部",
+        "department_en": "Food & Beverage Department",
+        "position_zh": "总经理",
+        "position_en": "General Manager",
+        "position_abbr": "GM",
+        "level_zh": "总经理级",
+        "level_en": "General Manager Level",
+        "created_at": "2025-01-19 10:00:00",
+        "updated_at": "2025-01-19 15:45:00",
+        "created_by": "system",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+**记录不存在响应:**
+```json
+{
+    "code": 404,
+    "success": false,
+    "message": "未找到ID为999的职位记录",
+    "data": null
+}
+```
+
+### 1.5 删除职位记录
+
+#### 基本信息
+- **URL**: `/delete-hotel-positions/<int:position_id>`
+- **方法**: `DELETE`
+- **功能**: 删除指定ID的职位记录
+
+#### 路径参数
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| position_id | integer | 职位记录ID |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+DELETE /api/data-parse/delete-hotel-positions/1
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "职位记录删除成功",
+    "data": {
+        "id": 1,
+        "department_zh": "餐饮部",
+        "department_en": "Food & Beverage Department",
+        "position_zh": "总经理",
+        "position_en": "General Manager",
+        "position_abbr": "GM",
+        "level_zh": "总经理级",
+        "level_en": "General Manager Level",
+        "created_at": "2025-01-19 10:00:00",
+        "updated_at": "2025-01-19 15:45:00",
+        "created_by": "system",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+---
+
+## 二、酒店集团品牌管理 API (hotel_group_brands)
+
+### 2.1 获取所有品牌记录
+
+#### 基本信息
+- **URL**: `/get-hotel-group-brands-list`
+- **方法**: `GET`
+- **功能**: 获取酒店集团品牌数据表的全部记录
+
+#### 请求参数
+无需请求参数
+
+#### 响应参数
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| code | integer | 响应状态码 |
+| success | boolean | 操作是否成功 |
+| message | string | 响应消息 |
+| data | array | 品牌记录数组 |
+| count | integer | 记录总数 |
+
+#### 品牌记录字段说明
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| id | integer | 主键ID |
+| group_name_en | string | 集团英文名称 |
+| group_name_zh | string | 集团中文名称 |
+| brand_name_en | string | 品牌英文名称 |
+| brand_name_zh | string | 品牌中文名称 |
+| positioning_level_en | string | 定位级别英文名称 |
+| positioning_level_zh | string | 定位级别中文名称 |
+| created_at | string | 创建时间 |
+| updated_at | string | 更新时间 |
+| created_by | string | 创建者 |
+| updated_by | string | 更新者 |
+| status | string | 状态(active/inactive) |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+GET /api/data-parse/get-hotel-group-brands-list
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "获取酒店集团品牌列表成功",
+    "data": [
+        {
+            "id": 1,
+            "group_name_en": "IHG Hotels & Resorts",
+            "group_name_zh": "洲际酒店集团",
+            "brand_name_en": "InterContinental",
+            "brand_name_zh": "洲际酒店及度假村",
+            "positioning_level_en": "Upper Upscale",
+            "positioning_level_zh": "超高端",
+            "created_at": "2025-01-19 10:00:00",
+            "updated_at": "2025-01-19 10:00:00",
+            "created_by": "system",
+            "updated_by": "system",
+            "status": "active"
+        }
+    ],
+    "count": 1
+}
+```
+
+### 2.2 新增品牌记录
+
+#### 基本信息
+- **URL**: `/add-hotel-group-brands`
+- **方法**: `POST`
+- **功能**: 新增酒店集团品牌记录
+
+#### 请求参数
+| 字段名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| group_name_en | string | 是 | 集团英文名称 |
+| group_name_zh | string | 是 | 集团中文名称 |
+| brand_name_en | string | 是 | 品牌英文名称 |
+| brand_name_zh | string | 是 | 品牌中文名称 |
+| positioning_level_en | string | 是 | 定位级别英文名称 |
+| positioning_level_zh | string | 是 | 定位级别中文名称 |
+| created_by | string | 否 | 创建者(默认system) |
+| updated_by | string | 否 | 更新者(默认system) |
+| status | string | 否 | 状态(默认active) |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+POST /api/data-parse/add-hotel-group-brands
+Content-Type: application/json
+
+{
+    "group_name_en": "Marriott International",
+    "group_name_zh": "万豪国际",
+    "brand_name_en": "The Ritz-Carlton",
+    "brand_name_zh": "丽思卡尔顿",
+    "positioning_level_en": "Luxury",
+    "positioning_level_zh": "奢华型",
+    "created_by": "admin"
+}
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "酒店集团品牌记录创建成功",
+    "data": {
+        "id": 296,
+        "group_name_en": "Marriott International",
+        "group_name_zh": "万豪国际",
+        "brand_name_en": "The Ritz-Carlton",
+        "brand_name_zh": "丽思卡尔顿",
+        "positioning_level_en": "Luxury",
+        "positioning_level_zh": "奢华型",
+        "created_at": "2025-01-19 16:00:00",
+        "updated_at": "2025-01-19 16:00:00",
+        "created_by": "admin",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+**重复记录错误响应:**
+```json
+{
+    "code": 409,
+    "success": false,
+    "message": "品牌记录已存在:万豪国际 - 丽思卡尔顿",
+    "data": {
+        "id": 200,
+        "group_name_zh": "万豪国际",
+        "brand_name_zh": "丽思卡尔顿",
+        "..."
+    }
+}
+```
+
+### 2.3 更新品牌记录
+
+#### 基本信息
+- **URL**: `/update-hotel-group-brands/<int:brand_id>`
+- **方法**: `PUT`
+- **功能**: 更新指定ID的品牌记录
+
+#### 路径参数
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| brand_id | integer | 品牌记录ID |
+
+#### 请求参数
+| 字段名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| group_name_en | string | 否 | 集团英文名称 |
+| group_name_zh | string | 否 | 集团中文名称 |
+| brand_name_en | string | 否 | 品牌英文名称 |
+| brand_name_zh | string | 否 | 品牌中文名称 |
+| positioning_level_en | string | 否 | 定位级别英文名称 |
+| positioning_level_zh | string | 否 | 定位级别中文名称 |
+| updated_by | string | 否 | 更新者 |
+| status | string | 否 | 状态 |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+PUT /api/data-parse/update-hotel-group-brands/1
+Content-Type: application/json
+
+{
+    "positioning_level_en": "Luxury",
+    "positioning_level_zh": "奢华型",
+    "updated_by": "admin"
+}
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "酒店集团品牌记录更新成功",
+    "data": {
+        "id": 1,
+        "group_name_en": "IHG Hotels & Resorts",
+        "group_name_zh": "洲际酒店集团",
+        "brand_name_en": "InterContinental",
+        "brand_name_zh": "洲际酒店及度假村",
+        "positioning_level_en": "Luxury",
+        "positioning_level_zh": "奢华型",
+        "created_at": "2025-01-19 10:00:00",
+        "updated_at": "2025-01-19 16:30:00",
+        "created_by": "system",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+### 2.4 查询指定品牌记录
+
+#### 基本信息
+- **URL**: `/query-hotel-group-brands/<int:brand_id>`
+- **方法**: `GET`
+- **功能**: 根据ID查询指定品牌记录
+
+#### 路径参数
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| brand_id | integer | 品牌记录ID |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+GET /api/data-parse/query-hotel-group-brands/1
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "查找品牌记录成功",
+    "data": {
+        "id": 1,
+        "group_name_en": "IHG Hotels & Resorts",
+        "group_name_zh": "洲际酒店集团",
+        "brand_name_en": "InterContinental",
+        "brand_name_zh": "洲际酒店及度假村",
+        "positioning_level_en": "Upper Upscale",
+        "positioning_level_zh": "超高端",
+        "created_at": "2025-01-19 10:00:00",
+        "updated_at": "2025-01-19 16:30:00",
+        "created_by": "system",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+**记录不存在响应:**
+```json
+{
+    "code": 404,
+    "success": false,
+    "message": "未找到ID为999的品牌记录",
+    "data": null
+}
+```
+
+### 2.5 删除品牌记录
+
+#### 基本信息
+- **URL**: `/delete-hotel-group-brands/<int:brand_id>`
+- **方法**: `DELETE`
+- **功能**: 删除指定ID的品牌记录
+
+#### 路径参数
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| brand_id | integer | 品牌记录ID |
+
+#### 测试样例
+
+**请求示例:**
+```bash
+DELETE /api/data-parse/delete-hotel-group-brands/1
+```
+
+**成功响应示例:**
+```json
+{
+    "code": 200,
+    "success": true,
+    "message": "品牌记录删除成功",
+    "data": {
+        "id": 1,
+        "group_name_en": "IHG Hotels & Resorts",
+        "group_name_zh": "洲际酒店集团",
+        "brand_name_en": "InterContinental",
+        "brand_name_zh": "洲际酒店及度假村",
+        "positioning_level_en": "Upper Upscale",
+        "positioning_level_zh": "超高端",
+        "created_at": "2025-01-19 10:00:00",
+        "updated_at": "2025-01-19 16:30:00",
+        "created_by": "system",
+        "updated_by": "admin",
+        "status": "active"
+    }
+}
+```
+
+---
+
+## 三、错误处理
+
+### 3.1 常见错误场景
+
+#### 缺少必填字段
+```json
+{
+    "code": 400,
+    "success": false,
+    "message": "缺少必填字段: department_zh, position_zh",
+    "data": null
+}
+```
+
+#### 记录不存在
+```json
+{
+    "code": 404,
+    "success": false,
+    "message": "未找到ID为999的职位记录",
+    "data": null
+}
+```
+
+#### 记录重复冲突
+```json
+{
+    "code": 409,
+    "success": false,
+    "message": "职位记录已存在:餐饮部 - 总经理",
+    "data": {
+        "id": 1,
+        "department_zh": "餐饮部",
+        "position_zh": "总经理",
+        "..."
+    }
+}
+```
+
+#### 服务器内部错误
+```json
+{
+    "code": 500,
+    "success": false,
+    "message": "创建酒店职位记录失败: 数据库连接超时",
+    "data": null
+}
+```
+
+### 3.2 错误处理建议
+
+1. **检查HTTP状态码**: 首先检查HTTP响应状态码
+2. **解析响应JSON**: 获取详细的错误信息
+3. **根据code字段处理**: 根据响应中的code字段进行相应处理
+4. **显示用户友好错误信息**: 将技术错误转换为用户可理解的提示
+
+---
+
+## 四、最佳实践
+
+### 4.1 API调用建议
+
+1. **设置合适的超时时间**: 建议设置30秒的请求超时
+2. **处理网络异常**: 实现重试机制,最多重试3次
+3. **验证输入参数**: 在发送请求前验证必填字段
+4. **缓存查询结果**: 对于列表查询,可以实现客户端缓存
+
+### 4.2 数据处理建议
+
+1. **字符串去除空格**: 所有字符串字段会自动去除前后空格
+2. **唯一性检查**: 
+   - 职位表:基于部门中文名称+职位中文名称
+   - 品牌表:基于集团中文名称+品牌中文名称
+3. **状态管理**: 记录状态默认为"active",可设置为"inactive"进行软删除
+
+### 4.3 安全建议
+
+1. **输入验证**: 所有输入都会进行服务端验证
+2. **SQL注入防护**: 使用ORM框架防止SQL注入
+3. **日志记录**: 所有操作都会记录详细日志
+4. **权限控制**: 建议在业务层实现用户权限验证
+
+---
+
+## 五、测试工具推荐
+
+### 5.1 Postman测试集合
+
+可以导入以下Postman集合来快速测试所有API接口:
+
+```json
+{
+    "info": {
+        "name": "酒店数据管理API",
+        "description": "酒店职位和集团品牌管理API测试集合"
+    },
+    "item": [
+        {
+            "name": "获取所有职位",
+            "request": {
+                "method": "GET",
+                "url": "{{baseUrl}}/api/data-parse/get-hotel-positions-list"
+            }
+        },
+        {
+            "name": "新增职位",
+            "request": {
+                "method": "POST",
+                "url": "{{baseUrl}}/api/data-parse/add-hotel-positions",
+                "header": [
+                    {
+                        "key": "Content-Type",
+                        "value": "application/json"
+                    }
+                ],
+                "body": {
+                    "raw": "{\n    \"department_zh\": \"餐饮部\",\n    \"department_en\": \"Food & Beverage Department\",\n    \"position_zh\": \"副总经理\",\n    \"position_en\": \"Deputy General Manager\",\n    \"position_abbr\": \"DGM\",\n    \"level_zh\": \"总监级\",\n    \"level_en\": \"Director Level\"\n}"
+                }
+            }
+        }
+    ]
+}
+```
+
+### 5.2 cURL命令示例
+
+#### 获取职位列表
+```bash
+curl -X GET "http://localhost:5000/api/data-parse/get-hotel-positions-list" \
+  -H "Content-Type: application/json"
+```
+
+#### 新增职位记录
+```bash
+curl -X POST "http://localhost:5000/api/data-parse/add-hotel-positions" \
+  -H "Content-Type: application/json" \
+  -d '{
+    "department_zh": "餐饮部",
+    "department_en": "Food & Beverage Department",
+    "position_zh": "副总经理",
+    "position_en": "Deputy General Manager",
+    "position_abbr": "DGM",
+    "level_zh": "总监级",
+    "level_en": "Director Level"
+  }'
+```
+
+---
+
+## 附录
+
+### A. 数据字典
+
+#### A.1 部门列表(参考)
+- 餐饮部 / Food & Beverage Department
+- 房务部 / Housekeeping Department
+- 市场销售部 / Sales & Marketing Department
+- 人力资源部 / Human Resources Department
+- 财务部 / Finance Department
+- 行政办公室 / Administrative Office
+- 工程部 / Engineering Department
+- 水疗部 / Spa Department
+- 保安部 / Security Department
+
+#### A.2 职级列表(参考)
+- 经理级 / Manager Level
+- 总监级 / Director Level
+- 总经理级 / General Manager Level
+
+#### A.3 定位级别列表(参考)
+- 奢华型 / Luxury
+- 超高端 / Upper Upscale
+- 高端 / Upscale
+- 中高端 / Upper Midscale
+- 中端 / Midscale
+- 经济型 / Economy
+
+### B. 版本历史
+
+| 版本 | 日期 | 修改内容 | 作者 |
+|------|------|----------|------|
+| 1.0 | 2025-01-19 | 初始版本,包含完整CRUD API | 系统 |
+
+---
+
+**文档结束**
+
+> 如有疑问或需要技术支持,请联系开发团队。