def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.s3 = S3() self.amount = Amount() self.converter = Converter() self.validation = Validation() self.slack = Slack() self.pdf = Pdf()
def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.s3 = S3() self.converter = Converter() self.validation = Validation() self.slack = Slack() # 年間上限金額 self.max_amount = int(settings.MAX_AMOUNT)
class Reminder: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.slack = Slack() def remind_impression(self, elapsed_days=60): self.logger.info(f"感想登録されずに{elapsed_days}日経過したのでリマインドをします") target_entry_time_yyyymmdd = self.converter.get_yyyymmdd_specified_days_ago(days_ago=elapsed_days) self.logger.debug(f"target_entry_time_yyyymmdd={target_entry_time_yyyymmdd}") items = self.dynamodb.query_impression_flag_and_entry_time("0", target_entry_time_yyyymmdd) if len(items) == 0: self.logger.info(f"リマインド対象者はいませんでした") return mention_set = set() book_list = list() for item in items: mention_set.add(f"<@{item['slack_id']}>") book_list.append(self.converter.get_list_str(item)) text_list = list() text_list.append(" ".join(mention_set) + " そろそろ読み終わりましたか?読み終わったら感想登録お願いします!") text_list.extend(book_list) channel_name = self.slack.get_channel_name_by_slacker(settings.DEFAULT_CHANNEL_ID) self.slack.send_message_by_slacker(channel=channel_name, text="\n".join(text_list)) return True def remind_impression_minutes(self): self.logger.info("remind minutes!")
class Describe: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.list_history = ListHistory() def specified_entry_no(self, message, entry_no): items = self.dynamodb.query_specified_key_value(self.dynamodb.default_table, 'entry_no', entry_no) if len(items) == 0: message.reply(f"登録番号 *[{entry_no}]* のデータが見つかりません。") return # プライマリキー指定なので必ず1件取得 item = items[0] self.logger.debug(item) text_list = list() text_list.append(self.converter.get_list_str(item)) impression = item.get('impression') if impression != '': text_list.append(f"```\n{impression}\n```") else: text_list.append("感想は登録されていません。") message.send("\n".join(text_list))
class ListHistory: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.default_record_num = 20 def default(self, message): items = self.dynamodb.find(self.dynamodb.default_table, self.default_record_num) self.logger.info(items) if len(items) == 0: message.reply('まだ登録データが無いようです。') return # 申請日でソート items.sort(key=lambda x: x['entry_time'], reverse=True) text_list = list() for item in items: text_list.append(self.converter.get_list_str(item)) message.send("\n".join(text_list)) def search(self, message, search_words): items = self.dynamodb.scan_contains_search_words(search_words) if len(items) == 0: message.reply('見つかりませんでした...。検索文字を変えてみてください。大文字小文字も区別しますよ。') return # 申請日でソート items.sort(key=lambda x: x['entry_time'], reverse=True) text_list = list() for item in items: text_list.append(self.converter.get_list_str(item)) message.send("\n".join(text_list))
class Delete: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.slack = Slack() self.list_history = ListHistory() def specified_entry_no(self, message, entry_no): # 削除対象レコードを取得 items = self.dynamodb.query_specified_key_value( self.dynamodb.default_table, 'entry_no', entry_no) if len(items) == 0: message.reply(f"登録番号 *[{entry_no}]* のデータが見つかりません。") return # プライマリキー指定なので必ず1件取得 item = items[0] # 削除できるのは自分の登録情報だけ if item['slack_id'] != self.slack.get_slack_id(message): message.reply("削除できるのは自分の登録情報だけです!") return # 感想登録されていたら削除不可とする if item['impression_flag'] == '1': message.reply("感想登録後は削除できません!") return # レコード削除 key = dict() key['entry_no'] = entry_no self.dynamodb.remove(self.dynamodb.default_table, key) text_list = list() text_list.append("以下の登録情報を削除しました!") text_list.append(self.converter.get_list_str(item)) message.reply("\n".join(text_list))
def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.slack = Slack()
class Impression: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.validation = Validation() self.slack = Slack() def save(self, message: Message): now = datetime.now() entry_no = '' impression = '' for block in message.body['blocks']: if not ('text' in block and 'text' in block['text']): continue text = block['text']['text'] if '*登録番号*' in text: entry_no = re.sub('\\D', '', self.converter.to_hankaku(text)) self.logger.debug(f"entry_no={entry_no}") elif '*感想*' in text: impression = re.sub('\*感想\*\n', '', text).strip() self.logger.debug(f"impression={impression}") # 投稿タイムスタンプ(スレッド投稿のため) ts = message.body['ts'] # パラメータチェック if not self.validation.validate_impression(entry_no=entry_no, message=message): self.logger.debug("パラメータチェックNG") return # 申請者 Slack ID slack_id = self.slack.get_slack_id_from_workflow(message.body['text']) # 更新対象レコードを取得 items = self.dynamodb.query_specified_key_value(self.dynamodb.default_table, 'entry_no', entry_no) # プライマリキー指定なので必ず1件取得 item = items[0] if item['slack_id'] != slack_id: message.send(f"<@{slack_id}> 購入者本人以外は感想登録できません!", thread_ts=ts) return False # 感想登録日 impression_time = now.strftime("%Y%m%d%H%M%S") self.logger.debug(f"impression_time={impression_time}") # 感想登録フラグ 1:登録あり impression_flag = '1' # 感想登録 response = self.dynamodb.update_bookbot_entry_impression(entry_no, impression, impression_time, impression_flag) self.logger.debug(response) if response is None: self.logger.error(f"感想の登録に失敗しました") message.send(f"<@{slack_id}> 感想の登録に失敗しました...すいません!", thread_ts=ts) return False item['impression'] = impression reply_texts = [f"<!here> 以下の感想が登録されました!"] reply_texts.append(self.converter.get_list_str(item)) message.send("\n".join(reply_texts), thread_ts=ts)
def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.default_record_num = 20
class Amount: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.s3 = S3() self.converter = Converter() self.validation = Validation() self.slack = Slack() # 年間上限金額 self.max_amount = int(settings.MAX_AMOUNT) def get_all_total_price_in_year(self, target_yyyy=None) -> int: this_year_start, this_year_end = self.converter.get_target_year_start_end(target_yyyy) target_entry_time_start = this_year_start.ljust(14, '0') target_entry_time_end = this_year_end.ljust(14, '9') self.logger.debug(target_entry_time_start) self.logger.debug(target_entry_time_end) items = self.dynamodb.scan_entry_time(target_entry_time_start, target_entry_time_end) all_total_price_in_year = sum(map(lambda x: int(x['book_price']), items)) return all_total_price_in_year def get_total_price_in_this_year(self, slack_name: str) -> int: this_year_start, this_year_end = self.converter.get_this_year_from_today() target_entry_time_start = this_year_start.ljust(14, '0') target_entry_time_end = this_year_end.ljust(14, '9') self.logger.debug(target_entry_time_start) self.logger.debug(target_entry_time_end) items = self.dynamodb.query_entry_time(slack_name, target_entry_time_start, target_entry_time_end) total_price_in_this_year = sum(map(lambda x: int(x['book_price']), items)) return total_price_in_this_year def check_max_amount(self, slack_name: str, book_price: str, total_price_in_this_year=None) -> bool: if total_price_in_this_year is None: total_price_in_this_year = self.get_total_price_in_this_year(slack_name) if total_price_in_this_year + int(book_price) > self.max_amount: self.logger.info(f"今年度の立替金額が{self.max_amount}円を超えてしまいます 対象ユーザ:{slack_name}, 今年度立替金額合計:{total_price_in_this_year}, 今回立替金額:{book_price}") return False self.logger.debug(f"対象ユーザ:{slack_name}, 今年度立替金額合計:{total_price_in_this_year}, 今回立替金額:{book_price}") return True def get_remain_amount(self, slack_name: str, total_price_in_this_year=None) -> int: if total_price_in_this_year is None: total_price_in_this_year = self.get_total_price_in_this_year(slack_name) remain_amount = self.max_amount - total_price_in_this_year # もしマイナスになったら0にしておく if remain_amount < 0: remain_amount = 0 return remain_amount
class Entry: def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.s3 = S3() self.amount = Amount() self.converter = Converter() self.validation = Validation() self.slack = Slack() self.pdf = Pdf() def save(self, message: Message): now = datetime.now() book_name = '' book_type = '' book_price = '' book_url = '' purpose = '' for block in message.body['blocks']: if not ('text' in block and 'text' in block['text']): continue text = block['text']['text'] if '*題名*' in text: book_name = re.sub('\*題名\*|\n', '', text) self.logger.debug(f"book_name={book_name}") elif '*形式*' in text: book_type = re.sub('\*形式\*|\n', '', text) self.logger.debug(f"book_type={book_type}") elif '*立替金額(税込)*' in text: book_price = re.sub('\\D', '', self.converter.to_hankaku(text)) self.logger.debug(f"book_price={book_price}") elif '*詳細リンク(Amazonなど)*' in text: book_url = re.sub('\*詳細リンク(Amazonなど)\*|<|>|\n', '', text) self.logger.debug(f"book_url={book_url}") elif '*購入目的*' in text: purpose = re.sub('\*購入目的\*|<|>|\n', '', text) self.logger.debug(f"purpose={purpose}") # 投稿タイムスタンプ(スレッド投稿のため) ts = message.body['ts'] # パラメータチェック if not self.validation.validate_entry(book_name=book_name, book_price=book_price, book_url=book_url, message=message): self.logger.debug("パラメータチェックNG") return # 申請日 entry_time = now.strftime("%Y%m%d%H%M%S") # 申請者 Slack ID slack_id = self.slack.get_slack_id_from_workflow(message.body['text']) # 申請者名 user_name = self.slack.get_user_name(slack_id, message) slack_name = user_name[0] real_name = user_name[1] # 今年度の合計立替金額を取得 total_price_in_this_year = self.amount.get_total_price_in_this_year(slack_name) # そのユーザが年間上限金額以上立替していないか result = self.amount.check_max_amount(slack_name, book_price, total_price_in_this_year) # 今回申請分を登録する前の 残り金額 remain_amount = self.amount.get_remain_amount(slack_name, total_price_in_this_year) if not result: self.logger.debug("年間立替金額上限を超えています") message.send(f"<@{slack_id}> 年間立替金額上限を超えるため登録できません。残り *{remain_amount}* 円 までならOKです。", thread_ts=ts) return # 受付番号 # アトミックカウンタでシーケンス番号を発行し文字列として取得する entry_no = str(self.dynamodb.atomic_counter('atomic-counter', 'entry_no')) # 今年度の合計立替金額に今回申請分を足す total_price_in_this_year += int(book_price) # 今回申請分を登録した後の 残り金額 remain_amount = self.amount.get_remain_amount(slack_name, total_price_in_this_year) # パーマリンクを取得 permalink = self.slack.get_message_permalink(message) # 感想(空で登録) impression = '' impression_flag = '0' # 0:登録無し item = { 'entry_no': entry_no, 'book_name': book_name, 'book_type': book_type, 'book_price': book_price, 'total_price_in_this_year': total_price_in_this_year, 'remain_amount': remain_amount, 'book_url': book_url, 'purpose': purpose, 'entry_time': entry_time, 'slack_id': slack_id, 'slack_name': slack_name, 'real_name': real_name, 'permalink': permalink, 'impression': impression, 'impression_flag': impression_flag } self.logger.info(f"item={item}") self.dynamodb.insert(self.dynamodb.default_table, item) reply_texts = [f"<@{slack_id}> 登録しました!"] reply_texts.append(f"登録番号: *[{entry_no}]*") reply_texts.append(f"今年度の立替金額合計が *{total_price_in_this_year}* 円になりました。") if remain_amount == 0: reply_texts.append(f"上限金額は *{self.amount.max_amount}* 円です。今年度はこれが最後の立替になります。") else: reply_texts.append(f"残り *{remain_amount}* 円 までならOKです。") if book_price == '0': self.logger.info("0円のため承認PDFは作成しません") message.send("\n".join(reply_texts), thread_ts=ts) return reply_texts.append('補助対象になりますので承認PDFを作成します。') message.send("\n".join(reply_texts), thread_ts=ts) # 承認内容のPDFを作成してSlackにアップ バックアップでS3にアップ # 保存先PDFファイルパス save_pdf_fname = f"{entry_no}_{entry_time}_{slack_name}.pdf" save_pdf_path = f"{app_home}/output_pdf/{save_pdf_fname}" # 承認PDF作成 if not self.pdf.make_approved_pdf(item, save_pdf_path): self.logger.warning('承認PDFの作成に失敗しました') message.send(f"<@{item['slack_id']}> 承認PDFの作成に失敗しました...すいません!") return False channel_name = self.slack.get_channel_name(message) self.logger.debug(channel_name) self.slack.upload_file(message, channel_name, fpath=save_pdf_path, comment="このPDFと購入時の領収書を添付して立替金申請をしてください。", thread_ts=ts) # S3にもアップロード this_year = self.converter.get_this_year_from_today()[0][0:4] # 今年度のYYYY self.s3.upload_to_pdf(save_pdf_path, process_yyyy=this_year)
def __init__(self): self.logger = get_logger(__name__) self.dynamodb = Dynamodb() self.converter = Converter() self.list_history = ListHistory()