mcpField
A
airline-cargo-optimization

airline-cargo-optimization

github.com/kishorkukrejaその他8446 回インストール3 週間前に更新
リポジトリ

airline-cargo-optimization について

airline-cargo-optimizationは、航空貨物チーム向けの計画スキルです。収益、輸送能力、経路、取扱上の制約を考慮し、旅客便のベリー貨物と貨物便を対象に、容量配分、ULD積載、価格設定、複数区間の経路計画を扱います。

主な機能

  1. 01貨物容量の割り当て
  2. 02ULD積載の最適化
  3. 03需要と容量に基づく価格設定
  4. 04複数区間の貨物経路計画
  5. 05特殊貨物の取扱に関する考慮事項

活用シーン

  1. 01旅客手荷物と併せたベリー容量の配分
  2. 02貨物のULD積載計画
  3. 03出発時期と残容量に応じた価格調整
  4. 04乗り継ぎ便を使った貨物経路の計画

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kishorkukreja/awesome-supply-chain --skill airline-cargo-optimization

インストール後、Claude Code で/airline-cargo-optimizationを入力して読み込まれたか確認します。

詳細

航空貨物の最適化

航空貨物の運航と航空貨物輸送の最適化に精通しています。旅客運航と運航上の制約とのバランスを取りながら、容量配分、価格設定、経路選定、取り扱いを最適化し、貨物収入の最大化を支援します。

初期評価

航空貨物を最適化する前に、以下を把握します。

  1. 貨物運航の種類

    • 貨物運航の形態は何ですか?(貨物専用、旅客便のベリー搭載、コンビ、貨物専用機)
    • ネットワーク構造はどのようなものですか?(ハブ・アンド・スポーク、ポイント・ツー・ポイント、地域型)
    • 主な輸送路線と市場はどこですか?
    • フォワーダーとの関係はどうなっていますか?
  2. 容量とリソース

    • 機材構成と貨物搭載容量はどうなっていますか?
    • ULD(ユニット・ロード・デバイス)の在庫はどれくらいですか?
    • 貨物取扱施設はありますか?
    • 倉庫と保管の容量はどれくらいですか?
  3. 貨物の構成

    • 貨物の種類は何ですか?(一般貨物、エクスプレス、特殊貨物)
    • 種類別の収入貢献はどれくらいですか?
    • 特別な取扱要件はありますか?(生鮮品、医薬品、危険物)
    • Eコマースと従来型貨物の割合はどうなっていますか?
  4. 目標と課題

    • 主な目標は何ですか?(収入、イールド、搭載率)
    • 現在の課題は何ですか?(容量利用率、価格設定、運航)
    • 旅客と貨物のどちらを優先しますか?
    • どのような技術システムを利用していますか?(CMS、レベニューマネジメント)

航空貨物のフレームワーク

貨物カテゴリー

一般貨物:

  • 標準的な貨物
  • 特別な要件なし
  • 容量計画において最も柔軟

エクスプレスとEコマース:

  • 時間的制約のある貨物
  • 優先的な取扱い
  • 高いイールドが期待できる

特殊貨物:

  • 生鮮品(花、魚介類、青果物)
  • 医薬品(温度管理が必要)
  • 危険物(IATA 規制)
  • 生きた動物
  • 高価値貨物(宝飾品、電子機器)

寸法超過・重量物貨物:

  • 規格外の貨物
  • 特殊な ULD または床面への積載が必要
  • 航空機との適合性に関する制約あり

貨物容量管理

ベリー搭載容量の配分
import numpy as np
import pandas as pd
from pulp import *

