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)) # あくまで動作確認用に日付を指定している