workforce-scheduling について
倉庫やサプライチェーン運営向けの人員配置スキルです。需要、人件費、従業員の勤務可能時間、スキル、コンプライアンス上の制約を考慮したシフト計画を支援します。
主な機能
- 01労働需要と人員供給の評価
- 02シフト設計方式の比較
- 03配置目標と制約の定式化
- 04貪欲法や整数計画法の活用
- 05希望条件とリアルタイム変更への対応
- 06シフト・コスト・指標のレポート作成
活用シーン
- 01需要が変動する倉庫のシフト計画
- 02通常勤務・残業・臨時雇用の調整
- 03勤務可能時間・スキル・休息規則の考慮
- 04欠勤や需要急増への対応
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ kishorkukreja/ awesome-supply-chain --skill workforce-schedulingインストール後、Claude Code で/workforce-schedulingを入力して読み込まれたか確認します。
詳細
労働力のシフトスケジューリング
倉庫およびサプライチェーン業務における労働力のシフトスケジューリングと労働力の最適化の専門家です。労働力の供給を需要に合わせ、コストを最小限に抑え、コンプライアンスを確保し、従業員の満足度を高める最適なシフトスケジュールの作成を支援します。
初期評価
労働力のシフトスケジューリングを最適化する前に、次の項目を把握します。
-
労働需要
- 日次/週次の注文量のパターンはどのようになっていますか?
- 繁忙期や季節性はありますか?
- 実施する作業(ピッキング、梱包、入荷処理)は何ですか?
- 必要なスキルや資格は何ですか?
- サービスレベルの目標(納期どおりの出荷)は何ですか?
-
労働力の供給
- 労働力の総人数(フルタイム、パートタイム、臨時)は何人ですか?
- 従業員の勤務可能時間や希望はどのようになっていますか?
- スキルレベルやクロストレーニングの状況はどうなっていますか?
- 希望するシフトの長さ(8時間、10時間、12時間)はどれですか?
- 労働組合の規則や労働協約はありますか?
-
業務上の制約
- 稼働時間(週5日24時間、週7日24時間、日勤のみ)はどのようになっていますか?
- 最低必要人員数は何人ですか?
- 連続勤務日数の上限はありますか?
- 残業の規則とコストはどのようになっていますか?
- 休憩や食事時間に関する要件はありますか?
- 週末や祝日の人員配置は必要ですか?
-
現状
- 現在のスケジュール作成方法(手作業、ソフトウェア)は何ですか?
- 現在の労務費(通常勤務+残業)はいくらですか?
- 労働力の稼働率はどのくらいですか?
- 従業員は現在のスケジュールに満足していますか?
- スケジュールの変更頻度はどのくらいですか?
労働力のシフトスケジューリングの枠組み
スケジューリングの目標
主な目標:
- 需要への適合:予測される業務量に対して十分な労働力を確保します
- コストの最小化:通常勤務時間、残業、臨時従業員の構成を最適化します
- 稼働率の最大化:待機時間や過剰人員を削減します
- 従業員の満足度:希望、公平性、ワークライフバランスを考慮します
- コンプライアンス:労働法、労働組合の規則、会社の方針を遵守します
主な指標:
- 単位あたりの労務費(注文あたりのドル額、ピッキングした明細行あたりのドル額)
- 労働力の稼働率(%)(生産的な時間/スケジュール上の時間)
- スケジュール効率(実績と計画の労働時間の比較)
- 従業員の離職率と欠勤率
- 残業率(残業時間/総労働時間)
シフト設計の戦略
1. 固定シフト
- 毎週同じスケジュール
- メリット:予定が立てやすく、生活設計がしやすい
- デメリット:柔軟性がなく、需要に合わない場合があります
- 用途:需要が安定している場合、労働組合のある職場
2. ローテーションシフト
- 従業員が異なるシフトを順番に担当します
- メリット:好ましくないシフトを公平に分担できます
- デメリット:概日リズムを乱し、従業員の負担が増えます
- 用途:24時間365日の業務、公平性を重視する場合
3. 柔軟/変動シフト
- シフトの開始時刻や長さが変動します
- メリット:需要に合わせ、コストを削減できます
- デメリット:従業員にとって予定が立てにくく、スケジュール作成も難しくなります
- 用途:需要が変動する場合、労務費への感度が高い場合
4. 圧縮労働週
- 週5日8時間の代わりに、週4日10時間または週3日12時間勤務にします
- メリット:勤務日数が少なく、従業員に好まれ、必要な人員を確保できます
- デメリット:疲労が蓄積し、割増賃金が必要になる場合があります
- 用途:継続的な業務、従業員の定着
5. オンコール/フレックス人員
- 必要に応じて労働時間を変動させます
- メリット:柔軟性が最大限に高く、コスト効率に優れています
- デメリット:従業員が予定を立てにくく、離職率が上がる場合があります
- 用途:繁忙期、予備要員の確保
数理的な定式化
最適化問題としての労働力スケジューリング
決定変数:
- x[i,s,d] = 従業員 i が日 d にシフト s で勤務する場合は 1、それ以外は 0
- y[s,d] = 日 d のシフト s に配置する従業員数
- o[i,d] = 従業員 i の日 d の残業時間
パラメーター:
- D[s,d] = 日 d のシフト s に必要な労働時間
- C_reg = 通常勤務の時給
- C_ot = 残業の時給(通常は通常勤務の時給の1.5倍)
- C_temp = 臨時従業員の時給
- A[i,s,d] = 従業員 i が日 d のシフト s に勤務できるかどうか(0 または 1)
- H[s] = シフト s の長さ(時間)
- Max_hours[i] = 従業員 i の週あたりの最大勤務時間
- Min_rest = シフト間に必要な最小休息時間
目的関数:
Minimize:
Total Labor Cost = Regular + Overtime + Temp + Penalties
Formally:
Σ Σ Σ (C_reg × H[s] × x[i,s,d]) # Regular time
+ Σ Σ (C_ot × o[i,d]) # Overtime
+ Σ Σ (C_temp × temp_hours[s,d]) # Temporary workers
+ α × (Σ schedule_disruption_penalty) # Preference violations
+ β × (Σ understaffing_penalty) # Demand shortfall
制約条件:
# 1. Meet demand (with possible understaffing penalty)
for s in shifts:
for d in days:
Σ (H[s] × x[i,s,d]) + temp_hours[s,d] >= D[s,d]
# 2. Each employee works at most one shift per day
for i in employees:
for d in days:
Σ x[i,s,d] <= 1 for all s
# 3. Respect employee availability
for i in employees:
for s in shifts:
for d in days:
x[i,s,d] <= A[i,s,d]
# 4. Maximum hours per week
for i in employees:
for week in weeks:
Σ Σ (H[s] × x[i,s,d]) <= Max_hours[i] for d in week, s in shifts
# 5. Minimum rest between shifts
for i in employees:
for d in days[:-1]:
if x[i, evening_shift, d] = 1:
x[i, morning_shift, d+1] = 0 # Example: no evening then morning
# 6. Maximum consecutive working days
for i in employees:
for d in days:
Σ x[i,s,d'] <= 6 for d' in [d...d+6], s in shifts
# 7. Minimum employees per shift (coverage)
for s in shifts:
for d in days:
Σ x[i,s,d] >= Min_coverage[s,d] for all i
# 8. Skill requirements
for s in shifts:
for d in days:
Σ x[i,s,d] × skill[i,k] >= required_skill[k,s,d]
for all i, k in skills
スケジューリングアルゴリズム
貪欲法による需要主導型スケジューリング
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def greedy_workforce_scheduling(demand, employees, shifts, days):
"""
Greedy heuristic for workforce scheduling
Algorithm:
1. Sort days by demand (highest first)
2. For each day, assign employees to meet demand
3. Prioritize employees with availability and low weekly hours
Parameters:
-----------
demand : dict
{(shift, day): required_hours}
employees : DataFrame
Columns: employee_id, max_hours_per_week, availability
shifts : list
Shift identifiers
days : list
Day identifiers (e.g., dates)
Returns:
--------
Schedule assignments
"""
# Initialize schedule
schedule = []
employee_hours = {emp['employee_id']: 0 for _, emp in employees.iterrows()}
# Sort (shift, day) pairs by demand
demand_sorted = sorted(demand.items(), key=lambda x: x[1], reverse=True)
for (shift, day), required_hours in demand_sorted:
assigned_hours = 0
# Get available employees for this shift/day
available_employees = employees[
employees['availability'].apply(lambda x: (shift, day) in x)
].copy()
# Sort by current hours worked (assign to those with fewer hours first)
available_employees['current_hours'] = available_employees['employee_id'].map(employee_hours)
available_employees = available_employees.sort_values('current_hours')
# Assign employees until demand met
for idx, emp in available_employees.iterrows():
emp_id = emp['employee_id']
shift_length = 8 # Assume 8-hour shifts
# Check if employee can work (not exceeding max hours)
if employee_hours[emp_id] + shift_length <= emp['max_hours_per_week']:
# Assign employee
schedule.append({
'employee_id': emp_id,
'shift': shift,
'day': day,
'hours': shift_length
})
employee_hours[emp_id] += shift_length
assigned_hours += shift_length
if assigned_hours >= required_hours:
break
# Check if demand met
if assigned_hours < required_hours:
print(f"Warning: Understaffed on {day}, shift {shift} "
f"({assigned_hours}/{required_hours} hours)")
return pd.DataFrame(schedule)
# Example usage
employees = pd.DataFrame({
'employee_id': [f'EMP{i:03d}' for i in range(1, 21)],
'max_hours_per_week': [40] * 15 + [20] * 5, # 15 full-time, 5 part-time
'availability': [
[(s, d) for s in ['morning', 'afternoon', 'evening']
for d in range(7)] # Available all shifts/days
for _ in range(20)
]
})
shifts = ['morning', 'afternoon', 'evening']
days = list(range(7)) # Monday=0, Sunday=6
# Demand varies by day and shift
demand = {
(shift, day): np.random.randint(40, 120)
for shift in shifts for day in days
}
# Higher demand on weekdays, mornings and afternoons
for day in range(5): # Mon-Fri
demand[('morning', day)] *= 1.5
demand[('afternoon', day)] *= 1.3
schedule = greedy_workforce_scheduling(demand, employees, shifts, days)
print("Workforce Schedule:")
print(f"Total Scheduled Hours: {schedule['hours'].sum()}")
print(f"Employees Scheduled: {schedule['employee_id'].nunique()}")
print(f"\nSchedule by Shift:")
print(schedule.groupby('shift')['hours'].sum())
整数計画モデル
from pulp import *
def optimize_workforce_schedule(demand, employees, shifts, days,
cost_regular=20, cost_overtime=30):
"""
Optimal workforce scheduling using MIP
Parameters:
-----------
demand : dict
{(shift, day): hours_needed}
employees : DataFrame
Employee data with availability and constraints
shifts : list
Available shifts
days : list
Days to schedule
cost_regular : float
Regular hourly cost
cost_overtime : float
Overtime hourly cost
Returns:
--------
Optimal schedule
"""
prob = LpProblem("Workforce_Scheduling", LpMinimize)
# Decision variables
# x[emp, shift, day] = 1 if employee works this shift on this day
x = LpVariable.dicts("assign",
[(emp['employee_id'], shift, day)
for _, emp in employees.iterrows()
for shift in shifts
for day in days],
cat='Binary')
# Overtime hours variables
overtime = LpVariable.dicts("overtime",
[(emp['employee_id'], day)
for _, emp in employees.iterrows()
for day in days],
lowBound=0,
cat='Continuous')
# Understaffing variables (soft constraint)
understaffed = LpVariable.dicts("understaffed",
[(shift, day) for shift in shifts for day in days],
lowBound=0,
cat='Continuous')
# Objective: minimize cost
shift_hours = 8 # Assume 8-hour shifts
prob += (
# Regular time cost
cost_regular * shift_hours * lpSum([
x[emp['employee_id'], shift, day]
for _, emp in employees.iterrows()
for shift in shifts
for day in days
]) +
# Overtime cost
cost_overtime * lpSum([
overtime[emp['employee_id'], day]
for _, emp in employees.iterrows()
for day in days
]) +
# Understaffing penalty (high cost)
1000 * lpSum([
understaffed[shift, day]
for shift in shifts
for day in days
])
), "Total_Cost"
# Constraints
# 1. Meet demand (with possible understaffing)
for shift in shifts:
for day in days:
prob += (
lpSum([
shift_hours * x[emp['employee_id'], shift, day]
for _, emp in employees.iterrows()
]) + understaffed[shift, day] >= demand.get((shift, day), 0)
), f"Demand_{shift}_{day}"
# 2. Each employee works at most one shift per day
for _, emp in employees.iterrows():
for day in days:
prob += lpSum([
x[emp['employee_id'], shift, day]
for shift in shifts
]) <= 1, f"OneShift_{emp['employee_id']}_{day}"
# 3. Maximum 40 hours per week for full-time (simplified to 5 shifts)
for _, emp in employees.iterrows():
max_shifts = emp['max_hours_per_week'] // shift_hours
prob += lpSum([
x[emp['employee_id'], shift, day]
for shift in shifts
for day in days
]) <= max_shifts, f"MaxHours_{emp['employee_id']}"
# 4. Calculate overtime (hours beyond 40)
for _, emp in employees.iterrows():
total_hours = lpSum([
shift_hours * x[emp['employee_id'], shift, day]
for shift in shifts
for day in days
])
prob += (
overtime[emp['employee_id'], days[0]] >= total_hours - emp['max_hours_per_week']
), f"Overtime_{emp['employee_id']}"
# Solve
prob.solve(PULP_CBC_CMD(msg=0))
# Extract solution
schedule = []
for _, emp in employees.iterrows():
for shift in shifts:
for day in days:
if x[emp['employee_id'], shift, day].varValue > 0.5:
schedule.append({
'employee_id': emp['employee_id'],
'shift': shift,
'day': day,
'hours': shift_hours
})
return {
'status': LpStatus[prob.status],
'total_cost': value(prob.objective),
'schedule': pd.DataFrame(schedule)
}
result = optimize_workforce_schedule(demand, employees, shifts, days)
print(f"\nOptimization Status: {result['status']}")
print(f"Total Cost: ${result['total_cost']:,.2f}")
print(f"\nSchedule Summary:")
print(result['schedule'].groupby('shift').size())
高度なスケジューリング手法
シフト入札と希望に基づくスケジューリング
class PreferenceBasedScheduler:
"""
Schedule based on employee preferences and seniority
"""
def __init__(self, employees, shifts, days):
self.employees = employees
self.shifts = shifts
self.days = days
self.schedule = []
def collect_preferences(self):
"""
Collect employee shift preferences (1-10 scale)
In practice, would come from employee input system
"""
preferences = {}
for _, emp in self.employees.iterrows():
emp_id = emp['employee_id']
preferences[emp_id] = {}
for shift in self.shifts:
for day in self.days:
# Simulate: random preference score
# Higher = more preferred
preferences[emp_id][(shift, day)] = np.random.randint(1, 11)
return preferences
def schedule_with_preferences(self, demand, preferences, seniority):
"""
Create schedule considering preferences and seniority
Algorithm:
1. Sort employees by seniority
2. Senior employees pick preferred shifts first
3. Fill remaining shifts with junior employees
4. Balance to meet demand
Parameters:
-----------
demand : dict
Required staffing
preferences : dict
{employee_id: {(shift, day): preference_score}}
seniority : dict
{employee_id: years_of_service}
Returns:
--------
Schedule with preference satisfaction
"""
# Sort employees by seniority
employees_sorted = sorted(
self.employees['employee_id'],
key=lambda emp_id: seniority.get(emp_id, 0),
reverse=True
)
remaining_demand = demand.copy()
employee_assignments = {emp: 0 for emp in employees_sorted}
schedule = []
# Round 1: Senior employees pick top preferences
for emp_id in employees_sorted:
emp_prefs = preferences[emp_id]
# Get top 5 preferred shifts
top_prefs = sorted(emp_prefs.items(),
key=lambda x: x[1],
reverse=True)[:5]
for (shift, day), pref_score in top_prefs:
# Check if this slot still needs staffing
if remaining_demand.get((shift, day), 0) > 0:
# Check if employee hasn't exceeded weekly hours
if employee_assignments[emp_id] < 5: # Max 5 shifts/week
schedule.append({
'employee_id': emp_id,
'shift': shift,
'day': day,
'hours': 8,
'preference_score': pref_score
})
employee_assignments[emp_id] += 1
remaining_demand[(shift, day)] -= 8
break # Move to next employee
# Round 2: Fill remaining demand with available employees
for (shift, day), needed_hours in remaining_demand.items():
if needed_hours > 0:
# Find employees not yet at capacity
available = [
emp for emp in employees_sorted
if employee_assignments[emp] < 5
]
for emp_id in available:
if needed_hours <= 0:
break
schedule.append({
'employee_id': emp_id,
'shift': shift,
'day': day,
'hours': 8,
'preference_score': preferences[emp_id].get((shift, day), 0)
})
employee_assignments[emp_id] += 1
needed_hours -= 8
schedule_df = pd.DataFrame(schedule)
# Calculate satisfaction metrics
avg_preference = schedule_df['preference_score'].mean()
pref_above_7 = (schedule_df['preference_score'] >= 7).sum() / len(schedule_df) * 100
return {
'schedule': schedule_df,
'avg_preference_score': avg_preference,
'percent_preferred_shifts': pref_above_7
}
# Example
scheduler = PreferenceBasedScheduler(employees, shifts, days)
preferences = scheduler.collect_preferences()
seniority = {f'EMP{i:03d}': np.random.randint(1, 15) for i in range(1, 21)}
result_pref = scheduler.schedule_with_preferences(demand, preferences, seniority)
print("\nPreference-Based Scheduling:")
print(f"Average Preference Score: {result_pref['avg_preference_score']:.2f}/10")
print(f"Preferred Shifts (7+): {result_pref['percent_preferred_shifts']:.1f}%")
リアルタイム調整による動的スケジューリング
class DynamicScheduleManager:
"""
Manage real-time schedule adjustments
Handle call-outs, demand surges, schedule swaps
"""
def __init__(self, base_schedule, employee_pool):
self.base_schedule = base_schedule
self.employee_pool = employee_pool
self.adjustments = []
def handle_callout(self, employee_id, shift, day):
"""
Handle employee call-out and find replacement
Priority:
1. Overtime for already-scheduled employees
2. On-call employees
3. Temporary workers
"""
print(f"Call-out: {employee_id} for {shift} on day {day}")
# Option 1: Ask already-scheduled employees if they can extend/add shift
same_day_workers = self.base_schedule[
(self.base_schedule['day'] == day) &
(self.base_schedule['employee_id'] != employee_id)
]
if len(same_day_workers) > 0:
# Offer overtime to current workers
replacement = same_day_workers.iloc[0]['employee_id']
print(f" Replacement: {replacement} (overtime)")
self.adjustments.append({
'type': 'replacement',
'original': employee_id,
'replacement': replacement,
'shift': shift,
'day': day,
'cost': 'overtime'
})
return replacement
# Option 2: Call on-call employee
on_call = self.employee_pool[self.employee_pool['type'] == 'on_call']
if len(on_call) > 0:
replacement = on_call.iloc[0]['employee_id']
print(f" Replacement: {replacement} (on-call)")
self.adjustments.append({
'type': 'replacement',
'original': employee_id,
'replacement': replacement,
'shift': shift,
'day': day,
'cost': 'regular'
})
return replacement
# Option 3: Hire temp worker
print(f" Replacement: TEMP (temporary agency)")
self.adjustments.append({
'type': 'replacement',
'original': employee_id,
'replacement': 'TEMP',
'shift': shift,
'day': day,
'cost': 'temp_agency'
})
return 'TEMP'
def handle_demand_surge(self, shift, day, additional_hours_needed):
"""
Handle unexpected demand increase
Options:
1. Extend shifts (overtime)
2. Call in off-duty employees
3. Hire temps
"""
print(f"Demand surge: +{additional_hours_needed} hours needed for {shift} on day {day}")
# Option 1: Extend current shift
current_workers = self.base_schedule[
(self.base_schedule['shift'] == shift) &
(self.base_schedule['day'] == day)
]
if len(current_workers) > 0:
# Ask workers to extend shift
overtime_per_worker = additional_hours_needed / len(current_workers)
print(f" Solution: Extend shift for {len(current_workers)} workers "
f"({overtime_per_worker:.1f} OT hours each)")
self.adjustments.append({
'type': 'overtime',
'shift': shift,
'day': day,
'employees': current_workers['employee_id'].tolist(),
'ot_hours': overtime_per_worker
})
return 'overtime'
# Option 2: Call in off-duty
# (implementation similar to call-out)
return 'temp'
# Example usage
manager = DynamicScheduleManager(schedule, employees)
# Simulate call-out
manager.handle_callout('EMP005', 'morning', 2)
# Simulate demand surge
manager.handle_demand_surge('afternoon', 3, 24)
print(f"\nTotal Adjustments: {len(manager.adjustments)}")
ツールとライブラリ
要員スケジューリングソフトウェア
専門的なスケジューリング:
- Workforce Software (Kronos):エンタープライズ向けスケジューリングと勤怠管理
- ADP Workforce Now:人事とスケジューリングの統合
- Shiftboard:シフトスケジューリングと労務管理
- When I Work:従業員向けスケジューリングアプリ
- Deputy:要員管理プラットフォーム
- 7shifts:飲食店・小売店向けスケジューリング
- Humanity (TCP):従業員のスケジューリングと勤怠管理
労務管理機能を備えたWMS:
- Manhattan WMS:労務管理システム(LMS)
- Blue Yonder (JDA) WMS:労務計画とスケジューリング
- SAP EWM:統合された労務管理
- HighJump WMS:標準作業時間を設定したLMSモジュール
Pythonライブラリ
# Optimization
from pulp import *
from ortools.sat.python import cp_model
# Scheduling
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# Constraint Programming
from constraint import Problem, AllDifferentConstraint
よくある課題と解決策
課題:予測できない需要
問題:
- 1日の注文量が±30%変動する
- 必要な要員数を正確に予測できない
- 過剰人員(コストの無駄)または人員不足(出荷漏れ)が発生する
解決策:
- 柔軟な要員体制(中核要員+柔軟要員プール)
- オンコール従業員(4時間前の通知)
- 複数の業務を担当できるようにクロストレーニングする
- 動的スケジューリング(勤務中に調整)
- 残業を緩衝策として活用する(費用は高いものの効果的)
- 派遣会社と提携する(迅速に人員を増やせる)
課題:従業員の勤務可能時間の制約
問題:
- 学生は夕方や週末のみ勤務可能
- 親は特定の時間帯(送迎)を必要とする
- 副業によって勤務可能時間が限られる
- 勤務不可の希望が多い
解決策:
- セルフサービスのシフト入札システム
- パートタイム従業員を採用して要員数を増やす
- 人気の低いシフトには割増賃金を支払う
- スケジュールを事前に通知する(2週間以上前)
- シフト交換を認める(従業員同士)
- 最適化に勤務可能時間の制約を反映する
課題:公平性と士気
問題:
- いつも週末が休みの従業員がいる
- 勤続年数の長い従業員が好条件のシフトを得る
- えこひいきだと受け取られる
- 士気の低下が生産性に影響する
解決策:
- スケジューリングのルールを透明化する
- 人気の低いシフトを公平にローテーションする
- 勤続年数に基づくシフト入札(公平な手続き)
- 週末シフトを均等に割り当てる
- 公平性の指標を追跡し、公表する
- スケジューリングに関する匿名のフィードバックを募る
課題:必要なスキル構成
問題:
- すべての従業員がすべての業務を担当できるわけではない
- フォークリフトの認定オペレーターが必要
- 品質管理には経験豊富な作業員が必要
- 勤務可能時間だけを基準にスケジュールを組めない
解決策:
- 従業員データベースでスキルを管理する
- 最適化にスキルの制約を含める
- シフトごとに必要な有資格者の最低人数を設定する
- クロストレーニングプログラムを実施する(スキルの幅を広げる)
- 重要なスキルには手当を支給する
- 資格の取得状況と更新を管理する
課題:直前の変更
問題:
- 急な欠勤(病気、緊急事態)
- 需要の急増(予期しない大口注文)
- 設備の故障(追加の人員が必要)
- スケジュールが実情に合わなくなる
解決策:
- オンコール要員のプール(要員の10〜15%)
- 欠勤時の自動通知
- 派遣会社との継続契約
- 残業の承認ルール
- リアルタイムでスケジュールを調整するアプリ
- 5〜10%の欠勤率を想定する
出力形式
従業員スケジュールレポート
週間スケジュール - 2024年1月15日~21日の週
スケジュールの概要:
| 曜日 | シフト | 従業員数 | 合計時間 | 需要(時間) | 稼働率 |
|---|---|---|---|---|---|
| 月 | 午前 | 12 | 96 | 92 | 96% |
| 月 | 午後 | 10 | 80 | 78 | 98% |
| 月 | 夜間 | 6 | 48 | 45 | 94% |
| 火 | 午前 | 11 | 88 | 85 | 97% |
| ... | ... | ... | ... | ... | ... |
従業員の割り当て:
Employee: EMP001 (John Smith)
Mon: Morning (6:00-14:00)
Tue: Morning (6:00-14:00)
Wed: Morning (6:00-14:00)
Thu: Morning (6:00-14:00)
Fri: Afternoon (14:00-22:00)
Total: 40 hours
Employee: EMP002 (Jane Doe)
Mon: Afternoon (14:00-22:00)
Wed: Afternoon (14:00-22:00)
Thu: Evening (22:00-6:00)
Sat: Morning (6:00-14:00)
Total: 32 hours (Part-time)
...
コスト分析:
| 区分 | 時間 | 時給 | コスト |
|---|---|---|---|
| 通常勤務 | 1,520 | $20/hr | $30,400 |
| 残業 | 85 | $30/hr | $2,550 |
| 臨時雇用 | 40 | $25/hr | $1,000 |
| 合計 | 1,645 | - | $33,950 |
パフォーマンス指標:
- 平均稼働率:95%
- 残業の割合:5.2%
- 従業員満足度(希望):8.2/10
- 配置率:100%(人員不足のシフトなし)
- 1時間あたりのコスト:$20.64
スケジュールの遵守状況:
- ✓ すべてのシフトで最低人員数を満たしています
- ✓ 通常勤務時間が40時間を超える従業員はいません
- ✓ シフト間に最低11時間の休息時間があります
- ✓ 連続勤務日数が6日を超える従業員はいません
- ✓ スキル要件を満たしています(フォークリフト、QC)
確認事項
さらに詳しい情報が必要な場合は、以下をご確認ください。
- 営業時間とシフト体制はどのようになっていますか?
- 従業員数(フルタイム、パートタイム)はどれくらいですか?
- 需要はどのように変動しますか(日次、週次、季節ごと)?
- どのようなスケジュール上の制約がありますか(労働組合、残業規則)?
- 現在、どのような方法でスケジュールを作成していますか?
- 人件費の内訳はどのようになっていますか(通常勤務、残業、臨時雇用)?
- 従業員に勤務可能時間の制約や希望はありますか?
- スキルや資格の要件はありますか?
関連スキル
- task-assignment-problem:作業者を特定のタスクに割り当てる場合
- capacity-planning:長期的な人員計画を立てる場合
- wave-planning-optimization:人員を考慮してピッキングのウェーブを計画する場合
- demand-forecasting:人員需要を予測する場合
- constraint-programming:複雑なスケジュール制約を扱う場合
- optimization-modeling:数学的なスケジュールモデルを作成する場合
- production-scheduling:製造業の人員スケジュールを作成する場合
コメント
Markdown 対応