示例#1
0
def card_payment_performing(payment_json, amount, order, put_order=True):
    binding_id = payment_json.get('binding_id')
    client_id = payment_json.get('client_id')
    return_url = payment_json.get('return_url')
    if not binding_id or not client_id or not return_url:
        return False, u'Карта не найдена'

    legal = Venue.get(order.venue_id).legal.get()

    try:
        success, result = alfa_bank.create_simple(legal.alfa_login, legal.alfa_password, amount, order.key.id(), return_url,
                                                  client_id)
    except Exception as e:
        send_error("Alfa error", "Alfa failure", str(e))
        success, result = False, u'Не удалось произвести оплату'

    if not success:
        return success, result

    order.payment_id = result
    if put_order:
        order.put()
    success, error = alfa_bank.hold_and_check(legal.alfa_login, legal.alfa_password, order.payment_id, binding_id)
    if not success:
        error = u"Не удалось произвести оплату. %s" % error
    return success, error
示例#2
0
def send_sms(to, text, company_footer=True):
    if company_footer:
        text += u'\n%s' % config.APP_NAME
    data = {
        'apikey':
        SMSPILOT_API_KEY,
        'send': [{
            'from': 'Ru-beacon',
            'to': phone,
            'text': text
        } for phone in to if phone]
    }
    if not data['send']:
        return
    try:
        response = urlfetch.fetch("http://smspilot.ru/api2.php",
                                  payload=json.dumps(data),
                                  method='POST',
                                  headers={
                                      'Content-Type': 'application/json'
                                  }).content
        logging.info(response)
        result = json.loads(response)
        success = "send" in result
        for message in result.get("send", []):
            if message["status"] != "0":
                success = False
    except Exception as e:
        success = False
        response = str(e)
    if not success:
        admins.send_error("sms", "SMS failure", response)
 def get(self):
     now = datetime.datetime.now()
     delta = datetime.timedelta(minutes=MINUTES_INTERVAL)
     namespace_infos = {}
     for namespace in metadata.get_namespaces():
         namespace_manager.set_namespace(namespace)
         orders = Order.query(Order.status == CREATING_ORDER, Order.date_created <= now - delta).fetch()
         if orders:
             infos = []
             for order in orders:
                 if config.APP_KIND == AUTO_APP:
                     info = _handle_auto(order)
                 elif config.APP_KIND == RESTO_APP:
                     info = _handle_resto(order)
                 else:
                     info = [("ERROR", "unknown APP_KIND")]
                 infos.append(info)
             namespace_infos[namespace] = infos
     mail_body = "Orders with creating status\n"
     for namespace in namespace_infos.keys():
         mail_body += 'In namespace = %s:\n' % namespace
         mail_body += "List of orders:\n" + \
                      "\n\n".join("\n".join("%s: %s" % t for t in info) for info in namespace_infos[namespace])
     if namespace_infos:
         namespace_manager.set_namespace('')
         admins.send_error("order", "Orders crashed while creating", mail_body)
示例#4
0
 def get(self):
     statuses = list(NOT_CANCELED_STATUSES)
     statuses.remove(READY_ORDER)
     namespace_orders = {}
     for namespace in metadata.get_namespaces():
         namespace_manager.set_namespace(namespace)
         resto = RestoCompany.get()
         if resto:
             continue
         orders = Order.query(Order.status.IN(statuses),
                              Order.delivery_time < datetime.utcnow() - timedelta(hours=HOURS_BEFORE)).fetch()
         if orders:
             logging.info('-----------------------------')
             namespace_orders[namespace] = orders
         for order in orders:
             logging.info("closing order id=%s, namespace=%s" % (order.key.id(), namespace))
             try:
                 done_order(order, namespace, with_push=False)
             except Exception as e:
                 admins.send_error("closing", "In closing orders occur error!!!", str(e))
     mail_body = u"List of orders not closed:\n"
     for namespace in namespace_orders.keys():
         mail_body += u'In namespace = %s:\n' % namespace
         namespace_manager.set_namespace(namespace)
         for order in namespace_orders[namespace]:
             venue = Venue.get_by_id(order.venue_id)
             venue_title = venue.title if venue else u'Не определено'
             mail_body += u'%s (%s),\n' % (order.key.id(), venue_title)
     if namespace_orders:
         namespace_manager.set_namespace('')
         admins.send_error("order", "Orders not closed", mail_body)