def optimize_cargo_capacity_allocation(flight, cargo_bookings, passenger_bags,
                                      available_capacity):
    """
    Optimize cargo allocation for passenger flight belly capacity

    Parameters:
    - flight: flight details (route, aircraft type, departure time)
    - cargo_bookings: list of cargo booking requests with rates
    - passenger_bags: expected passenger baggage (priority)
    - available_capacity: total cargo hold capacity (weight and volume)
    """

    prob = LpProblem("Cargo_Allocation", LpMaximize)

    # Variables: accept booking b (binary) and quantity
    accept = {}
    quantity = {}

    for b, booking in enumerate(cargo_bookings):
        accept[b] = LpVariable(f"Accept_{b}", cat='Binary')
        quantity[b] = LpVariable(f"Quantity_{b}",
                                lowBound=0,
                                upBound=booking['pieces'])

    # Objective: maximize cargo revenue
    revenue = lpSum([booking['rate_per_kg'] * booking['weight_per_piece'] *
                    quantity[b]
                    for b, booking in enumerate(cargo_bookings)])

    prob += revenue

    # Constraints

    # Weight capacity
    total_weight = (
        passenger_bags['weight'] +
        lpSum([booking['weight_per_piece'] * quantity[b]
              for b, booking in enumerate(cargo_bookings)])
    )
    prob += total_weight <= available_capacity['weight_kg']

    # Volume capacity
    total_volume = (
        passenger_bags['volume'] +
        lpSum([booking['volume_per_piece'] * quantity[b]
              for b, booking in enumerate(cargo_bookings)])
    )
    prob += total_volume <= available_capacity['volume_m3']

    # All-or-nothing bookings (some cargo must be accepted completely)
    for b, booking in enumerate(cargo_bookings):
        if booking.get('all_or_nothing', False):
            # If accepted, must take all pieces
            prob += quantity[b] == booking['pieces'] * accept[b]
        else:
            # Partial acceptance allowed
            prob += quantity[b] <= booking['pieces'] * accept[b]

    # Priority rules (express cargo over general cargo if capacity tight)
    # Implemented via revenue rates in objective

    # Solve
    prob.solve(PULP_CBC_CMD(msg=0))

    # Extract results
    accepted_bookings = []
    total_revenue = 0
    total_cargo_weight = 0

    for b, booking in enumerate(cargo_bookings):
        if quantity[b].varValue > 0.1:
            pieces_accepted = quantity[b].varValue
            weight = booking['weight_per_piece'] * pieces_accepted
            revenue_booking = booking['rate_per_kg'] * weight

            accepted_bookings.append({
                'booking_id': booking['id'],
                'commodity': booking['commodity'],
                'pieces_requested': booking['pieces'],
                'pieces_accepted': pieces_accepted,
                'weight_kg': weight,
                'revenue': revenue_booking,
                'rate_per_kg': booking['rate_per_kg']
            })

            total_revenue += revenue_booking
            total_cargo_weight += weight

    return {
        'status': LpStatus[prob.status],
        'total_revenue': value(prob.objective),
        'accepted_bookings': pd.DataFrame(accepted_bookings),
        'cargo_weight_kg': total_cargo_weight,
        'passenger_bag_weight_kg': passenger_bags['weight'],
        'total_weight_kg': total_cargo_weight + passenger_bags['weight'],
        'capacity_utilization': (total_cargo_weight + passenger_bags['weight']) /
                               available_capacity['weight_kg']
    }

# Example usage
flight = {'flight_number': 'AA100', 'route': 'JFK-LAX', 'aircraft': 'B777'}

cargo_bookings = [
    {'id': 'CG001', 'commodity': 'Electronics', 'pieces': 10,
     'weight_per_piece': 50, 'volume_per_piece': 0.2,
     'rate_per_kg': 3.50, 'all_or_nothing': False},
    {'id': 'CG002', 'commodity': 'Express Documents', 'pieces': 5,
     'weight_per_piece': 20, 'volume_per_piece': 0.1,
     'rate_per_kg': 8.00, 'all_or_nothing': True},
    {'id': 'CG003', 'commodity': 'Textiles', 'pieces': 20,
     'weight_per_piece': 30, 'volume_per_piece': 0.3,
     'rate_per_kg': 2.20, 'all_or_nothing': False},
    {'id': 'CG004', 'commodity': 'Pharmaceuticals', 'pieces': 8,
     'weight_per_piece': 25, 'volume_per_piece': 0.15,
     'rate_per_kg': 6.50, 'all_or_nothing': True},
]

passenger_bags = {
    'weight': 3000,  # kg
    'volume': 15     # m3
}

available_capacity = {
    'weight_kg': 5000,
    'volume_m3': 35
}

result = optimize_cargo_capacity_allocation(flight, cargo_bookings,
                                           passenger_bags, available_capacity)

print(f"Total cargo revenue: ${result['total_revenue']:,.2f}")
print(f"Capacity utilization: {result['capacity_utilization']:.1%}")
print(result['accepted_bookings'])

