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!")
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 delete_handler(message: Message, command, entry_no): logging.info(message.body) if message.body['channel'] != settings.DEFAULT_CHANNEL_ID: slack = Slack() text = f"公式チャンネル #{slack.get_channel_name(message, channel_id=settings.DEFAULT_CHANNEL_ID)} で実行してください!" slack.send_message_with_link_names(message, message.body['channel'], text) return if entry_no is None or entry_no == '': message.send(f"{command} のあとに登録番号(半角数字のみ)を入力してください") return Delete().specified_entry_no(message, entry_no)
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 Total: def __init__(self): self.logger = get_logger(__name__) self.amount = Amount() self.converter = Converter() self.slack = Slack() def default(self, message): # 申請者 Slack ID slack_id = self.slack.get_slack_id(message) # 申請者名 user_name = self.slack.get_user_name(slack_id, message) slack_name = user_name[0] total_price_in_this_year = self.amount.get_total_price_in_this_year(slack_name) remain_amount = self.amount.get_remain_amount(slack_name) text_list = list() text_list.append(f"今年度の立替金合計は *{total_price_in_this_year}* 円 です。") if remain_amount == 0: text_list.append(f"上限金額は *{self.amount.max_amount}* 円です。今年度はこれ以上立替できません。") else: text_list.append(f"残り *{remain_amount}* 円 までならOKです。") message.reply("\n".join(text_list)) def all_total_price_in_year(self, message, target_yyyy): text_list = list() self.logger.debug(len(target_yyyy)) if len(target_yyyy) == 4: all_total_price_in_year = self.amount.get_all_total_price_in_year(target_yyyy) text_list.append(f"{target_yyyy}年度のすべての立替金合計は *{all_total_price_in_year}* 円 です。") else: this_year_start, this_year_end = self.converter.get_this_year_from_today() target_yyyy = this_year_start[0:4] all_total_price_in_year = self.amount.get_all_total_price_in_year(target_yyyy) text_list.append(f"今年度のすべての立替金合計は *{all_total_price_in_year}* 円 です。") message.reply("\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.amount = Amount() self.converter = Converter() self.slack = Slack()
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)