示例#5
0
def fuckup_ios_delivery_types(delivery_types):
    RESTRICTION = {
        'meatme': [DELIVERY],
        'sushimarket': [DELIVERY],
        'nasushi': [DELIVERY],
        'perchiniribaris': [SELF, IN_CAFE],
        'perchiniribarislublino': [SELF, IN_CAFE],
        'burgerhouse': [SELF, IN_CAFE],
        'tykano': [SELF, IN_CAFE],
        'magnolia': [SELF, IN_CAFE],
        'chikarabar': [SELF, IN_CAFE],
        'sushivesla': [DELIVERY],
        'pastadeli': [SELF, IN_CAFE]
    }
    user = get_temporary_user()
    if not is_ios_user() or user.get(VERSION) != 2 or RESTRICTION.get(
            namespace_manager.get_namespace()) == None:
        return delivery_types
    send_error = False
    for delivery_type in delivery_types[:]:
        if int(delivery_type['id']) in RESTRICTION.get(
                namespace_manager.get_namespace()):
            delivery_types.remove(delivery_type)
            send_error = True
    if send_error:
        logging.warning('Cut delivery types: %s' % delivery_types)
        admins.send_error(
            'ios_fuckup', 'Catch Version 2 with 2 delivery types',
            str({
                'user_agent': user.get(USER_AGENT),
                'delivery_types': delivery_types,
                'version': user.get(VERSION),
                'namespace': namespace_manager.get_namespace()
            }))
    return delivery_types
示例#6
0
def send_demo_sms(client):
    text = u'Поздравляем! На Вашу почту поступил тестовый заказ. Хотите боевой?\nhttp://rbcn.mobi/'
    try:
        send_sms([client.tel], text, company_footer=False)
    except Exception as e:
        error_text = str(e)
        error_text += u' В демо компании "%s" (%s).' % (config.APP_NAME, namespace_manager.get_namespace())
        send_error('sms_error', 'Send sms', error_text)
示例#7
0
 def post(self):
     logging.info(self.request.POST)
     country = self.request.get('FromCountry')
     region = self.request.get('FromState')
     phone = self.request.get('From')
     body = self.request.get('Body')
     message = u'Страна: %s\nРегион: %s\nТелефон: %s\nСообщение: %s' % (
         country, region, phone, body)
     logging.info(message)
     admins.send_error('analytics', u'Смс ответ', body=message)
示例#8
0
def handle_500(request, response, exception):
    if config and config.COMPANY_STATUS == COMPANY_IN_PRODUCTION:
        body = """URL: %s
User-Agent: %s
Exception: %s
Logs: https://appengine.google.com/logs?app_id=s~%s&severity_level_override=0&severity_level=3""" \
                        % (request.url, request.headers['User-Agent'], exception, CURRENT_APP_ID)
        admins.send_error("server", "Error 500", body)
    exc_info = sys.exc_info()
    raise exc_info[0], exc_info[1], exc_info[2]