ULD(ユニット・ロード・デバイス)の最適化

ULD の組み付け最適化
class ULDOptimizer:
    """
    Optimize packing of cargo into ULDs (containers and pallets)
    """

    def __init__(self, uld_types):
        self.uld_types = uld_types  # dict of ULD specs

    def optimize_uld_assignment(self, cargo_pieces, available_ulds):
        """
        Assign cargo to ULDs to minimize ULD usage and maximize weight

        3D bin packing problem
        """
        from pulp import *

        prob = LpProblem("ULD_Assignment", LpMinimize)

        # Variables

        # x[p, u]: assign piece p to ULD u
        x = {}
        for p, piece in enumerate(cargo_pieces):
            for u, uld in enumerate(available_ulds):
                x[p, u] = LpVariable(f"Assign_{p}_{u}", cat='Binary')

        # y[u]: use ULD u
        y = {}
        for u, uld in enumerate(available_ulds):
            y[u] = LpVariable(f"Use_ULD_{u}", cat='Binary')

        # Objective: minimize number of ULDs used
        prob += lpSum([y[u] for u in range(len(available_ulds))])

        # Constraints

        # Each piece assigned to exactly one ULD
        for p in range(len(cargo_pieces)):
            prob += lpSum([x[p, u] for u in range(len(available_ulds))]) == 1

        # ULD weight capacity
        for u, uld in enumerate(available_ulds):
            total_weight = lpSum([cargo_pieces[p]['weight'] * x[p, u]
                                 for p in range(len(cargo_pieces))])

            prob += total_weight <= uld['max_weight_kg'] * y[u]

        # ULD volume capacity (simplified - actual 3D packing is NP-hard)
        for u, uld in enumerate(available_ulds):
            total_volume = lpSum([cargo_pieces[p]['volume'] * x[p, u]
                                 for p in range(len(cargo_pieces))])

            prob += total_volume <= uld['max_volume_m3'] * y[u]

        # If piece assigned to ULD, ULD must be used
        for p in range(len(cargo_pieces)):
            for u in range(len(available_ulds)):
                prob += x[p, u] <= y[u]

        # Solve
        prob.solve(PULP_CBC_CMD(msg=0))

        # Extract results
        assignments = []
        for p, piece in enumerate(cargo_pieces):
            for u, uld in enumerate(available_ulds):
                if x[p, u].varValue > 0.5:
                    assignments.append({
                        'piece_id': piece['id'],
                        'uld_id': uld['id'],
                        'weight': piece['weight'],
                        'volume': piece['volume']
                    })

        ulds_used = [uld['id'] for u, uld in enumerate(available_ulds)
                    if y[u].varValue > 0.5]

        return {
            'ulds_used': len(ulds_used),
            'uld_list': ulds_used,
            'assignments': pd.DataFrame(assignments),
            'status': LpStatus[prob.status]
        }

    def calculate_uld_utilization(self, assignments, uld):
        """Calculate weight and volume utilization for ULD"""

        uld_pieces = assignments[assignments['uld_id'] == uld['id']]

        total_weight = uld_pieces['weight'].sum()
        total_volume = uld_pieces['volume'].sum()

        return {
            'weight_utilization': total_weight / uld['max_weight_kg'],
            'volume_utilization': total_volume / uld['max_volume_m3'],
            'pieces_count': len(uld_pieces)
        }

# Example
cargo_pieces = [
    {'id': 'P001', 'weight': 150, 'volume': 0.8},
    {'id': 'P002', 'weight': 200, 'volume': 1.2},
    {'id': 'P003', 'weight': 180, 'volume': 0.9},
    {'id': 'P004', 'weight': 120, 'volume': 0.6},
    {'id': 'P005', 'weight': 250, 'volume': 1.5},
]

available_ulds = [
    {'id': 'ULD_1', 'type': 'AKE', 'max_weight_kg': 1588, 'max_volume_m3': 4.0},
    {'id': 'ULD_2', 'type': 'AKE', 'max_weight_kg': 1588, 'max_volume_m3': 4.0},
    {'id': 'ULD_3', 'type': 'PMC', 'max_weight_kg': 6033, 'max_volume_m3': 16.0},
]

optimizer = ULDOptimizer(uld_types={})
result = optimizer.optimize_uld_assignment(cargo_pieces, available_ulds)

