feat: 新增崗位描述與清單整合功能 v2.1
主要功能更新: - 崗位描述保存功能:保存後資料寫入資料庫 - 崗位清單自動刷新:切換模組時自動載入最新資料 - 崗位清單檢視功能:點擊「檢視」按鈕載入對應描述 - 管理者頁面擴充:新增崗位資料管理與匯出功能 - CSV 批次匯入:支援崗位與職務資料批次匯入 後端 API 新增: - Position Description CRUD APIs - Position List Query & Export APIs - CSV Template Download & Import APIs 文件更新: - SDD.md 更新至版本 2.1 - README.md 更新功能說明與版本歷史 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
258
add_random_positions.py
Normal file
258
add_random_positions.py
Normal file
@@ -0,0 +1,258 @@
|
||||
"""
|
||||
隨機建立 10 筆崗位資料到系統
|
||||
從 excel_table copy.md 中隨機選取資料並透過 API 建立
|
||||
"""
|
||||
|
||||
import requests
|
||||
import random
|
||||
from datetime import datetime
|
||||
import sys
|
||||
import io
|
||||
|
||||
# 設定 UTF-8 輸出
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||
|
||||
# 從 excel_table copy.md 中讀取的組織及崗位資料
|
||||
org_positions = [
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產部", "position": "組長"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產部", "position": "班長"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產部", "position": "副班長"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產部", "position": "作業員"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產企劃部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產企劃部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產企劃部", "position": "專員"},
|
||||
{"business": "岡山製造事業體", "division": "生產處", "department": "生產企劃部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "組長"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "班長"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "副班長"},
|
||||
{"business": "岡山製造事業體", "division": "岡山製造事業體", "department": "岡山品質管制部", "position": "作業員"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "", "position": "處長"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "", "position": "專員"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "製程工程一部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "製程工程二部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "製程工程二部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "製程工程二部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "設備一部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "設備二部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "設備二部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "封裝工程處", "department": "設備二部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "副總辦公室", "department": "工業工程部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "副總辦公室", "department": "工業工程部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "副總辦公室", "department": "工業工程部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "副總辦公室", "department": "工業工程部", "position": "副理"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "", "position": "處長"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "", "position": "專員"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "測試工程部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "測試工程部", "position": "課長"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "測試工程部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "新產品導入部", "position": "經副理"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "新產品導入部", "position": "專員"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "新產品導入部", "position": "工程師"},
|
||||
{"business": "岡山製造事業體", "division": "測試工程與研發處", "department": "研發部", "position": "經副理"},
|
||||
{"business": "產品事業體", "division": "先進產品事業處", "department": "產品管理部(APD)", "position": "經副理"},
|
||||
{"business": "產品事業體", "division": "先進產品事業處", "department": "產品管理部(APD)", "position": "工程師"},
|
||||
{"business": "產品事業體", "division": "成熟產品事業處", "department": "產品管理部(MPD)", "position": "經副理"},
|
||||
{"business": "產品事業體", "division": "成熟產品事業處", "department": "產品管理部(MPD)", "position": "專案經副理"},
|
||||
{"business": "產品事業體", "division": "成熟產品事業處", "department": "產品管理部(MPD)", "position": "工程師"},
|
||||
{"business": "晶圓三廠", "division": "晶圓三廠", "department": "品質部", "position": "經副理"},
|
||||
{"business": "晶圓三廠", "division": "晶圓三廠", "department": "品質部", "position": "工程師"},
|
||||
{"business": "晶圓三廠", "division": "晶圓三廠", "department": "製造部", "position": "經副理"},
|
||||
{"business": "晶圓三廠", "division": "晶圓三廠", "department": "製造部", "position": "課長"},
|
||||
{"business": "晶圓三廠", "division": "晶圓三廠", "department": "製造部", "position": "班長"},
|
||||
{"business": "晶圓三廠", "division": "製程工程處", "department": "工程一部", "position": "經副理"},
|
||||
{"business": "晶圓三廠", "division": "製程工程處", "department": "工程一部", "position": "工程師"},
|
||||
{"business": "晶圓三廠", "division": "製程工程處", "department": "工程二部", "position": "經副理"},
|
||||
{"business": "晶圓三廠", "division": "製程工程處", "department": "工程二部", "position": "工程師"},
|
||||
{"business": "集團人資行政事業體", "division": "集團人資行政事業體", "department": "招募任用部", "position": "經副理"},
|
||||
{"business": "集團人資行政事業體", "division": "集團人資行政事業體", "department": "招募任用部", "position": "專員"},
|
||||
{"business": "集團人資行政事業體", "division": "集團人資行政事業體", "department": "訓練發展部", "position": "經副理"},
|
||||
{"business": "集團人資行政事業體", "division": "集團人資行政事業體", "department": "訓練發展部", "position": "專員"},
|
||||
{"business": "集團人資行政事業體", "division": "集團人資行政事業體", "department": "薪酬管理部", "position": "經副理"},
|
||||
{"business": "集團人資行政事業體", "division": "集團人資行政事業體", "department": "薪酬管理部", "position": "專員"},
|
||||
]
|
||||
|
||||
# 崗位類別對應
|
||||
position_category_map = {
|
||||
"處長": "02", # 管理職
|
||||
"經副理": "02",
|
||||
"副理": "02",
|
||||
"課長": "02",
|
||||
"組長": "02",
|
||||
"班長": "02",
|
||||
"副班長": "02",
|
||||
"工程師": "01", # 技術職
|
||||
"專員": "04", # 行政職
|
||||
"作業員": "06", # 生產職
|
||||
}
|
||||
|
||||
# 崗位等級對應
|
||||
position_level_map = {
|
||||
"處長": "L7",
|
||||
"經副理": "L5",
|
||||
"副理": "L5",
|
||||
"課長": "L4",
|
||||
"組長": "L3",
|
||||
"班長": "L3",
|
||||
"副班長": "L2",
|
||||
"工程師": "L3",
|
||||
"專員": "L3",
|
||||
"作業員": "L1",
|
||||
}
|
||||
|
||||
# 學歷要求對應
|
||||
education_map = {
|
||||
"處長": "MA", # 碩士
|
||||
"經副理": "BA", # 大學
|
||||
"副理": "BA",
|
||||
"課長": "BA",
|
||||
"組長": "JC", # 專科
|
||||
"班長": "JC",
|
||||
"副班長": "HS", # 高中職
|
||||
"工程師": "BA",
|
||||
"專員": "BA",
|
||||
"作業員": "HS",
|
||||
}
|
||||
|
||||
# 薪資範圍對應
|
||||
salary_range_map = {
|
||||
"處長": "E",
|
||||
"經副理": "D",
|
||||
"副理": "D",
|
||||
"課長": "C",
|
||||
"組長": "C",
|
||||
"班長": "B",
|
||||
"副班長": "B",
|
||||
"工程師": "C",
|
||||
"專員": "C",
|
||||
"作業員": "A",
|
||||
}
|
||||
|
||||
def generate_position_code(business, division, department, position, index):
|
||||
"""生成崗位編號"""
|
||||
# 事業體代碼
|
||||
business_code_map = {
|
||||
"岡山製造事業體": "KS",
|
||||
"產品事業體": "PD",
|
||||
"晶圓三廠": "F3",
|
||||
"集團人資行政事業體": "HR",
|
||||
}
|
||||
|
||||
# 崗位代碼
|
||||
position_code_map = {
|
||||
"處長": "DIR",
|
||||
"經副理": "MGR",
|
||||
"副理": "AMG",
|
||||
"課長": "SUP",
|
||||
"組長": "LDR",
|
||||
"班長": "CHF",
|
||||
"副班長": "ACF",
|
||||
"工程師": "ENG",
|
||||
"專員": "SPC",
|
||||
"作業員": "OPR",
|
||||
}
|
||||
|
||||
biz_code = business_code_map.get(business, "XX")
|
||||
pos_code = position_code_map.get(position, "XXX")
|
||||
|
||||
return f"{biz_code}-{pos_code}-{index:03d}"
|
||||
|
||||
def create_position_data(org_data, index):
|
||||
"""創建崗位資料"""
|
||||
business = org_data["business"]
|
||||
division = org_data["division"]
|
||||
department = org_data["department"]
|
||||
position = org_data["position"]
|
||||
|
||||
position_code = generate_position_code(business, division, department, position, index)
|
||||
|
||||
# 組合崗位名稱
|
||||
dept_str = f"{department}-" if department else ""
|
||||
position_name = f"{dept_str}{position}"
|
||||
|
||||
return {
|
||||
"basicInfo": {
|
||||
"positionCode": position_code,
|
||||
"positionName": position_name,
|
||||
"positionCategory": position_category_map.get(position, "04"),
|
||||
"positionCategoryName": "管理職" if position_category_map.get(position, "04") == "02" else "技術職",
|
||||
"positionNature": "FT",
|
||||
"positionNatureName": "全職",
|
||||
"headcount": str(random.randint(1, 5)),
|
||||
"positionLevel": position_level_map.get(position, "L3"),
|
||||
"effectiveDate": "2024-01-01",
|
||||
"positionDesc": f"{business} {division} {position_name}",
|
||||
"positionRemark": f"組織架構: {business} > {division} > {department if department else '(處級)'}"
|
||||
},
|
||||
"recruitInfo": {
|
||||
"minEducation": education_map.get(position, "BA"),
|
||||
"requiredGender": "",
|
||||
"salaryRange": salary_range_map.get(position, "C"),
|
||||
"workExperience": str(random.randint(0, 5)),
|
||||
"minAge": "22",
|
||||
"maxAge": "50",
|
||||
"jobType": "FT",
|
||||
"recruitPosition": position,
|
||||
"jobTitle": position,
|
||||
"jobDesc": "",
|
||||
"positionReq": "",
|
||||
"titleReq": "",
|
||||
"majorReq": "",
|
||||
"skillReq": "",
|
||||
"langReq": "",
|
||||
"otherReq": "",
|
||||
"superiorPosition": "",
|
||||
"recruitRemark": ""
|
||||
}
|
||||
}
|
||||
|
||||
def main():
|
||||
"""主程式"""
|
||||
api_url = "http://localhost:5000/api/positions"
|
||||
|
||||
# 隨機選取 10 筆資料
|
||||
selected = random.sample(org_positions, min(10, len(org_positions)))
|
||||
|
||||
print("=" * 60)
|
||||
print("隨機建立 10 筆崗位資料")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for i, org_data in enumerate(selected, 1):
|
||||
position_data = create_position_data(org_data, i)
|
||||
|
||||
print(f"[{i}/10] 建立崗位: {position_data['basicInfo']['positionCode']} - {position_data['basicInfo']['positionName']}")
|
||||
|
||||
try:
|
||||
response = requests.post(api_url, json=position_data, timeout=5)
|
||||
|
||||
if response.status_code == 201:
|
||||
print(f" [OK] 成功")
|
||||
success_count += 1
|
||||
else:
|
||||
error_msg = response.json().get('error', '未知錯誤')
|
||||
print(f" [ERROR] 失敗: {error_msg}")
|
||||
fail_count += 1
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
print(f" [ERROR] 失敗: 無法連接到伺服器 (請確認伺服器是否已啟動)")
|
||||
fail_count += 1
|
||||
except Exception as e:
|
||||
print(f" [ERROR] 失敗: {str(e)}")
|
||||
fail_count += 1
|
||||
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print(f"建立完成: 成功 {success_count} 筆, 失敗 {fail_count} 筆")
|
||||
print("=" * 60)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user