示例#9
0
    def _send_push(self):
        from models.config.config import config

        logging.debug(
            "data:{}, dev_type: {}, parsekey: {}, parserest: {}".format(
                self.data, self.device_type, config.PARSE_APP_API_KEY,
                config.PARSE_REST_API_KEY))
        if not self.data or self.device_type not in DEVICE_CHOICES or not config.PARSE_APP_API_KEY or not config.PARSE_REST_API_KEY:
            logging.warning(
                u'Невозможно послать уведомление, data=%s, device_type=%s' %
                (self.data, self.device_type))
            return
        payload = {
            'channels':
            self.channels,
            'type':
            DEVICE_TYPE_MAP[self.device_type],
            'expiry':
            timestamp(datetime.datetime.utcnow() +
                      datetime.timedelta(days=365)),
            'data':
            self.data,
        }
        headers = {
            'Content-Type': 'application/json',
            'X-Parse-Application-Id': config.PARSE_APP_API_KEY,
            'X-Parse-REST-API-Key': config.PARSE_REST_API_KEY
        }
        logging.debug(headers)
        try:
            result = json.loads(
                urlfetch.fetch('https://api.parse.com/1/push',
                               payload=json.dumps(payload),
                               method='POST',
                               headers=headers,
                               validate_certificate=False,
                               deadline=10).content)
            logging.info(result)

            if result and (result.get('code') or result.get('error')):
                text = u'Namespace = %s\nCode = %s, Error = %s' % (
                    namespace_manager.get_namespace(), result.get('code'),
                    result.get('error'))
                send_error('push', u'Ошибка Parse', text)
        except Exception as e:
            text = str(e)
            send_error('push', u'Parse упал', text)
            result = None
        return result
示例#10
0
def paypal_payment_performing(payment_json, amount, order, client, put_order=True):
    correlation_id = payment_json['correlation_id']
    try:
        success, info = paypal.authorize(order.key.id(), amount / 100.0, client.paypal_refresh_token, correlation_id)
    except Exception as e:
        success, info = False, str(e)
    if success:
        order.payment_id = info
        if put_order:
            order.put()
    error = None
    if not success:
        error = u'Не удалось произвести оплату'
        if not isinstance(info, (str, unicode)):
            info = json.dumps(info)
        send_error("Paypal error", "Paypal failure", info)
    return success, error
示例#11
0
 def get(self):
     time = datetime.datetime.now() - datetime.timedelta(
         days=MAX_DAYS_BEFORE_CANCEL)
     namespace_cancels = {}
     for namespace in metadata.get_namespaces():
         namespace_manager.set_namespace(namespace)
         unused_gifts = SharedGift.query(
             SharedGift.status == SharedGift.READY)
         old_gifts = [gift for gift in unused_gifts if gift.created < time]
         if old_gifts:
             for gift in old_gifts:
                 gift.cancel(namespace)
             namespace_cancels[namespace] = 'Gifts not used within %s days: %s. In company %s\n' % \
                                            (MAX_DAYS_BEFORE_CANCEL, len(old_gifts), config.APP_NAME)
     if namespace_cancels:
         namespace_manager.set_namespace('')
         admins.send_error('order', 'Unused gifts found',
                           ''.join(namespace_cancels.values()))
示例#12
0
    def post(self):
        namespace = namespace_manager.get_namespace()
        order_id = self.request.get_range('order_id')
        logging.debug('Processing %s/%s', namespace, order_id)

        order = Order.get_by_id(order_id)
        if not order:
            logging.error('Not found order, aborting')
            return
        order_url = 'http://auto.rbcn.mobi' + self.uri_for(
            'bitrix_order_info', namespace=namespace, order_id=order_id)

        bm = config.BITRIX_EXT_API_MODULE
        bitrix_params = {bm.param_name: order_url}
        bitrix_params.update(bm.constant_params)
        bitrix_url = "%s?%s" % (bm.url, urllib.urlencode(bitrix_params))
        logging.debug('Bitrix URL is %s', bitrix_url)

        try:
            result = urlfetch.fetch(bitrix_url, method='POST', deadline=60)
            if result.status_code >= 500:
                send_error(
                    'bitrix', 'Bitrix not responding when importing %s/%s' %
                    (namespace, order_id), '')
                raise Exception('Bitrix fetch failed with status code %s' %
                                result.status_code)
        except Exception as e:
            logging.exception(e)
            raise
        else:
            logging.debug(result.content)
            content = result.content.lower()
            if 'error' in content:
                logging.error('Error!')
                send_error(
                    'bitrix', 'Bitrix error when importing %s/%s' %
                    (namespace, order_id), result.content)
            else:
                number_match = re.search('\d+', content)
                if number_match:
                    number = int(number_match.group())
                    logging.debug('Setting number to %s', number)
                    order.number = int(number)
                    order.put()