print(f"ULDs used: {result['ulds_used']}")
print(f"ULD list: {result['uld_list']}")

貨物レベニューマネジメント

貨物の動的価格設定
def optimize_cargo_pricing(flight, capacity_remaining, days_to_departure,
                          historical_demand, competitor_rates):
    """
    Dynamic pricing for air cargo based on demand and capacity

    Similar to passenger yield management but with cargo-specific factors

    Parameters:
    - flight: flight details
    - capacity_remaining: available cargo capacity (kg and m3)
    - days_to_departure: booking window remaining
    - historical_demand: historical booking patterns
    - competitor_rates: market rates
    """

    # Calculate recommended rates by commodity type

    rates = {}

    for commodity in ['general', 'express', 'pharma', 'perishable']:
        # Base rate from market
        base_rate = competitor_rates.get(commodity, 2.50)

        # Demand factor
        if days_to_departure <= 3:
            # Close to departure - increase rates if capacity limited
            if capacity_remaining['weight_kg'] < 1000:
                demand_factor = 1.5  # High demand, low capacity
            else:
                demand_factor = 0.8  # Need to fill capacity
        elif days_to_departure <= 7:
            demand_factor = 1.1
        else:
            demand_factor = 1.0

        # Commodity premium
        commodity_premium = {
            'general': 1.0,
            'express': 2.5,
            'pharma': 3.0,
            'perishable': 2.0
        }.get(commodity, 1.0)

        # Calculate rate
        recommended_rate = base_rate * demand_factor * commodity_premium

        # Floor and ceiling
        min_rate = base_rate * 0.8
        max_rate = base_rate * 3.0

        recommended_rate = max(min_rate, min(recommended_rate, max_rate))

        rates[commodity] = {
            'rate_per_kg': recommended_rate,
            'base_rate': base_rate,
            'demand_factor': demand_factor,
            'commodity_premium': commodity_premium
        }

    return rates

# Example
flight = {'flight_number': 'AA200', 'route': 'LAX-NRT', 'aircraft': 'B777'}

capacity_remaining = {
    'weight_kg': 1500,
    'volume_m3': 12
}

competitor_rates = {
    'general': 2.50,
    'express': 6.00,
    'pharma': 8.00,
    'perishable': 5.00
}

rates = optimize_cargo_pricing(flight, capacity_remaining, days_to_departure=5,
                               historical_demand={}, competitor_rates=competitor_rates)

for commodity, rate_info in rates.items():
    print(f"{commodity}: ${rate_info['rate_per_kg']:.2f}/kg "
         f"(demand factor: {rate_info['demand_factor']:.2f})")

貨物ネットワークの最適化

複数区間の貨物経路設定
def optimize_cargo_routing(shipments, flight_network, connecting_times):
    """
    Optimize routing of cargo shipments through flight network

    Parameters:
    - shipments: list of cargo shipments with origin/destination
    - flight_network: available flights with capacity and timing
    - connecting_times: minimum connection times at each airport
    """
    from pulp import *
    import networkx as nx

    prob = LpProblem("Cargo_Routing", LpMaximize)

    # Build network graph
    G = nx.DiGraph()

    for flight in flight_network:
        G.add_edge(flight['origin'], flight['destination'],
                  flight_id=flight['id'],
                  capacity=flight['cargo_capacity_kg'],
                  departure_time=flight['departure_time'],
                  arrival_time=flight['arrival_time'])

    # Variables: route shipment s on flight f
    x = {}

    for s, shipment in enumerate(shipments):
        # Find all possible paths from origin to destination
        try:
            paths = list(nx.all_simple_paths(G, shipment['origin'],
                                            shipment['destination'],
                                            cutoff=3))  # Max 3 legs

            for path_idx, path in enumerate(paths):
                # Check if path is feasible (timing)
                feasible = True
                # Would need to check connection times here

                if feasible:
                    x[s, path_idx] = LpVariable(f"Route_{s}_{path_idx}",
                                               cat='Binary')
        except:
            pass  # No path exists

    # Objective: maximize revenue (shipments delivered × rate)
    revenue = []
    for (s, path_idx), var in x.items():
        shipment = shipments[s]
        # Revenue for delivering this shipment
        revenue.append(shipment['revenue'] * var)

    prob += lpSum(revenue)

    # Constraints

    # Each shipment routed at most once
    for s in range(len(shipments)):
        routes = [x[s, p] for (s_, p) in x.keys() if s_ == s]
        if routes:
            prob += lpSum(routes) <= 1

    # Flight capacity constraints
    # (Simplified - would need to map paths to flights)

    # Solve
    prob.solve(PULP_CBC_CMD(msg=0))

    # Extract routes
    selected_routes = []
    for (s, path_idx), var in x.items():
        if var.varValue > 0.5:
            shipment = shipments[s]
            selected_routes.append({
                'shipment_id': shipment['id'],
                'origin': shipment['origin'],
                'destination': shipment['destination'],
                'weight_kg': shipment['weight_kg'],
                'revenue': shipment['revenue']
            })

    return {
        'total_revenue': value(prob.objective),
        'routes': selected_routes
    }

