Beispiel #1
0
def payment_should_be_skipped(order_id):
    if config.SKIP_PAYMENT:
        return True

    if config.ENABLE_MAGIC_CREDIT_CARD:
        try:

            def normalize_name(name):
                return ' '.join(name.split()).lower()

            magic_credit_card = json.loads(config.MAGIC_CREDIT_CARD_JSON)
            magic_brand = magic_credit_card['brand']
            magic_country = magic_credit_card['country']
            magic_exp_month = magic_credit_card['exp_month']
            magic_exp_year = magic_credit_card['exp_year']
            magic_last4 = magic_credit_card['last4']
            magic_name = normalize_name(magic_credit_card['name'])

            user_credit_card = get_credit_card(get_order(order_id).user_id)
            return magic_brand == user_credit_card['brand'] and \
                   magic_country == user_credit_card['country'] and \
                   magic_exp_month == user_credit_card['exp_month'] and \
                   magic_exp_year == user_credit_card['exp_year'] and \
                   magic_last4 == user_credit_card['last4'] and \
                   magic_name == normalize_name(user_credit_card['name'])
        except:
            logging.exception(
                'Failed to compare user\'s credit card to MAGIC_CREDIT_CARD_JSON'
            )
            return False
    return False
Beispiel #2
0
def create_product_offers(order_id, products_list):
    order = get_order(order_id)
    products = products_list[0]

    master_product_id = products[0]['master_product_id']
    master_product = get_master_product(master_product_id)

    source = db.session.query(Source).filter_by(id=master_product.source_id).first()

    product_offer = ProductOffer(
        order_id=order_id,
        source_id=master_product.source_id,
        wine_type=order.subscription.type,
        priority=1,
        name=source.name,
        accepted=True
    )
    db.session.add(product_offer)
    db.session.flush()

    for product in products:
        create_offer_item_from_dict(product, product_offer.id)

    db.session.flush()
    populate_offer_costs(product_offer)
Beispiel #3
0
def get_user_order_data(order_id):
    order = get_order(order_id)
    tracking_url = get_order_tracking_url(order)

    user = order.user
    shipping_address = {
        'name': user.first_name or '',
        'city': order.shipping_city,
        'street': order.shipping_street1,
        'state': USA_STATES_POSTCODE[order.shipping_state_region],
        'zipcode': order.shipping_postcode,
        'email': user.email,
        'phone': user.phone,
    }

    product_offer = order.accepted_offers[0]
    products = []
    for product in product_offer.offer_items:
        products.append({
            'name': product.name,
            'price': str(product.price),
            'sku': product.sku or '',
        })

    carrier = ''
    if order.shipping_method:
        carrier = order.shipping_method.carrier.carrier

    return {
        'order': {
            'url':
            'url',
            'number':
            order.order_number,
            'month':
            MONTH[order.month - 1],
            'tracking_number':
            order.shipping_tracking_num,
            'tracking_url':
            tracking_url or '',
            'shipping_date':
            str(order.shipping_date),
            'carrier':
            carrier,
            'deeplink':
            '%s/subscriptions/?id=%s' % (config.SERVER_DEEPLINK_URL, order_id),
        },
        'billing_address': shipping_address,
        'shipping_address': shipping_address,
        'products': products,
        'total_cost': str(product_offer.total_cost),
        'product_cost': str(product_offer.product_cost),
        'salestax_cost': str(product_offer.salestax_cost),
        'shipping_cost': str(product_offer.shipping_cost),
        'source_name': product_offer.source.name,
    }
Beispiel #4
0
    def run(self, order_id):
        logging.info('running SearchAction')
        order = get_order(order_id)
        themes = get_user_themes(order.user_id)
        subscription = order.subscription
        bottle_qty = subscription.bottle_qty
        wine_types = get_wine_types(subscription.type)
        budget = subscription.budget

        address = order.user.primary_user_address
        order.shipping_name = order.user.first_name
        order.shipping_street1 = address.street1
        order.shipping_street2 = address.street2
        order.shipping_state_region = address.state_region
        order.shipping_country = address.country
        order.shipping_city = address.city
        order.shipping_postcode = address.postcode
        order.shipping_phone = order.user.phone
        order.subscription_snapshot.type = subscription.type
        order.subscription_snapshot.bottle_qty = bottle_qty
        order.subscription_snapshot.budget = budget
        db.session.flush()

        user_id = order.user.id
        user_state_region = order.user.primary_user_address.state_region

        state_postal_code = state_to_postcode(user_state_region)
        sources = get_sources_shipping_to(state_postal_code)
        if not sources:
            raise OrderException(
                'No source found that ships to User: %s in state_region: %s' %
                (user_id, user_state_region)
            )

        sources_budget = get_sources_budget(sources, budget, bottle_qty, order.shipping_postcode)
        if not sources_budget:
            raise OrderException('No available shipping or tax info')

        sent_wines = get_all_accepted_wines(user_id)

        # call search API
        products = do_search(bottle_qty, wine_types, themes, sources_budget, sent_wines)
        logging.info('got products: %s', products)

        # update DB
        delete_product_offers(order_id)
        db.session.flush()
        create_product_offers(order_id, products)

        if order.scheduled_for is None:
            subscription.last_order_searched_at = datetime.utcnow()
        else:
            subscription.last_order_searched_at = order.scheduled_for

        return NOTIFY_WINE_EXPERT_ACTION, READY_TO_PROPOSE_STATE