示例#13
0
 def get(self):
     namespace_hit = {}
     for namespace in metadata.get_namespaces():
         namespace_manager.set_namespace(namespace)
         if config.HIT_MODULE and config.HIT_MODULE.status == STATUS_AVAILABLE:
             module = config.HIT_MODULE
             update_hit_category()
             items_str = u'\n'.join([
                 '%s: rating = %s' %
                 (item.get().title, round(item.get().rating, 3))
                 for item in module.items
             ])
             text = 'In company (%s), hit category (%s) has items: \n%s\n\n' % (
                 config.APP_NAME, module.title, items_str)
             namespace_hit[namespace] = text
     if namespace_hit:
         namespace_manager.set_namespace('')
         admins.send_error('hits', 'Hits has been changed',
                           ''.join(namespace_hit.values()))
示例#14
0
 def post(self, order_id):
     order = self.user.order_by_id(int(order_id))
     if order.status not in [NEW_ORDER, CONFIRM_ORDER]:
         self.abort(400)
     if order.status == NEW_ORDER and (order.delivery_type
                                       in [DELIVERY, PICKUP]
                                       and config.APP_KIND == AUTO_APP):
         return self.render_error(u'Необходимо сначала подтвердить заказ')
     try:
         done_order(order, self.user.namespace)
     except Exception as e:
         send_error('Close error', 'Barista error in closing order', str(e))
         return self.render_error(
             u'Непредвиденная ошибка! Повторите позднее! Не отменяйте заказ, если он уже оплачен!'
         )
     self.render_json({
         "success":
         True,
         "delivery_time":
         timestamp(order.delivery_time),
         "actual_delivery_time":
         timestamp(order.actual_delivery_time)
     })
示例#15
0
 def get(self):
     result_text = u''
     for namespace in metadata.get_namespaces():
         namespace_manager.set_namespace(namespace)
         text = u''
         for promo in Promo.query().fetch():
             if promo.status == STATUS_AVAILABLE:
                 if promo.end and datetime.utcnow() >= promo.end:
                     promo.status = STATUS_UNAVAILABLE
                     promo.put()
                     text += u'\nАкция "%s" была выключена' % promo.title
             if promo.status == STATUS_UNAVAILABLE:
                 if promo.start and promo.start <= datetime.utcnow():
                     if promo.end and datetime.utcnow() >= promo.end:
                         continue
                     promo.status = STATUS_AVAILABLE
                     promo.visible = True
                     promo.put()
                     text += u'\nАкция "%s" была включена' % promo.title
         if text:
             result_text += u'В компании %s: %s' % (namespace, text)
     if result_text:
         namespace_manager.set_namespace('')
         admins.send_error('Promos', 'Promos has been updated', result_text)
示例#16
0
 def get(self):
     now = datetime.datetime.now()
     since = now - datetime.timedelta(minutes=MINUTES_INTERVAL)
     namespace_errors = {}
     for namespace in metadata.get_namespaces():
         namespace_manager.set_namespace(namespace)
         requests = PaymentErrorsStatistics.get_requests(since)
         if requests:
             logging.info('-----------------------------')
             failure_count = sum(int(not r.success) for r in requests)
             if float(failure_count) / len(
                     requests) > AVAIL_FAILURE_PERCENT / 100.0:
                 failure_info = defaultdict(
                     Counter)  # url -> {message -> count}
                 for request in requests:
                     if not request.success:
                         failure_info[request.url][
                             request.error_message] += 1
                 error_details = []
                 for url, messages in failure_info.iteritems():
                     messages_string = "\n".join(
                         "| %s: %s" % item for item in messages.items())
                     error_details.append("%s\n%s" % (url, messages_string))
                 text = u"%s errors out of %s requests\n\n%s" % (
                     failure_count, len(requests),
                     "\n\n".join(error_details))
                 namespace_errors[namespace] = text
     mail_body = u'Errors with AlfaBank within %s minutes and with %s%% of failures:\n' % \
                 (MINUTES_INTERVAL, AVAIL_FAILURE_PERCENT)
     for namespace in namespace_errors.keys():
         mail_body += u'In namespace = %s:\n' % namespace
         mail_body += namespace_errors[namespace]
     if namespace_errors:
         logging.warning(mail_body)
         namespace_manager.set_namespace('')
         admins.send_error("server", "Payment errors", mail_body)