特殊貨物の取扱い

温度管理が必要な貨物
class TemperatureControlledCargo:
    """
    Manage pharmaceutical and perishable cargo requiring temp control
    """

    def __init__(self, aircraft_cool_chain_capacity):
        self.cool_chain_capacity = aircraft_cool_chain_capacity

    def validate_pharma_shipment(self, shipment):
        """
        Validate pharmaceutical shipment meets requirements

        - Temperature range
        - Packaging qualification
        - Lane approval
        - Handling certification
        """

        requirements = {
            'temp_range': shipment.get('required_temp_range', (2, 8)),  # °C
            'packaging': shipment.get('packaging_type'),
            'lane_approved': shipment.get('lane_approved', False),
            'gdp_certified': shipment.get('gdp_certified', False)  # Good Distribution Practice
        }

        validation_result = {
            'approved': True,
            'issues': []
        }

        # Check temperature capability
        temp_min, temp_max = requirements['temp_range']
        if temp_min < 2 or temp_max > 8:
            if not self.cool_chain_capacity.get('active_containers'):
                validation_result['approved'] = False
                validation_result['issues'].append(
                    'Temperature range requires active containers'
                )

        # Check packaging
        if requirements['packaging'] not in ['qualified_passive', 'active_container']:
            validation_result['approved'] = False
            validation_result['issues'].append('Invalid packaging type')

        # Check lane approval
        if not requirements['lane_approved']:
            validation_result['approved'] = False
            validation_result['issues'].append('Lane not approved for pharma')

        return validation_result

    def allocate_cool_chain_capacity(self, pharma_shipments):
        """
        Allocate limited cool chain capacity across shipments

        Prioritize by:
        - Value
        - Urgency
        - Contracted customers
        """

        # Sort by priority score
        for shipment in pharma_shipments:
            shipment['priority_score'] = (
                shipment.get('value_usd', 0) * 0.5 +
                shipment.get('urgency_score', 0) * 0.3 +
                shipment.get('customer_tier', 1) * 0.2
            )

        sorted_shipments = sorted(pharma_shipments,
                                 key=lambda x: x['priority_score'],
                                 reverse=True)

        allocated = []
        capacity_used = 0

        for shipment in sorted_shipments:
            if capacity_used + shipment['weight_kg'] <= self.cool_chain_capacity['weight_kg']:
                allocated.append(shipment)
                capacity_used += shipment['weight_kg']

        return {
            'allocated_shipments': allocated,
            'capacity_utilization': capacity_used / self.cool_chain_capacity['weight_kg']
        }

ツールとライブラリ

Python ライブラリ

最適化:

  • PuLP:線形計画法
  • OR-Tools:Google の最適化ツール
  • networkx:ネットワークの経路設定とフロー

3D パッキング:

  • py3dbp:3D ビンパッキング
  • ULD 最適化向けのカスタムアルゴリズム

データ分析:

  • pandas、numpy:データ操作
  • matplotlib:可視化
商用ソフトウェア

貨物管理システム(CMS):

  • IBS iCargo:包括的な貨物管理
  • Mercator:貨物レベニューマネジメント
  • Champ Cargosystems:貨物 IT ソリューション
  • Smartkargo:クラウドベースの貨物プラットフォーム

レベニューマネジメント:

  • Pros Revenue Management:価格設定の最適化
  • Accelya:貨物収入の最適化

