def notify_10mins_ahead(self): try: userdao = UserDAO() current_time = dt.datetime.now() print '-' * 40 print 'push before 10 minutes' print 'current_time :', current_time hour = current_time.hour if current_time.minute >= 20 and current_time.minute <= 29: minute = 30 elif current_time.minute >= 50 and current_time.minute <= 59: hour += 1 minute = 0 else: minute = 0 cron_time = current_time.replace(hour=hour, minute=minute, second=0, microsecond=0) print 'cron_time :', cron_time print '-' * 40 session = Session() result = session.query(Booking, Master, User, UserPushKey) \ .join(Master, Booking.master_id == Master.id) \ .join(User, Booking.user_id == User.id) \ .outerjoin(UserPushKey, User.id == UserPushKey.user_id) \ .filter(or_(Booking.cleaning_status == BC.BOOKING_UPCOMMING, Booking.cleaning_status == BC.BOOKING_STARTED)) \ .filter(func.date(Booking.start_time) == cron_time.date()) \ .filter(func.HOUR(Booking.start_time) == cron_time.time().hour) \ .filter(func.MINUTE(Booking.start_time) == cron_time.time().minute) \ .all() for row in result: key = userdao.get_user_salt_by_id(row.User.id)[:16] crypto = aes.MyCrypto(key) booking_id = row.Booking.id pushkey = row.UserPushKey.pushkey if row.UserPushKey != None else '' user_name = crypto.decodeAES(row.User.name) phone = crypto.decodeAES(row.User.phone) master_name = row.Master.name devicetype = row.User.devicetype print 'push to', user_name, master_name, booking_id print pushkey if devicetype != 'android': pushkey = crypto.decodeAES(row.User.phone) send_10mins_ahead_notification(devicetype, [pushkey], booking_id) send_alimtalk(phone, 'noti_10', user_name, master_name) except Exception, e: print_err_detail(e)
def post(self): self.set_header("Content-Type", "application/json") ret = {} uid = self.get_argument('uid', '') search_keys = self.get_argument('search_keys', '') store_key = self.get_argument('store_key', '') price = self.get_argument('price', 0) price_with_task = self.get_argument('price_with_task', 0) discounted_price = self.get_argument('discounted_price', 0) promotion_code = self.get_argument('promotion_code', '') laundry_apply_all = self.get_argument('laundry_apply_all', 0) # -1 - 없앰, 0 - one time, 1 - all time # convert datetime price = int(price) price_with_task = int(price_with_task) discounted_price = int(discounted_price) laundry_apply_all = int(laundry_apply_all) search_keys = search_keys.split(',') mongo_logger = get_mongo_logger() mix = get_mixpanel() try: session = Session() masterdao = MasterDAO() userdao = UserDAO() promotiondao = PromotionDAO() holder = IntermediateValueHolder() # request id to group each individual bookings request_id = str(uuid.uuid4()) obj = holder.retrieve(store_key) print obj if obj == None: self.set_status(Response.RESULT_OK) add_err_message_to_response(ret, err_dict['err_booking_timeout']) mix.track(uid, 'request timeout', {'time' : dt.datetime.now()}) mongo_logger.error('%s got timed out' % uid) return # retrieve all stored values uid = obj['user_id'] mid = obj['master_id'] dates = obj['dates'] time = obj['time'] appointment_type = obj['appointment_type'] additional_task = obj['additional_task'] taking_time = obj['taking_time'] first_added_time = obj['first_added_time'] additional_time = obj['additional_time'] total_time = obj['total_time'] master_gender = obj['master_gender'] have_pet = obj['have_pet'] isdirty = obj['isdirty'] # hasids to generate unique booking id now = dt.datetime.strftime(dt.datetime.now(), '%Y%m%d%H%M%S') hashids = Hashids(min_length = 16, salt = now + uid) # set tool info havetools = 1 if additional_task >= 64: havetools = 0 card_idx = 0 addr_idx = 0 # get card and address idx addr_idx = userdao.get_user_default_address_index(uid) card_idx = userdao.get_user_default_card_index(uid) i = 1 booking_ids = [] start_time_list = [] for date in dates: # print date, time booking_id = hashids.encode(int(date + time.replace(':', ''))) print 'key', booking_id master_id = mid date = dt.datetime.strptime(date, '%Y%m%d') dow = date.date().weekday() booking_time = dt.time(hour = int(time.split(':')[0]), minute = int(time.split(':')[1])) start_time = dt.datetime.combine(date, booking_time) estimated_end_time = start_time + dt.timedelta(minutes = total_time) cleaning_duration = taking_time actual_price = 0 if i == 1: # 1 번째 클리닝 actual_price = price_with_task - discounted_price # 할인은 1회만 적용됨 else: # 나머지 actual_price = price if havetools == 1: additional_task = 0 else: additional_task = 64 if laundry_apply_all == 1: additional_task += 4 # 빨래 isdirty = 0 # 첫째 이후에는 is dirty는 0 estimated_end_time = estimated_end_time - dt.timedelta(minutes = additional_time + first_added_time) booking = Booking(id = booking_id, request_id = request_id, user_id = uid, master_id = mid, appointment_type = appointment_type, appointment_index = i, dow = dow, booking_time = dt.datetime.now(), org_start_time = start_time, start_time = start_time, estimated_end_time = estimated_end_time, end_time = estimated_end_time, # update after homemaster finish their job cleaning_duration = cleaning_duration, additional_task = additional_task, price = price, price_with_task = actual_price, charging_price = 0, card_idx = card_idx, addr_idx = addr_idx, havetools = havetools, havepet = have_pet, laundry_apply_all = laundry_apply_all, is_dirty = isdirty, master_gender = master_gender, status = BC.BOOKING_UPCOMMING, cleaning_status = BC.BOOKING_UPCOMMING, payment_status = BC.BOOKING_UNPAID_YET) i += 1 session.add(booking) booking_ids.append(booking_id) start_time_list.append(start_time) #print 'booking_id', booking_id, 'was added..' # charge for first appointment date user_name = userdao.get_user_name(uid) if price_with_task - discounted_price <= 0: ret_code = True msg = '' else: ret_code = True msg = '' if ret_code: session.commit() # remove store_key and related_keys holder.remove(store_key) for sk in search_keys: holder.remove(sk) # promotion code 와 연결 if promotion_code != '': promotiondao.set_promotion_code_status(promotion_code, 1, booking_ids[0], price_with_task) session.commit() mix.track(uid, 'confirm booking', {'time' : dt.datetime.now(), 'appointment_type' : appointment_type, 'additional_task' : additional_task}) mongo_logger.debug('confirm booking', extra = {'user_id' : uid, 'master_id' : mid, 'booking_id' : booking_ids[0], 'start_time' : start_time_list[0]}) #ret['response'] = {'booking_ids' : booking_ids} # victor 요청으로 첫번째 ret['response'] = booking_ids[0] self.set_status(Response.RESULT_OK) # notification to managers send_booking_iphone(booking_ids[0]) appointment_type_text = '' if appointment_type == BC.ONE_TIME or appointment_type == BC.ONE_TIME_BUT_CONSIDERING: appointment_type_text = '1회' elif appointment_type == BC.FOUR_TIME_A_MONTH: appointment_type_text = '매주' elif appointment_type == BC.TWO_TIME_A_MONTH: appointment_type_text = '2주 1회' elif appointment_type == BC.ONE_TIME_A_MONTH: appointment_type_text = '4주 1회' master_phone = masterdao.get_master_phone(mid) send_alimtalk(master_phone, 'noti_manager_new', user_name, appointment_type_text) try: first_booking = session.query(Booking, User, MasterPushKey) \ .join(User, Booking.user_id == User.id) \ .outerjoin(MasterPushKey, Booking.master_id == MasterPushKey.master_id) \ .filter(Booking.id == booking_ids[0]) \ .one() except NoResultFound, e: session.close() self.set_status(Response.RESULT_OK) mongo_logger.debug('no first booking record', extra = { 'uid' : uid, 'mid' : mid,'appointment_type' : appointment_type, 'have_pet' : have_pet, 'master_gender' : master_gender, 'isdirty' : isdirty}) add_err_message_to_response(ret, err_dict['err_no_record']) return except MultipleResultsFound, e: session.close() self.set_status(Response.RESULT_OK) mongo_logger.debug('multiple first booking record', extra = { 'uid' : uid, 'mid' : mid, 'appointment_type' : appointment_type, 'have_pet' : have_pet, 'master_gender' : master_gender, 'isdirty' : isdirty}) add_err_message_to_response(ret, err_dict['err_multiple_record']) return
def post(self): self.set_header("Content-Type", "application/json") booking_id = self.get_argument('booking_id', '') reason_id = self.get_argument('reason_id', 0) etc_reason = self.get_argument('etc_reason', '') reason_id = int(reason_id) ret = {} mongo_logger = get_mongo_logger() mix = get_mixpanel() try: session = Session() try: row = session.query(Booking, Master, User, UserAddress) \ .join(Master, Booking.master_id == Master.id) \ .join(User, Booking.user_id == User.id) \ .join(UserDefaultAddress, User.id == UserDefaultAddress.user_id) \ .join(UserAddress, and_(UserAddress.user_id == UserDefaultAddress.user_id, UserAddress.user_addr_index == UserDefaultAddress.address_idx)) \ .filter(Booking.id == booking_id) \ .filter(Booking.cleaning_status == BC.BOOKING_UPCOMMING) \ .one() except NoResultFound, e: session.close() self.set_status(Response.RESULT_OK) add_err_message_to_response(ret, err_dict['err_no_entry_to_cancel']) self.write(json.dumps(ret)) return charge = 0 new_status = BC.BOOKING_CANCELED_CHARGE request_id = row.Booking.request_id user_id = row.Booking.user_id appointment_index = row.Booking.appointment_index appointment_time = row.Booking.start_time appointment_type = row.Booking.appointment_type current_status = row.Booking.status current_cleaning_status = row.Booking.cleaning_status current_payment_status = row.Booking.payment_status price = row.Booking.price_with_task now = dt.datetime.now() diff_in_hours = (appointment_time - now).total_seconds() / 3600 if diff_in_hours >= 24: charge = price * BC.BOOKING_CHARGE_RATE_NO elif 4 <= diff_in_hours < 24: charge = price * BC.BOOKING_CHARGE_RATE_30 else: charge = price * BC.BOOKING_CHARGE_RATE_50 if current_payment_status == BC.BOOKING_PAID: new_status = BC.BOOKING_CANCELED_REFUND ''' partial = '1' if charge == 0: partial = '0' cancel_amount = int(price - charge) if cancel_amount > 0: ret_code, msg = cancel_payment(user_id, booking_id, cancel_amount, partial) if ret_code == False: session.close() self.set_status(Response.RESULT_OK) add_err_ko_message_to_response(ret, msg) self.write(json.dumps(ret)) return''' #row.Booking.modified_date = now row.Booking.charging_price = int(charge) row.Booking.status = new_status row.Booking.cleaning_status = BC.BOOKING_CANCELED row.Booking.payment_status = new_status masterdao = MasterDAO() userdao = UserDAO() key = userdao.get_user_salt_by_id(user_id)[:16] crypto = aes.MyCrypto(key) # push to homemaster via sms master_id = row.Master.id master_phone = str(row.Master.phone) master_name = str(row.Master.name) username = str(crypto.decodeAES(row.User.name)) userphone = str(crypto.decodeAES(row.User.phone)) date = str(convert_datetime_format(row.Booking.start_time)) addr = str(crypto.decodeAES(row.UserAddress.address)) appointment_type_text = '' if appointment_type == BC.ONE_TIME or appointment_type == BC.ONE_TIME_BUT_CONSIDERING: appointment_type_text = '1회' elif appointment_type == BC.FOUR_TIME_A_MONTH: appointment_type_text = '매주' elif appointment_type == BC.TWO_TIME_A_MONTH: appointment_type_text = '2주 1회' elif appointment_type == BC.ONE_TIME_A_MONTH: appointment_type_text = '4주 1회' #sms_sender = SMS_Sender() #text = BOOKING_CANCEL_TEXT % (username, userphone, master_name, date) #print sms_sender.send_for_manager(sender = MAIN_CALL, mtype = 'sms', to = MANAGERS_CALL, subject = BOOKING_TEXT_SUBJECT, text = text) for manager_phone in MANAGERS_CALL.split(','): send_alimtalk(manager_phone, 'noti_manager_cancel', username, date, appointment_type_text) master_pushkey = masterdao.get_master_pushkey(master_id) #send_booking_canceled('android', [master_pushkey], booking_id, date) print 'master_pushkey', master_pushkey print booking_id, date #send_alimtalk(master_phone, 'noti_manager_cancel', username, date, appointment_type_text) # adjust appointment index index_result = session.query(Booking).filter( Booking.request_id == request_id).filter( Booking.appointment_index > appointment_index).all() for index_row in index_result: index_row.appointment_index -= 1 CANCEL = 0 cancel_reason = CancelReason(booking_id=booking_id, user_id=user_id, reason_id=reason_id, etc_reason=etc_reason, kind=CANCEL, cancel_time=dt.datetime.now()) session.add(cancel_reason) session.commit() mix.track( user_id, 'cancel', { 'time': dt.datetime.now(), 'reason_id': reason_id, 'etc_reason': etc_reason }) mongo_logger.debug('%s was canceled' % booking_id, extra={ 'user_id': user_id, 'booking_id': booking_id }) ret['response'] = Response.SUCCESS self.set_status(Response.RESULT_OK)
def notify_try_charge_unpaid(self): try: mongo_logger = get_mongo_logger() userdao = UserDAO() bookingdao = BookingDAO() current_time = dt.datetime.now() two_weeks_before = current_time - dt.timedelta(days=28) two_weeks_before = two_weeks_before.date() print '-' * 40 print 'try charge unpaid notification via alimtalk' print 'cron_time :', current_time print '-' * 40 session = Session() result = session.query(Booking, User) \ .join(User, Booking.user_id == User.id) \ .filter(func.Date(Booking.start_time) >= two_weeks_before) \ .filter(Booking.cleaning_status == BC.BOOKING_COMPLETED) \ .filter(Booking.payment_status != BC.BOOKING_PAID) \ .filter(User.is_b2b == 0) \ .filter(Booking.source == 'hm') \ .order_by(Booking.start_time) \ .all() for row in result: if 'b2b.com' in row.User.email: # b2b 무시 continue if row.User.is_b2b == 1: # b2b 무시 continue if row.Booking.source != 'hm': # 11번가 무시 continue key = userdao.get_user_salt_by_id(row.User.id)[:16] crypto = aes.MyCrypto(key) user_id = row.Booking.user_id user_name = crypto.decodeAES(row.User.name) phone = crypto.decodeAES(row.User.phone) booking_id = row.Booking.id appointment_type = row.Booking.appointment_type cleaning_time = convert_datetime_format2( row.Booking.start_time) charge_price = row.Booking.price_with_task price = '{:,}원'.format(charge_price) print booking_id, user_id, user_name, cleaning_time, price status, try_charge, remain_days = bookingdao.is_next_booking_left_over_2days( booking_id) print status, try_charge, remain_days if status == 'FAILURE': # 다음 회차 예약 가져오기 실패. 건너 뜀 continue if try_charge: # 결제를 시도해야함 ret, value = request_payment(user_id, user_name, booking_id, charge_price, appointment_type) if ret: # 결제 성공 row.Booking.payment_status = BC.BOOKING_PAID session.commit() print '*** success ***' send_alimtalk(phone, 'notify_try_charge_unpaid_success', cleaning_time, price) mongo_logger.debug('user try charge success', extra={ 'dt': current_time, 'user_id': user_id, 'booking_id': booking_id, 'price': price, 'cleaning_time': cleaning_time }) else: # 결제 실패 print '*** failed ***' if remain_days == -1: mongo_logger.debug('no booking remains', extra={ 'dt': current_time, 'user_id': user_id, 'booking_id': booking_id, 'price': price, 'cleaning_time': cleaning_time }) elif remain_days > 3: # 3일 초과로 남았으면 실패 공지 send_alimtalk(phone, 'notify_charge_failure', cleaning_time, price) mongo_logger.debug('user try charge fail', extra={ 'dt': current_time, 'user_id': user_id, 'booking_id': booking_id, 'price': price, 'cleaning_time': cleaning_time }) elif remain_days >= 0: # 3일 이내면 전체 취소 print '*** cancel all ***' bookingdao.cancel_all_upcomings(booking_id) send_jandi( 'NEW_BOOKING', "미결제 전체 취소 알림", user_name + ' 고객님 전체 취소됨', '미결제 일시 : {}, 금액 : {}'.format( cleaning_time, price)) send_alimtalk( phone, 'notify_try_charge_unpaid_cancel_all', cleaning_time, price) mongo_logger.debug('user try charge cancel all', extra={ 'dt': current_time, 'user_id': user_id, 'booking_id': booking_id, 'price': price, 'cleaning_time': cleaning_time }) except Exception, e: print_err_detail(e) mongo_logger.error('failed to try charge failure', extra={'err': str(e)})
devicetype = push_row.User.devicetype key = userdao.get_user_salt_by_id(user_id)[:16] crypto = aes.MyCrypto(key) if devicetype == 'android': pushkey = push_row.UserPushKey.pushkey else: pushkey = crypto.decodeAES(push_row.User.phone) phone = crypto.decodeAES(push_row.User.phone) user_name = crypto.decodeAES(push_row.User.name) send_cleaning_complete_notification(devicetype, [pushkey], booking_id) # alim talk send_alimtalk(phone, 'noti_complete', user_name) print booking_id, 'status updated to complete at :', dt.datetime.now( ) except Exception, e: session.rollback() print_err_detail(e) self.set_status(Response.RESULT_SERVERERROR) add_err_message_to_response(ret, err_dict['err_mysql']) finally: session.close() self.write(json.dumps(ret))
class RequestConfirmScheduleHandler(tornado.web.RequestHandler): def post(self): self.set_header("Content-Type", "application/json") self.set_header('Access-Control-Allow-Origin', '*') ret = {} uid = self.get_argument('uid', '') search_keys = self.get_argument('search_keys', '') store_key = self.get_argument('store_key', '') price = self.get_argument('price', 0) price_with_task = self.get_argument('price_with_task', 0) wage_per_hour = self.get_argument('wage_per_hour', 0) address_index = self.get_argument('address_index', 0) discounted_price = self.get_argument('discounted_price', 0) promotion_code = self.get_argument('promotion_code', '') coupon_id = self.get_argument('coupon_id', '') coupon_discount_price = self.get_argument('coupon_discount_price', 0) laundry_apply_all = self.get_argument( 'laundry_apply_all', 0) # -1 - 없앰, 0 - one time, 1 - all time user_type = self.get_argument('user_type', 'unknown') # convert datetime # for ios fix if discounted_price != 0: discounted_price = discounted_price.replace('Optional(', '').replace(')', '') price = int(price) price_with_task = int(price_with_task) discounted_price = int(discounted_price) coupon_discount_price = int(coupon_discount_price) laundry_apply_all = int(laundry_apply_all) wage_per_hour = int(wage_per_hour) print 'price_with_task', price_with_task print 'discounted_price', discounted_price search_keys = search_keys.split(',') mongo_logger = get_mongo_logger() mix = get_mixpanel() try: session = Session() userdao = UserDAO() masterdao = MasterDAO() promotiondao = PromotionDAO() addressdao = AddressDAO() coupondao = CouponDAO() holder = IntermediateValueHolder() # request id to group each individual bookings request_id = str(uuid.uuid4()) obj = holder.retrieve(store_key) print obj if obj == None: self.set_status(Response.RESULT_OK) add_err_message_to_response(ret, err_dict['err_booking_timeout']) mix.track(uid, 'request timeout', {'time': dt.datetime.now()}) mongo_logger.error('%s got timed out' % uid) return # retrieve all stored values uid = obj['user_id'] mid = obj['master_id'] dates = obj['dates'] time = obj['time'] appointment_type = obj['appointment_type'] additional_task = obj['additional_task'] org_additional_task = additional_task taking_time = obj['taking_time'] first_added_time = obj['first_added_time'] additional_time = obj['additional_time'] total_time = obj['total_time'] master_gender = obj['master_gender'] have_pet = obj['have_pet'] isdirty = obj['isdirty'] is_b2b = userdao.is_b2b(uid) # hasids to generate unique booking id now = dt.datetime.strftime(dt.datetime.now(), '%Y%m%d%H%M%S') hashids = Hashids(min_length=16, salt=now + uid) # set tool info havetools = 1 if additional_task >= 64: havetools = 0 card_idx = 0 addr_idx = 0 # get card and address idx if is_b2b: addr_idx = address_index else: addr_idx = userdao.get_user_default_address_index(uid) card_idx = userdao.get_user_default_card_index(uid) i = 1 booking_ids = [] start_time_list = [] for date in dates: # print date, time booking_id = hashids.encode(int(date + time.replace(':', ''))) print 'key', booking_id master_id = mid date = dt.datetime.strptime(date, '%Y%m%d') dow = date.date().weekday() booking_time = dt.time(hour=int(time.split(':')[0]), minute=int(time.split(':')[1])) start_time = dt.datetime.combine(date, booking_time) estimated_end_time = start_time + dt.timedelta( minutes=total_time) cleaning_duration = taking_time actual_price = 0 if i == 1: # 1 번째 클리닝 actual_price = price_with_task - ( discounted_price + coupon_discount_price ) # 할인은 1회만 적용됨 else: # 나머지 actual_price = price if havetools == 1: additional_task = 0 else: additional_task = 64 if laundry_apply_all == 1: additional_task += 4 # 빨래 isdirty = 0 # 첫째 이후에는 is dirty는 0 estimated_end_time = estimated_end_time - dt.timedelta( minutes=additional_time + first_added_time) booking = Booking( id=booking_id, request_id=request_id, user_id=uid, master_id=mid, appointment_type=appointment_type, appointment_index=i, dow=dow, booking_time=dt.datetime.now(), org_start_time=start_time, start_time=start_time, estimated_end_time=estimated_end_time, end_time= estimated_end_time, # update after homemaster finish their job cleaning_duration=cleaning_duration, additional_task=additional_task, price=price, price_with_task=actual_price, charging_price=0, card_idx=card_idx, addr_idx=addr_idx, havetools=havetools, havepet=have_pet, laundry_apply_all=laundry_apply_all, is_dirty=isdirty, master_gender=master_gender, user_type=user_type, wage_per_hour=wage_per_hour, status=BC.BOOKING_UPCOMMING, cleaning_status=BC.BOOKING_UPCOMMING, payment_status=BC.BOOKING_UNPAID_YET) i += 1 session.add(booking) booking_ids.append(booking_id) start_time_list.append(start_time) #print 'booking_id', booking_id, 'was added..' # charge for first appointment date user_name = userdao.get_user_name(uid) if is_b2b: session.commit() # remove store_key and related_keys holder.remove(store_key) for sk in search_keys: holder.remove(sk) send_jandi('NEW_BOOKING', '[b2b]새 예약 알림', 'b2b 고객님 예약완료', user_name) # b2b용 알림톡 추가 필요 ret['response'] = booking_ids[0] self.set_status(Response.RESULT_OK) mongo_logger.debug('b2b confirm booking', extra={ 'user_id': uid, 'master_id': mid, 'booking_id': booking_ids[0] }) return charge_price = price_with_task - (discounted_price + coupon_discount_price) # 1주 1회면서, 이벤트 기간인 경우에는 결제 하지 않음 import redis try: from utils.secrets import REDIS_HOST, REDIS_PORT, REDIS_PWD except ImportError: REDIS_HOST = 'localhost' REDIS_PORT = 6379 REDIS_PWD = '' r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PWD) event_on = r.get('free_event') print event_on if appointment_type == 4 and event_on: charge_price = price_with_task - price # 1회 이벤트 고객임을 명시해야함 # table 필요 free_event = UserFreeEvent(booking_request_id=request_id, user_id=uid, datetime=dt.datetime.now()) session.add(free_event) if charge_price <= 0: ret_code = True msg = '' else: ret_code, msg = request_payment(uid, user_name, booking_ids[0], charge_price, appointment_type) # 결제 정보 출력 print user_name, ret_code, msg if ret_code: session.commit() # remove store_key and related_keys holder.remove(store_key) for sk in search_keys: holder.remove(sk) # promotion code 와 연결 if promotion_code != '': promotiondao.set_promotion_code_status( promotion_code, 1, booking_ids[0], price_with_task) if coupon_id != '': coupondao.set_coupon_status(coupon_id, 1, booking_ids[0], price_with_task) # change status to paid try: first_booking = session.query(Booking, User, MasterPushKey) \ .join(User, Booking.user_id == User.id) \ .outerjoin(MasterPushKey, Booking.master_id == MasterPushKey.master_id) \ .filter(Booking.id == booking_ids[0]) \ .one() except NoResultFound, e: session.close() self.set_status(Response.RESULT_OK) mongo_logger.debug('no first booking record', extra={ 'uid': uid, 'mid': mid, 'appointment_type': appointment_type, 'have_pet': have_pet, 'master_gender': master_gender, 'isdirty': isdirty }) add_err_message_to_response(ret, err_dict['err_no_record']) return except MultipleResultsFound, e: session.close() self.set_status(Response.RESULT_OK) mongo_logger.debug('multiple first booking record', extra={ 'uid': uid, 'mid': mid, 'appointment_type': appointment_type, 'have_pet': have_pet, 'master_gender': master_gender, 'isdirty': isdirty }) add_err_message_to_response( ret, err_dict['err_multiple_record']) return for bid in booking_ids: print 'booking_id', bid, 'was added successfully...' tid = msg first_booking.Booking.tid = tid first_booking.Booking.status = BC.BOOKING_PAID first_booking.Booking.clearning_status = BC.BOOKING_UPCOMMING first_booking.Booking.payment_status = BC.BOOKING_PAID cleaning_time = convert_datetime_format2( first_booking.Booking.start_time) devicetype = first_booking.User.devicetype master_pushkey = first_booking.MasterPushKey.pushkey if first_booking.MasterPushKey != None else '' session.commit() mix.track( uid, 'confirm booking', { 'time': dt.datetime.now(), 'appointment_type': appointment_type, 'additional_task': additional_task }) mongo_logger.debug('confirm booking', extra={ 'log_time': dt.datetime.now(), 'user_id': uid, 'master_id': mid, 'booking_id': booking_ids[0], 'start_time': start_time_list[0] }) #ret['response'] = {'booking_ids' : booking_ids} # victor 요청으로 첫번째 ret['response'] = booking_ids[0] self.set_status(Response.RESULT_OK) # notification to iphone users #send_booking_iphone(booking_ids[0]) # ios released!! 03.23 # alimtalk phone = userdao.get_user_phone(uid) appointment_type_text = '' if appointment_type == BC.ONE_TIME or appointment_type == BC.ONE_TIME_BUT_CONSIDERING: appointment_type_text = '1회' elif appointment_type == BC.FOUR_TIME_A_MONTH: appointment_type_text = '매주' elif appointment_type == BC.TWO_TIME_A_MONTH: appointment_type_text = '2주 1회' elif appointment_type == BC.ONE_TIME_A_MONTH: appointment_type_text = '4주 1회' service = '기본 클리닝' if org_additional_task != 0: service += ', {}'.format( additional_task_string(org_additional_task)) if len(phone) > 11: phone = phone[:11] # jandi notification user_address, _, _ = userdao.get_user_address_by_index( uid, addr_idx) district = addressdao.get_gu_name( userdao.get_user_address(uid)[0]) print district master_name = masterdao.get_master_name(mid) master_phone = masterdao.get_master_phone(mid) send_jandi( 'NEW_BOOKING', '[{}] 새 예약 알림'.format(user_type), user_name + ' 고객님 예약됨', '({}), {} 홈마스터, {}, {}'.format(district, master_name, start_time_list[0], appointment_type_text)) send_alimtalk(phone, 'noti_reservation', user_name, cleaning_time, appointment_type_text, service, 'http://goo.gl/j6PByf') send_alimtalk(phone, 'noti_caution', 'https://goo.gl/FxrJML', 'http://goo.gl/kuCVIh') # notification to homemaster send_new_booking_notification('android', [master_pushkey], booking_ids[0], cleaning_time) content = '''안녕하세요 {} 홈마스터님, 새로운 예약 정보를 알려드립니다. 날짜 : {} 주소 : {} 주기/서비스 : {} {} 자세한 내용은 마스터님 앱에서 확인 부탁 드립니다 ^^'''.format( master_name, convert_datetime_format2(start_time_list[0]), user_address, appointment_type_text, service) message_sender = MessageSender() print master_phone message_sender.send([master_phone], '새로운 예약 알림', content)
def notify_24hours_ahead(self): try: userdao = UserDAO() current_time = dt.datetime.now() print '-' * 40 print 'push before 24 hours' print 'current_time :', current_time hour = current_time.hour minute = 30 if current_time.minute >= 30 else 0 current_time = current_time + dt.timedelta(days=1) cron_time = current_time.replace(hour=hour, minute=minute, second=0, microsecond=0) print 'cron_time :', cron_time print '-' * 40 session = Session() result = session.query(Booking, Master, User, UserPushKey) \ .join(Master, Booking.master_id == Master.id) \ .join(User, Booking.user_id == User.id) \ .outerjoin(UserPushKey, User.id == UserPushKey.user_id) \ .filter(or_(Booking.cleaning_status == BC.BOOKING_UPCOMMING, Booking.cleaning_status == BC.BOOKING_STARTED)) \ .filter(func.date(Booking.start_time) == cron_time.date()) \ .filter(func.HOUR(Booking.start_time) == cron_time.time().hour) \ .filter(func.MINUTE(Booking.start_time) == cron_time.time().minute) \ .all() for row in result: key = userdao.get_user_salt_by_id(row.User.id)[:16] crypto = aes.MyCrypto(key) booking_id = row.Booking.id pushkey = row.UserPushKey.pushkey if row.UserPushKey != None else '' user_name = crypto.decodeAES(row.User.name) phone = crypto.decodeAES(row.User.phone) master_name = row.Master.name devicetype = row.User.devicetype price = row.Booking.price_with_task start_time = row.Booking.start_time print 'push to', user_name, master_name, booking_id print pushkey if devicetype != 'android': pushkey = crypto.decodeAES(row.User.phone) ampm = '오전' hour = start_time.hour if hour >= 12: if hour > 12: hour -= 12 ampm = '오후' minute = start_time.minute time_str = '%s %d시' % (ampm, hour) if minute == 30: time_str += ' 반' send_day_ahead_notification(devicetype, [pushkey], booking_id, user_name, time_str) send_alimtalk(phone, 'noti_24', user_name, master_name) except Exception, e: print_err_detail(e)
def notify_charge_failure(self): try: mongo_logger = get_mongo_logger() userdao = UserDAO() current_time = dt.datetime.now() print '-' * 40 print 'charge failure notification via alimtalk' print 'current_time :', current_time hour = current_time.hour minute = 30 if current_time.minute >= 30 else 0 cron_time = current_time.replace(hour=hour, minute=minute, second=0, microsecond=0) print 'cron_time :', cron_time print '-' * 40 session = Session() result = session.query(Booking, User) \ .join(User, Booking.user_id == User.id) \ .filter(Booking.cleaning_status == BC.BOOKING_COMPLETED) \ .filter(Booking.payment_status != BC.BOOKING_PAID) \ .filter(func.date(Booking.estimated_end_time) == cron_time.date()) \ .filter(func.HOUR(Booking.estimated_end_time) == cron_time.time().hour) \ .filter(func.MINUTE(Booking.estimated_end_time) == cron_time.time().minute) \ .filter(User.is_b2b == 0) \ .filter(Booking.source == 'hm') \ .all() for row in result: if 'b2b.com' in row.User.email: # b2b 무시 continue if row.User.is_b2b == 1: # b2b 무시 continue if row.Booking.source != 'hm': # 11번가 무시 continue key = userdao.get_user_salt_by_id(row.User.id)[:16] crypto = aes.MyCrypto(key) user_id = row.User.id phone = crypto.decodeAES(row.User.phone) cleaning_time = convert_datetime_format2( row.Booking.start_time) price = '{:,}원'.format(row.Booking.price_with_task) try: send_alimtalk(phone, 'notify_charge_failure', cleaning_time, price) mongo_logger.debug('user charge failure', extra={ 'dt': current_time, 'user_id': user_id, 'price': price, 'cleaning_time': cleaning_time }) except Exception, e: mongo_logger.error('err user charge failure', extra={ 'dt': current_time, 'user_id': user_id, 'price': price, 'cleaning_time': cleaning_time }) except Exception, e: print_err_detail(e) mongo_logger.error('failed to user charge failure', extra={'err': str(e)})
def post(self): self.set_header("Content-Type", "application/json") booking_id = self.get_argument('booking_id', '') reason_id = self.get_argument('reason_id', 0) etc_reason = self.get_argument('etc_reason', '') charge_amount = self.get_argument('charge_amount', 0) charge_amount = int(charge_amount) reason_id = int(reason_id) print 'cancel all charge amount : ', charge_amount ret = {} mongo_logger = get_mongo_logger() mix = get_mixpanel() try: session = Session() userdao = UserDAO() masterdao = MasterDAO() stmt = session.query(Booking.request_id).filter( Booking.id == booking_id).subquery() first_startime = session.query(Booking.start_time).filter( Booking.request_id == stmt).order_by( Booking.start_time).first()[0] result = session.query(Booking, Master, User, UserAddress) \ .join(Master, Booking.master_id == Master.id) \ .join(User, Booking.user_id == User.id) \ .join(UserDefaultAddress, User.id == UserDefaultAddress.user_id) \ .join(UserAddress, and_(UserAddress.user_id == UserDefaultAddress.user_id, UserAddress.user_addr_index == UserDefaultAddress.address_idx)) \ .filter(Booking.request_id == stmt) \ .filter(or_(Booking.cleaning_status == BC.BOOKING_UPCOMMING, Booking.cleaning_status == BC.BOOKING_STARTED)) \ .all() # 서비스를 처음 이용한지 2달이 넘었는지 아닌지 조사, # 넘지 않았다면 이미 부과된 금액에 대해서도 1회 서비스 금액 과의 차액만큼 부과됨 current_time = dt.datetime.now() completed_charge = 1 if current_time >= first_startime + dt.timedelta(days=57): completed_charge = 0 cancel_all_charge = 0 # 그동안의 모든 예약에 대해서 처리함 for row in result: charge = 0 new_status = BC.BOOKING_CANCELED_CHARGE bid = row.Booking.id user_id = row.Booking.user_id appointment_time = row.Booking.start_time current_status = row.Booking.status current_cleaning_status = row.Booking.cleaning_status current_payment_status = row.Booking.payment_status price = row.Booking.price_with_task diff_in_hours = (appointment_time - current_time).total_seconds() / 3600 if diff_in_hours >= 24: charge = price * BC.BOOKING_CHARGE_RATE_NO elif 4 <= diff_in_hours < 24: charge = price * BC.BOOKING_CHARGE_RATE_30 else: charge = price * BC.BOOKING_CHARGE_RATE_50 # 이미 지불한 금액에 대해 1회 비용의 차액만큼 계산 if completed_charge == 1: if current_cleaning_status == BC.BOOKING_COMPLETED: # 차액만큼 계속 더함 cancel_all_charge += charge_amount if current_payment_status == BC.BOOKING_PAID and current_cleaning_status == BC.BOOKING_UPCOMMING: new_status = BC.BOOKING_CANCELED_REFUND ''' partial = '1' if charge == 0: partial = '0' cancel_amount = int(price - charge) if cancel_amount > 0: ret_code, msg = cancel_payment(user_id, bid, cancel_amount, partial) if ret_code == False: session.close() self.set_status(Response.RESULT_OK) add_err_ko_message_to_response(ret, msg) self.write(json.dumps(ret)) return ''' #row.Booking.modified_date = current_time row.Booking.charging_price = int(charge) row.Booking.status = new_status row.Booking.cleaning_status = BC.BOOKING_CANCELED row.Booking.payment_status = new_status # add cancel reason CANCEL_ALL = 1 reason = session.query(CancelReason).filter( CancelReason.booking_id == bid) if reason.count() == 0: cancel_reason = CancelReason(booking_id=bid, user_id=user_id, reason_id=reason_id, etc_reason=etc_reason, kind=CANCEL_ALL, cancel_time=dt.datetime.now()) session.add(cancel_reason) else: reason_row = reason.one() reason_row.kind = 1 '''if cancel_all_charge > 0: user_name = userdao.get_user_name(user_id) ret_code, msg = request_charge(user_id, user_name, cancel_all_charge) if ret_code == False: session.close() self.set_status(Response.RESULT_OK) add_err_ko_message_to_response(ret, msg) self.write(json.dumps(ret)) return ''' key = userdao.get_user_salt_by_id(row.User.id)[:16] crypto = aes.MyCrypto(key) # push to homemaster via sms master_id = row.Master.id master_phone = str(row.Master.phone) master_name = str(row.Master.name) username = str(crypto.decodeAES(row.User.name)) userphone = str(crypto.decodeAES(row.User.phone)) date = str(convert_datetime_format(row.Booking.start_time)) addr = str(crypto.decodeAES(row.UserAddress.address)) appointment_type = str(row.Booking.appointment_type) appointment_type_text = '' if appointment_type == BC.ONE_TIME or appointment_type == BC.ONE_TIME_BUT_CONSIDERING: appointment_type_text = '1회' elif appointment_type == BC.FOUR_TIME_A_MONTH: appointment_type_text = '매주' elif appointment_type == BC.TWO_TIME_A_MONTH: appointment_type_text = '2주 1회' elif appointment_type == BC.ONE_TIME_A_MONTH: appointment_type_text = '4주 1회' #sms_sender = SMS_Sender() #text = BOOKING_CANCEL_ALL_TEXT % (appointment_type, username, userphone, master_name, date) #send_result = sms_sender.send_for_manager(sender = MAIN_CALL, mtype = 'sms', to = MANAGERS_CALL, subject = BOOKING_TEXT_SUBJECT, text = text) for manager_phone in MANAGERS_CALL.split(','): send_alimtalk(manager_phone, 'noti_manager_cancel_all', username, date, appointment_type_text) master_pushkey = masterdao.get_master_pushkey(master_id) #send_all_bookings_canceled('android', [master_pushkey], booking_id, date) #send_alimtalk(master_phone, 'noti_manager_cancel_all', username, date, appointment_type_text) session.commit() mix.track( user_id, 'cancel all', { 'time': dt.datetime.now(), 'reason_id': reason_id, 'etc_reason': etc_reason }) mongo_logger.debug('%s was all canceled' % booking_id, extra={ 'user_id': user_id, 'booking_id': booking_id }) ret['response'] = Response.SUCCESS self.set_status(Response.RESULT_OK) except Exception, e: session.rollback() print_err_detail(e) self.set_status(Response.RESULT_SERVERERROR) add_err_message_to_response(ret, err_dict['err_mysql'])
class RequestConfirmScheduleWebHandler(tornado.web.RequestHandler): def post(self): self.set_header("Content-Type", "application/json") self.set_header('Access-Control-Allow-Origin', '*') ret = {} uid = self.get_argument('uid', '') search_keys = self.get_argument('search_keys', '') store_key = self.get_argument('store_key', '') #price = self.get_argument('price', 0) #price_with_task = self.get_argument('price_with_task', 0) #discounted_price = self.get_argument('discounted_price', 0) promotion_code = self.get_argument('promotion_code', '') laundry_apply_all = self.get_argument( 'laundry_apply_all', 0) # -1 - 없앰, 0 - one time, 1 - all time has_card = self.get_argument('has_card', 0) # ---------- card paremeters ------------ cno = self.get_argument('cno', '') expy = self.get_argument('expy', '') expm = self.get_argument('expm', '') ssnf = self.get_argument('ssnf', '') cpftd = self.get_argument('cpftd', '') calias = self.get_argument('calias', '') # register card request_url = '%s:%d/homemaster_payment/register_card' % (PAYMENT_HOST, PAYMENT_PORT) params = {} params['id'] = uid params['cno'] = cno params['expy'] = expy params['expm'] = expm params['ssnf'] = ssnf params['cpftd'] = cpftd params['calias'] = calias has_card = int(has_card) mongo_logger = get_mongo_logger() mix = get_mixpanel() # 카드가 없는 경우에만 카드 등록하고 진행, 있다면 바로 진행 if has_card == 0: response = requests.post(request_url, data=params) result = json.loads(response.text) if response.status_code != 200 or result['response'] == "": print 'An error occurred while register card' print result['err_code'], result['err_msg'] add_err_ko_message_to_response(ret, result['err_msg']) mongo_logger.error('register card failed', extra={'uid': uid}) return laundry_apply_all = int(laundry_apply_all) search_keys = search_keys.split(',') try: session = Session() userdao = UserDAO() masterdao = MasterDAO() promotiondao = PromotionDAO() addressdao = AddressDAO() holder = IntermediateValueHolder() # request id to group each individual bookings request_id = str(uuid.uuid4()) obj = holder.retrieve(store_key) print obj if obj == None: self.set_status(Response.RESULT_OK) add_err_message_to_response(ret, err_dict['err_booking_timeout']) mix.track(uid, 'request timeout', {'time': dt.datetime.now()}) mongo_logger.error('%s got timed out' % uid) return # retrieve all stored values uid = obj['user_id'] mid = obj['master_id'] dates = obj['dates'] time = obj['time'] appointment_type = obj['appointment_type'] additional_task = obj['additional_task'] org_additional_task = additional_task taking_time = obj['taking_time'] first_added_time = obj['first_added_time'] additional_time = obj['additional_time'] total_time = obj['total_time'] master_gender = obj['master_gender'] have_pet = obj['have_pet'] isdirty = obj['isdirty'] # price # price_with_task # discounted_price address, house_size, house_type = userdao.get_user_address_detail( uid) _, _, price, _ = get_time_price(appointment_type, house_type, house_size) _, additional_price = get_additional_task_time_price( additional_task, house_type, house_size) discounted_price = 0 if promotion_code != '': discounted_price = promotiondao.get_discount_price( promotion_code) price_with_task = price + additional_price if 0 < discounted_price <= 100: price_with_task *= (float(100 - discounted_price) / 100) else: price_with_task -= discounted_price price_with_task = int(price_with_task) print '-' * 30 print price, additional_price print promotion_code, price_with_task print '##' * 20 # hasids to generate unique booking id now = dt.datetime.strftime(dt.datetime.now(), '%Y%m%d%H%M%S') hashids = Hashids(min_length=16, salt=now + uid) # set tool info havetools = 1 if additional_task >= 64: havetools = 0 card_idx = 0 addr_idx = 0 # get card and address idx addr_idx = userdao.get_user_default_address_index(uid) card_idx = userdao.get_user_default_card_index(uid) i = 1 booking_ids = [] start_time_list = [] for date in dates: # print date, time booking_id = hashids.encode(int(date + time.replace(':', ''))) print 'key', booking_id master_id = mid date = dt.datetime.strptime(date, '%Y%m%d') dow = date.date().weekday() booking_time = dt.time(hour=int(time.split(':')[0]), minute=int(time.split(':')[1])) start_time = dt.datetime.combine(date, booking_time) estimated_end_time = start_time + dt.timedelta( minutes=total_time) cleaning_duration = taking_time actual_price = 0 if i == 1: # 1 번째 클리닝 actual_price = price_with_task # 할인은 1회만 적용됨 else: # 나머지 actual_price = price if havetools == 1: additional_task = 0 else: additional_task = 64 if laundry_apply_all == 1: additional_task += 4 # 빨래 isdirty = 0 # 첫째 이후에는 is dirty는 0 estimated_end_time = estimated_end_time - dt.timedelta( minutes=additional_time + first_added_time) booking = Booking( id=booking_id, request_id=request_id, user_id=uid, master_id=mid, appointment_type=appointment_type, appointment_index=i, dow=dow, booking_time=dt.datetime.now(), org_start_time=start_time, start_time=start_time, estimated_end_time=estimated_end_time, end_time= estimated_end_time, # update after homemaster finish their job cleaning_duration=cleaning_duration, additional_task=additional_task, price=price, price_with_task=actual_price, charging_price=0, card_idx=card_idx, addr_idx=addr_idx, havetools=havetools, havepet=have_pet, laundry_apply_all=laundry_apply_all, is_dirty=isdirty, master_gender=master_gender, status=BC.BOOKING_UPCOMMING, cleaning_status=BC.BOOKING_UPCOMMING, payment_status=BC.BOOKING_UNPAID_YET) i += 1 session.add(booking) booking_ids.append(booking_id) start_time_list.append(start_time) #print 'booking_id', booking_id, 'was added..' # charge for first appointment date user_name = userdao.get_user_name(uid) if price_with_task <= 0: ret_code = True msg = '' else: ret_code, msg = request_payment(uid, user_name, booking_ids[0], price_with_task, appointment_type) # 결제 정보 출력 print user_name, ret_code, msg if ret_code: session.commit() # remove store_key and related_keys holder.remove(store_key) for sk in search_keys: holder.remove(sk) # promotion code 와 연결 if promotion_code != '': promotiondao.set_promotion_code_status( promotion_code, 1, booking_ids[0], price_with_task) # change status to paid try: first_booking = session.query(Booking, User, MasterPushKey) \ .join(User, Booking.user_id == User.id) \ .outerjoin(MasterPushKey, Booking.master_id == MasterPushKey.master_id) \ .filter(Booking.id == booking_ids[0]) \ .one() except NoResultFound, e: session.close() self.set_status(Response.RESULT_OK) mongo_logger.debug('no first booking record', extra={ 'uid': uid, 'mid': mid, 'appointment_type': appointment_type, 'have_pet': have_pet, 'master_gender': master_gender, 'isdirty': isdirty }) add_err_message_to_response(ret, err_dict['err_no_record']) return except MultipleResultsFound, e: session.close() self.set_status(Response.RESULT_OK) mongo_logger.debug('multiple first booking record', extra={ 'uid': uid, 'mid': mid, 'appointment_type': appointment_type, 'have_pet': have_pet, 'master_gender': master_gender, 'isdirty': isdirty }) add_err_message_to_response( ret, err_dict['err_multiple_record']) return for bid in booking_ids: print 'booking_id', bid, 'was added successfully...' tid = msg first_booking.Booking.tid = tid first_booking.Booking.status = BC.BOOKING_PAID first_booking.Booking.clearning_status = BC.BOOKING_UPCOMMING first_booking.Booking.payment_status = BC.BOOKING_PAID cleaning_time = convert_datetime_format2( first_booking.Booking.start_time) devicetype = first_booking.User.devicetype master_pushkey = first_booking.MasterPushKey.pushkey if first_booking.MasterPushKey != None else '' session.commit() mix.track( uid, 'confirm booking', { 'time': dt.datetime.now(), 'appointment_type': appointment_type, 'additional_task': additional_task }) mongo_logger.debug('confirm booking', extra={ 'log_time': dt.datetime.now(), 'user_id': uid, 'master_id': mid, 'booking_id': booking_ids[0], 'start_time': start_time_list[0] }) #ret['response'] = {'booking_ids' : booking_ids} # victor 요청으로 첫번째 ret['response'] = { 'booking_id': booking_ids[0], 'price': price_with_task } self.set_status(Response.RESULT_OK) # notification to iphone users #send_booking_iphone(booking_ids[0]) # ios released!! 03.23 # alimtalk phone = userdao.get_user_phone(uid) appointment_type_text = '' if appointment_type == BC.ONE_TIME or appointment_type == BC.ONE_TIME_BUT_CONSIDERING: appointment_type_text = '1회' elif appointment_type == BC.FOUR_TIME_A_MONTH: appointment_type_text = '매주' elif appointment_type == BC.TWO_TIME_A_MONTH: appointment_type_text = '2주 1회' elif appointment_type == BC.ONE_TIME_A_MONTH: appointment_type_text = '4주 1회' service = '기본 클리닝' if org_additional_task != 0: service += ', {}'.format( additional_task_string(org_additional_task)) if len(phone) > 11: phone = phone[:11] # notification to managers #send_booking_requested(booking_ids[0]) #for manager_phone in MANAGERS_CALL.split(','): # send_alimtalk(manager_phone, 'noti_manager_new', user_name, appointment_type_text) # jandi notification district = addressdao.get_gu_name( userdao.get_user_address(uid)[0]) send_jandi('NEW_BOOKING', "[웹]새 예약 알림", user_name + ' 고객님 예약됨', '({}), {}'.format(district, appointment_type_text)) #master_phone = masterdao.get_master_phone(mid) #send_alimtalk(master_phone, 'noti_manager_new', user_name, appointment_type_text) web_noti = "예약 변경 및 취소는 오직 모바일 앱을 통해서만 가능합니다.\n스토어에서 ‘홈마스터' 앱을 다운받아 주세요.\n구글플레이스토어 :\nhttps://goo.gl/qJ2g7b\n앱스토어 :\nhttps://goo.gl/1OE5W6\n(고객센터 1800-0199)" send_alimtalk(phone, 'noti_reservation', user_name, cleaning_time, appointment_type_text, service, web_noti) send_alimtalk(phone, 'noti_caution', 'https://goo.gl/FxrJML', 'http://goo.gl/kuCVIh') # notification to homemaster send_new_booking_notification('android', [master_pushkey], booking_ids[0], cleaning_time)
def post(self): self.set_header("Content-Type", "application/json") self.set_header('Access-Control-Allow-Origin', '*') booking_id = self.get_argument('booking_id', '') reason = self.get_argument('reason', '') print booking_id, reason ret = {} try: session = Session() userdao = UserDAO() masterdao = MasterDAO() addressdao = AddressDAO() now = dt.datetime.now().date() + dt.timedelta(days=2) row = session.query(Booking) \ .filter(Booking.id == booking_id) \ .filter(Booking.cleaning_status == 0) \ .filter(func.date(Booking.start_time) >= now) \ .one() master_id = row.master_id start_time = row.start_time request = MasterBookingModifyRequest( master_id=master_id, booking_id=booking_id, reason=reason, org_time=start_time, request_time=dt.datetime.now()) session.add(request) session.commit() row = session.query(Booking, UserAddress) \ .join(UserAddress, and_(Booking.user_id == UserAddress.user_id, Booking.addr_idx == UserAddress.user_addr_index)) \ .filter(Booking.id == booking_id) \ .one() master_name = masterdao.get_master_name(row.Booking.master_id) user_name = userdao.get_user_name(row.Booking.user_id) district = addressdao.get_gu_name( userdao.get_user_address(row.Booking.user_id)[0]) appointment_time = convert_datetime_format2(row.Booking.start_time) for manager_phone in MANAGERS_CALL.split(','): send_alimtalk(manager_phone, 'noti_manager_modify_schedule', master_name, user_name, district, appointment_time) send_jandi( 'HOMEMASTER_REST', "휴무 신청", master_name + ' 홈마스터님 일정변경 신청', '고객 : {}\n지역 : {}\n일정 : {}'.format(user_name, district, appointment_time)) ret['response'] = Response.SUCCESS self.set_status(Response.RESULT_OK) print 'booking_id', booking_id, 'was requested to modify' except NoResultFound, e: session.close() self.set_status(Response.RESULT_OK) add_err_ko_message_to_response( ret, '해당일은 일정 변경이 불가능 합니다. 일정 변경은 최소 이틀전에 가능합니다.') return