示例#17
0
def cancel_order(order, status, namespace, comment=None):
    success = True
    if order.has_card_payment:
        legal = Venue.get(order.venue_id).legal.get()
        return_result = alfa_bank.reverse(legal.alfa_login,
                                          legal.alfa_password,
                                          order.payment_id)
        success = str(return_result['errorCode']) == '0'
    elif order.has_paypal_payment:
        success, error = paypal.void(order.payment_id)
    if success:
        for gift_detail in order.gift_details:
            try:
                empatika_promos.cancel_activation(gift_detail.activation_id)
            except empatika_promos.EmpatikaPromosError as e:
                logging.exception(e)
                admins.send_error("payment", "Cancel activation", str(e))
                success = False
    if success:
        success_wallet_payment_reverse = False
        if order.wallet_payment > 0 and config.APP_KIND == AUTO_APP:
            try:
                empatika_wallet.reverse(order.client_id, order.key.id())
                deferred.defer(get_balance, order.client_id,
                               raise_error=True)  # just to update memcache
                success_wallet_payment_reverse = True
            except empatika_wallet.EmpatikaWalletError as e:
                logging.exception(e)
                admins.send_error("payment", "Wallet reversal failed", str(e))
                # main payment reversed -- do not abort
        for share_gift in order.shared_gift_details:
            gift = share_gift.gift.get()
            gift.recover()
        for performing in order.promo_code_performings:
            performing = performing.get()
            performing.recover()
        if order.subscription_details:
            subscription = order.subscription_details.subscription.get()
            subscription.recover(order.subscription_details.amount)
        if order.geo_push:
            geo_push = order.geo_push.get()
            geo_push.recover()
        if order.left_basket_promo:
            left_basket_promo = order.left_basket_promo.get()
            left_basket_promo.recover()

        order.status = status
        order.return_datetime = datetime.utcnow()
        order.return_comment = comment
        order.email_key_done = None
        order.email_key_cancel = None
        order.email_key_postpone = None
        order.email_key_confirm = None
        order.put()

        if order.shared_promo:
            shared_promo = order.shared_promo.get()

            if order.client_id == shared_promo.recipient.id():
                shared_promo.recipient_promo_success = False

            elif order.client_id == shared_promo.sender.id():
                shared_promo.sender_promo_success = False

            shared_promo.put()

        if status == CANCELED_BY_BARISTA_ORDER:
            client = Client.get(order.client_id)
            push_text = u"%s, заказ №%s отменен." % (client.name, order.number)
            if order.has_card_payment:
                push_text += u" Ваш платеж будет возвращен на карту в течение нескольких минут.\n"
            if success_wallet_payment_reverse:
                push_text += u" Бонусные баллы были возвращены на Ваш счет.\n"
            if comment:
                push_text += " " + comment
            OrderPush(push_text, order, namespace).send()
        elif status == CANCELED_BY_CLIENT_ORDER:
            message = u"Заказ из мобильного приложения №%s отменен клиентом" % order.key.id(
            )
            venue = Venue.get(order.venue_id)
            try:
                sms_pilot.send_sms(venue.phones, message)
            except:
                pass
            for email in venue.emails:
                if email:
                    deferred.defer(postmark.send_email, EMAIL_FROM, email,
                                   message, "<html></html>")
    return success