運航:

  • SITA:貨物運航と追跡
  • Descartes:貨物フォワーディングソフトウェア
  • CargoWise:貨物フォワーディングプラットフォーム

ULD 管理:

  • Unilode:ULD のプーリングと管理
  • Nordisk Aviation Products:ULD の追跡
  • Jettainer:ULD ソリューション

よくある課題と解決策

課題:容量予測

問題:

  • 旅客手荷物の量が不確定
  • 直前の貨物予約
  • 予約客の未搭乗やキャンセル

解決策:

  • 旅客手荷物の過去データ分析
  • 季節調整係数
  • 動的な容量開放
  • オーバーブッキング戦略
  • リアルタイムの容量更新
課題:ベリー搭載と貨物専用機の採算性

問題:

  • 貨物専用機の運航にかかる固定費
  • 副産物としてのベリー搭載容量
  • 市場運賃の圧力

解決策:

  • ネットワークの最適化(ベリー搭載+貨物専用機)
  • 貨物専用機の稼働率目標(>80%)
  • トラック輸送から貨物専用機への切り替え分析
  • ウェットリースの柔軟な活用
  • アセットライトモデル(チャーター)
課題:ULDの配置

問題:

  • ULDの配置場所が適切でない
  • 再配置コストが高い
  • 主要拠点でULDが不足している

解決策:

  • ULDフロー最適化モデル
  • 空のULDの再配置計画
  • ULDプーリング契約
  • ULD在庫の戦略的配置
  • 代替梱包ソリューション
課題:Eコマースとの統合

問題:

  • 小口貨物で、取扱量が多い
  • スピードが求められる
  • 混載貨物の仕分けが必要

解決策:

  • Eコマース専用商品
  • ハブでの混載貨物仕分け施設
  • エクスプレス取扱手順
  • インテグレーターとの連携
  • スピードに応じたプレミアム価格設定

出力形式

航空会社の貨物業績レポート

エグゼクティブサマリー:

  • ネットワーク全体の貨物業績
  • 収益とイールドの傾向
  • 搭載容量の利用状況
  • 主な機会

フライト業績:

フライト路線機材搭載容量(kg)搭載貨物PAX手荷物利用率収益イールド($/kg)
AA100JFK-LAXB7775,0003,2001,20088%$8,960$2.80
AA200LAX-NRTB7775,0004,10080098%$18,450$4.50
AA300ORD-LHRB7873,5002,40090094%$9,600$4.00

貨物構成:

品目重量(トン)収益イールド($/kg)収益に占める割合
一般貨物450$1,125,000$2.5042%
エクスプレス120$960,000$8.0036%
医薬品45$360,000$8.0013%
生鮮品80$240,000$3.009%
合計695$2,685,000$3.86100%

ULDの利用状況:

ULDタイプ数量平均重量利用率平均容積利用率月間回転数
AKE25082%68%12
PMC15088%75%10
PGA8079%71%8

推奨事項:

  1. LAX-NRT便(イールドの高い路線)の医薬品搭載容量を増やす
  2. より適切な積載計画により、ULDの容積利用率を改善する
  3. JFK-LAX向けのEコマース・エクスプレス商品を開始する
  4. 上位3社のフォワーダーと料金を再交渉する
  5. ORD-PVG便に貨物専用便を追加する(需要が旺盛)

確認事項

より詳しい情報が必要な場合:

  1. どのような貨物運航形態ですか?(貨物専用、ベリー、コンビ)
  2. ネットワーク構成と主要路線はどのようなものですか?
  3. 貨物構成と品目の種類はどのようなものですか?
  4. 現在のイールドと搭載率の指標はどのようなものですか?
  5. どのようなシステムを導入していますか?(CMS、レベニューマネジメント)
  6. 主な課題は何ですか?(容量、価格設定、運航)
  7. どのような特殊貨物の取扱能力がありますか?(医薬品、生鮮品など)

関連スキル

  • network-design:貨物ネットワークの最適化
  • route-optimization:貨物のルート設定
  • inventory-optimization:ULD在庫の管理
  • hotel-inventory-management:レベニューマネジメントの概念
  • 3d-bin-packing:ULD積載の最適化
  • container-loading-optimization:貨物の積み付け
  • demand-forecasting:貨物需要の予測
  • fleet-management:貨物専用機材の管理

コメント