Python中級 - Python中級のチャレンジ - そこそこ複雑な注文集計処理を作る演習問題 - 1問目

main.py の1問目終了時の解答コードです。

  1from datetime import date
  2import os
  3
  4ITEM_TSV_PATH = 'items.tsv'
  5ORDER_DIR = 'order/'
  6FAILURE_DIR = 'failure/'
  7DELIVERY_DIR = 'delivery/'
  8
  9
 10class Item:
 11    """ 1商品に対応するクラス
 12    """
 13    def __init__(self, item_id, name, price):
 14        self.item_id = item_id
 15        self.name = name
 16        self.price = price
 17
 18
 19class Items:
 20    def __init__(self, items):
 21        self.items = items
 22
 23    def has_id(self, item_id):
 24        """ item_id をもつ商品が存在するかチェックする
 25        """
 26        for item in self.items:
 27            if item.item_id == item_id:
 28                return True
 29        return False
 30
 31
 32class Order:
 33    def __init__(self, item_id, amount, shipping_address, tel_number,
 34                 fullname, shipping_date_str, order_file):
 35        self.item_id = item_id
 36        self.amount = amount
 37        self.shipping_address = shipping_address
 38        self.tel_number = tel_number
 39        self.fullname = fullname
 40        self.shipping_date_str = shipping_date_str
 41        self.order_file = order_file
 42
 43        self.amount_int = None
 44        self.shipping_date = None
 45
 46    def validate(self, items):
 47        """ 各注文の値が正しいかバリデーションチェックする。OKの場合True、NGの場合False
 48        """
 49
 50    def row_string(self):
 51        return ','.join((
 52            self.item_id,
 53            self.amount,
 54            self.shipping_address,
 55            self.tel_number,
 56            self.fullname,
 57            self.shipping_date_str,
 58            self.order_file,
 59        ))
 60
 61
 62def load_items():
 63    """ ITEM_TSV_PATHのTSVからItemsを作る
 64    """
 65    items = []
 66    with open(ITEM_TSV_PATH, encoding='utf-8') as f:
 67        for row in f:
 68            item_id, name, price = row.split('\t')
 69            item = Item(item_id.strip(), name.strip(), price.strip())
 70            items.append(item)
 71    return Items(items)
 72
 73
 74def load_orders(target_date):
 75    """ ORDER_DIR のCSVからOrderのリストを作る
 76
 77    * 各値の前後から空白を除外する
 78    """
 79
 80
 81def write_deliver_orders(orders):
 82    """ Orderのリストを受け取って日別注文ファイルに書き込み
 83    """
 84    # 宅配日毎に集計。ファイルをオープンする回数を減らすため事前にまとめる
 85    date_orders = {}
 86    for order in orders:
 87        if order.shipping_date in date_orders:
 88            date_orders[order.shipping_date].append(order)
 89        else:
 90            date_orders[order.shipping_date] = [order]
 91
 92    for d, day_orders in date_orders.items():
 93        filename = 'delivery_{}.csv'.format(d.strftime('%Y%m%d'))
 94        filepath = os.path.join(DELIVERY_DIR, filename)
 95        with open(filepath, 'a', encoding='utf-8') as f:
 96            for order in day_orders:
 97                f.write(order.row_string() + '\n')
 98
 99
100def write_failure_orders(orders, order_date):
101    """ Orderのリストを受け取って注文受付失敗ファイルに書き込み
102    """
103
104
105def main(target_date=None):
106    """ 毎日の注文集計用スクリプト
107
108    1. 商品マスター読み込み
109    2. 当日分の注文受付ファイル読み込み
110    3. 注文をバリデーションチェック
111    4. 日別注文ファイル書き込み
112    5. 注文受付失敗ファイル書き込み
113    """
114    target_date = target_date or date.today()
115
116    items = load_items()
117    orders = load_orders(target_date)
118    validated_orders = []
119    failed_orders = []
120    for order in orders:
121        if order.validate(items):
122            validated_orders.append(order)
123        else:
124            failed_orders.append(order)
125
126    if validated_orders:
127        write_deliver_orders(validated_orders)
128    if failed_orders:
129        write_failure_orders(failed_orders, target_date)
130
131
132if __name__ == '__main__':
133    main(date(2016, 12, 14))  # あくまで動作確認用に日付を指定している
当コンテンツの知的財産権は株式会社ビープラウドに所属します。詳しくは利用規約をご確認ください。