示例#18
0
    def post(self):
        client_id = self.request.get_range('client_id') or int(
            self.request.headers.get('Client-Id') or 0)
        client = Client.get(client_id)
        if not client:
            self.abort(400)

        delivery_type = int(self.request.get('delivery_type'))

        venue = None
        delivery_zone = None
        address = self.request.get('address')

        if delivery_type in [SELF, IN_CAFE, PICKUP]:
            venue_id = self.request.get('venue_id')
            if not venue_id or venue_id == '-1':
                venue = None
            else:
                venue = Venue.get(venue_id)
        elif delivery_type in [DELIVERY]:
            if address:
                address = json.loads(address)
                address = validate_address(address)
            venue, delivery_zone = get_venue_and_zone_by_address(address)

        logging.debug("venue: {0}, delivery zone: {1}".format(
            venue, delivery_zone))

        raw_payment_info = self.request.get('payment')
        payment_info = None
        if raw_payment_info:
            payment_info = json.loads(raw_payment_info)
            if (not payment_info.get('type_id') and payment_info.get('type_id') != 0) or \
                            payment_info.get('type_id') == -1:
                payment_info = None

        delivery_slot_id = self.request.get('delivery_slot_id')
        if delivery_slot_id == '-1':
            self.abort(400)
        if delivery_slot_id:
            delivery_slot_id = int(delivery_slot_id)
            delivery_slot = DeliverySlot.get_by_id(delivery_slot_id)
            if not delivery_slot:
                self.abort(400)
        else:
            delivery_slot = None

        delivery_time_minutes = self.request.get(
            'delivery_time')  # used for old versions todo: remove
        if delivery_time_minutes:  # used for old versions todo: remove
            send_error(
                'minutes', 'delivery_time field in check order',
                'The field is invoked in %s' %
                namespace_manager.get_namespace())
            delivery_time_minutes = int(
                delivery_time_minutes)  # used for old versions todo: remove
        delivery_time_picker = self.request.get('time_picker_value')

        delivery_time = get_delivery_time(delivery_time_picker, venue,
                                          delivery_slot, delivery_time_minutes)

        items = json.loads(self.request.get('items'))
        if self.request.get('gifts'):
            gifts = json.loads(self.request.get('gifts'))
        else:
            gifts = []
        if self.request.get('order_gifts'):
            order_gifts = json.loads(self.request.get('order_gifts'))
        else:
            order_gifts = []
        if self.request.get('cancelled_order_gifts'):
            cancelled_order_gifts = json.loads(
                self.request.get('cancelled_order_gifts'))
        else:
            cancelled_order_gifts = []

        # todo убрать через ~2 месяца - в июне
        items, gifts = fuckup_move_items_to_gifts(items, gifts)

        client.save_session(True, bool(items or gifts or order_gifts))

        module = config.BASKET_NOTIFICATION_MODULE
        if module and module.status and items:
            if client.notif_id:
                taskqueue.Queue(name='default').delete_tasks_by_name(
                    [client.notif_id])
            task = taskqueue.add(url='/task/basket_notification',
                                 method='POST',
                                 countdown=module.inactivity_duration,
                                 params={
                                     'client_id': client_id,
                                     'namespace':
                                     namespace_manager.get_namespace()
                                 })
            client.notif_id = task.name
            client.put()

        extra_fields = json.loads(
            self.request.get('extra_order_fields',
                             '{}'))  # todo: it can be checked in validation

        if config.APP_KIND == AUTO_APP:
            result = validate_order(client, items, gifts, order_gifts,
                                    cancelled_order_gifts, payment_info, venue,
                                    address, delivery_time, delivery_slot,
                                    delivery_type, delivery_zone)

        elif config.APP_KIND == RESTO_APP:
            result = resto_validate_order(client, items, venue, delivery_time,
                                          order_gifts, cancelled_order_gifts,
                                          delivery_type)
        elif config.APP_KIND == DOUBLEB_APP:
            result = doubleb_validate_order(client, venue, items, payment_info,
                                            delivery_time)
        else:
            result = {}

        logging.info('validation result = %s' % result)
        self.render_json(result)