Beispiel #5
0
    def run(self, order_id):
        logging.info('running NotifyUserShippedAction for order: %s', order_id)
        order = get_order(order_id)
        # device_tokens = [t.token for t in order.user.device_tokens]
        # msg = 'Your order is shipped!'
        # send_push(device_tokens, msg, order_id=order_id)

        try:
            self._send_email(order.id)
        except Exception as e:
            logging.exception('Error when sending shipping email: %s', e)

        return None, USER_NOTIFIED_SHIPPED_STATE
Beispiel #6
0
def authorize_payment(order_id):
    logging.info('authorizing payment for order: %s', order_id)
    order = get_order(order_id)
    customer = get_stripe_customer(order.user.stripe_customer_id)

    offer = get_accepted_product_offer(order_id)

    charge = stripe.Charge.create(amount=int(offer.total_cost * 100),
                                  currency='usd',
                                  customer=customer.id,
                                  capture=False)

    offer.stripe_charge_id = charge.id
    db.session.commit()
Beispiel #7
0
    def run(self, order_id):
        logging.info('running CompleteAction order_id: %s', order_id)
        order = get_order(order_id)

        utcnow = datetime.utcnow()
        if order.user.primary_user_subscription.last_order_searched_at is None:
            scheduled_for = utcnow
        else:
            scheduled_for = order.user.primary_user_subscription.last_order_searched_at
            scheduled_for += relativedelta(months=1)
            if scheduled_for < utcnow:
                scheduled_for = utcnow

        create_order(order.user.id,
                     order.user.primary_user_subscription.id,
                     scheduled_for=scheduled_for)
        return None, COMPLETED_STATE
Beispiel #8
0
    def run(self, order_id):
        logging.info('running NotifyExceptionAction order_id: %s', order_id)

        try:
            expert = get_wine_expert_for_order(order_id)
            order = get_order(order_id)
            new_state = EXCEPTION_STATE_NOTIFY_MAPPING.get(
                order.state, EXCEPTION_STATE)

            subject = 'Exception in Order: %s' % order.id
            send_mail(expert.email, subject, order.exception_message)
        except Exception:
            logging.exception(
                'Exception in NotifyExceptionAction for order: %s', order_id)
            return None, EXCEPTION_TO_NOTIFY_STATE

        return None, new_state
Beispiel #9
0
    def mutate_and_get_payload(cls, root, info, **inp):
        logging.info('SaveOrder input: %s', inp)
        order_id = from_global_id_assert_type(inp['id'], 'Order')

        order = OrderModel.query.get(order_id)

        save_input_fields(inp, (
            'shipping_name',
            'shipping_street1',
            'shipping_street2',
            'shipping_city',
            'shipping_country',
            'shipping_state_region',
            'shipping_postcode',
            'shipping_phone',
            'shipping_tracking_num',
            'shipping_date',
        ), order)
        try:
            shipping_method_global_id = inp['shipping_method_id']
        except KeyError:
            pass
        else:
            order.shipping_method_id = from_global_id_assert_type(
                shipping_method_global_id, 'OrderShippingMethod')

        save_product_offers(inp, order)
        replace_offer_items(inp, order)

        db.session.commit()

        order_action = inp.get('action')
        if order_action:
            task_res = run_order.delay(order.id, action=order_action)
            try:
                # wait for the task for up to 10 seconds (some order actions are quick)
                task_res.wait(timeout=10)
            except TimeoutError:
                pass

        db.session.expire_all()
        return SaveOrder(order=get_order(order.id))
Beispiel #10
0
    def run(self, order_id):
        logging.info('running NotifyUserAction for order: %s', order_id)
        order = get_order(order_id)
        # device_tokens = [t.token for t in order.user.device_tokens]
        month = get_order_creation_month(order)
        # msg = f'Your {month} wine selections are available! Please confirm quickly to ensure availability.'
        # send_push(device_tokens, msg)
        try:
            send_template_email(
                order.user.email,
                'search_completed',
                {
                    'month': month,
                    'deeplink': config.SHIPMENTS_DEEPLINK_URL  # Goes to webui
                    # 'deeplink': config.SERVER_DEEPLINK_URL + '/subscriptions/',
                })
        except Exception as e:
            logging.exception('Error when sending search_completed mail: %s',
                              e)

        return None, PROPOSED_TO_USER_STATE
Beispiel #11
0
 def __init__(self, order_or_id):
     if isinstance(order_or_id, Order):
         self.order = order_or_id
     else:
         self.order = get_order(order_or_id)
Beispiel #12
0
    def run(self, order_id):
        logging.info('running RetrySearchAction order_id: %s', order_id)

        get_order(order_id).scheduled_for = datetime.utcnow()

        return SEARCH_ACTION, STARTED_STATE