Exemple #1
0
 def _get_reward_data(self, conn, id_coupon, coupon_type):
     reward = {}
     if coupon_type == COUPON_REWARD_TYPE.COUPON_CURRENCY:
         credit_value = db_utils.select_dict(
             conn, 'store_credit', 'id_coupon',
             where={'id_coupon': id_coupon}).values()[0]
         reward['credit'] = {
             'currency': credit_value['currency'],
             'amount': credit_value['amount'],
         }
     else:
         gift_values = db_utils.select(
             conn, 'coupon_gift', columns=('id_sale', 'quantity'),
             where={'id_coupon': id_coupon})
         if gift_values:
             reward['gifts'] = [{'item_id': gift[0], 'quantity': gift[1]}
                                for gift in gift_values]
             results = db_utils.select(
                 conn, 'coupon_give_away', where={'id_coupon': id_coupon})
             if results:
                 reward['max_selection'] = results[0]['max_selection'] or 0
         else:
             discount_value = db_utils.select_dict(
                 conn, 'coupon_discount', 'id_coupon',
                 where={'id_coupon': id_coupon}).values()[0]
             reward['discount'] = {
                 'type': COUPON_DISCOUNT_APPLIES.toReverseDict()[
                         discount_value['discount_type']],
                 'discount': discount_value['discount'],
             }
     return reward
Exemple #2
0
def delete_invoices(conn, where):
    invoices = select_dict(conn, 'invoices', 'id', where=where)
    deleted_invoice_ids = []
    for id, invoice in invoices.iteritems():
        delete(conn, 'invoice_status', where={'id_invoice': id})
        invoice_id = delete(conn, 'invoices', where={'id': id}, returning='id')
        deleted_invoice_ids.append(invoice_id)
        logging.info('invoice %s deleted for %s', invoice_id, where)
    return deleted_invoice_ids
Exemple #3
0
def _create_shipping_list(conn, id_item, orig_id_item, quantity=1):
    shipping_value = db_utils.select_dict(conn,
                                          'shipping_list',
                                          'id',
                                          where={
                                              'id_item': orig_id_item
                                          }).values()[0]

    db_utils.insert(conn,
                    'shipping_list',
                    values={
                        'id_item': id_item,
                        'id_shipment': shipping_value['id_shipment'],
                        'quantity': quantity,
                        'packing_quantity': quantity,
                        'free_shipping': shipping_value['free_shipping'],
                    })
Exemple #4
0
def get_coupon_condition_data(conn, id_coupon):
    match = []
    operation = None
    threshold = None
    cond_values = db_utils.select_dict(conn,
                                       'coupon_condition',
                                       'id',
                                       where={'id_coupon': id_coupon})
    if cond_values:
        for cond_value in cond_values.itervalues():
            operation = cond_value['operation']
            if cond_value['id_value'] and cond_value['id_type']:
                match.append({
                    'id':
                    cond_value['id_value'],
                    'id_type':
                    cond_value['id_type'],
                    'type_name':
                    COUPON_CONDITION_IDTYPE.toReverseDict()[
                        cond_value['id_type']].lower(),
                })
            if cond_value['operation'] in (
                    COUPON_CONDITION_OPERATION.SUM_ITEMS,
                    COUPON_CONDITION_OPERATION.SUM_PRICE,
            ):
                _threshold = {
                    'operation_name':
                    'items' if cond_value['operation']
                    == COUPON_CONDITION_OPERATION.SUM_ITEMS else 'price',
                    'comparison_name':
                    COUPON_CONDITION_COMPARISON.toReverseDict()[
                        cond_value['comparison']],
                    'comparison':
                    cond_value['comparison'],
                    'threshold':
                    cond_value['threshold'],
                }
                if threshold:
                    assert threshold == _threshold
                else:
                    threshold = _threshold
    return match, operation, threshold
Exemple #5
0
def _copy_fake_order_item(conn,
                          id_order,
                          orig_id_item,
                          item_update_value,
                          quantity=1):
    item_copy_value = db_utils.select_dict(conn,
                                           'order_items',
                                           'id',
                                           where={
                                               'id': orig_id_item
                                           }).values()[0]
    item_copy_value = dict(item_copy_value)
    item_copy_value.update(item_update_value)
    item_copy_value.pop('id')

    id_item = db_utils.insert(conn,
                              'order_items',
                              values=item_copy_value,
                              returning='id')[0]
    logging.info('order_item create: item id: %s, values: %s', id_item,
                 item_copy_value)
    details_value = {
        'id_order': id_order,
        'id_item': id_item,
        'quantity': quantity
    }
    db_utils.insert(conn, 'order_details', values=details_value)
    logging.info('order_details create: %s', details_value)

    db_utils.update(
        conn,
        "order_items",
        values={'modified_by_coupon': item_copy_value['modified_by_coupon']},
        where={'id': orig_id_item})

    _create_shipping_list(conn, id_item, orig_id_item, quantity=quantity)
Exemple #6
0
def get_incomes_log(conn, where):
    incomes = select_dict(conn, 'incomes_log', 'order_id', where=where)

    if not incomes:
        return []

    q = ("SELECT od.id_order as id_order, "
                "oi.id_sale as id_sale, "
                "oi.id_shop as id_shop, "
                "oi.id_variant as id_variant, "
                "oi.price as price, "
                "od.quantity as quantity "
           "FROM order_items as oi "
           "JOIN order_details as od "
             "ON od.id_item = oi.id "
          "WHERE od.id_order in %s")
    r = query(conn, q, [tuple(incomes.keys())])

    details = [dict(income) for income in r]
    for detail in details:
        id_order = detail['id_order']
        detail.update({'up_time': incomes[id_order]['up_time'],
                       'id_user': incomes[id_order]['users_id']})
    return details
Exemple #7
0
def _calc_discount_result(conn, id_coupon, coupon, id_order, chosen_gifts,
                          all_order_items, match_order_items):
    results = db_utils.select_dict(conn,
                                   'coupon_discount',
                                   'id_coupon',
                                   where={
                                       'id_coupon': id_coupon
                                   }).values()
    if results:
        discount_value = results[0]
        if discount_value[
                'discount_type'] == COUPON_DISCOUNT_APPLIES.VALUE_CHEAPEST:
            min_price_item = min_price = match_order_items[0]
            for o_item in match_order_items[1:]:
                if 0 < o_item['price'] < min_price_item['price']:
                    min_price_item = o_item
            for o_item in all_order_items:
                if o_item == min_price_item:
                    o_item['discount'] = _calc_discount(
                        o_item['price'], discount_value['discount'])
                    break

        elif discount_value[
                'discount_type'] == COUPON_DISCOUNT_APPLIES.VALUE_MATCHING:
            for o_item in all_order_items:
                if o_item in match_order_items and o_item['price'] > 0:
                    o_item['discount'] = _calc_discount(
                        o_item['price'], discount_value['discount'])

        elif discount_value[
                'discount_type'] == COUPON_DISCOUNT_APPLIES.VALUE_INVOICED:
            for o_item in all_order_items:
                o_item['discount'] = _calc_discount(o_item['price'],
                                                    discount_value['discount'])

        elif discount_value[
                'discount_type'] == COUPON_DISCOUNT_APPLIES.VALUE_SHIPPING:
            shipments = get_shipments_by_order(conn, id_order)
            for shipment in shipments:
                fee = get_shipping_fee(conn, shipment['id'])
                update_values = {
                    'shipping_fee':
                    0,
                    'handling_fee':
                    0,
                    'details':
                    ujson.dumps({
                        'free_fee': True,
                        'shipping_fee': fee['shipping_fee'] or 0,
                        'handling_fee': fee['handling_fee'] or 0,
                        'manufacturer_promo': coupon['manufacturer'],
                    })
                }
                update_shipping_fee(conn, shipment['id'], update_values)

        for o_item in all_order_items:
            if 'discount' not in o_item:
                continue
            _copy_fake_order_item(conn,
                                  id_order,
                                  o_item['item_id'], {
                                      'price': -o_item['discount'],
                                      'description': coupon['description'],
                                      'weight': 0,
                                      'barcode': '',
                                      'external_id': '',
                                      'name': '',
                                      'item_detail': '{"name": ""}',
                                      'type_name': '',
                                      'modified_by_coupon': id_coupon,
                                  },
                                  quantity=o_item['quantity'])

    else:
        gift_values = db_utils.select(conn,
                                      'coupon_gift',
                                      columns=('id_sale', 'quantity'),
                                      where={'id_coupon': id_coupon})
        chosen_gifts = get_chosen_gifts(conn, id_coupon, chosen_gifts)
        if chosen_gifts:
            for id_sale, quantity in chosen_gifts:
                _create_free_order_item(conn,
                                        id_order,
                                        id_sale,
                                        match_order_items[0]['item_id'], {
                                            'price': 0,
                                            'modified_by_coupon': id_coupon
                                        },
                                        quantity=quantity)
Exemple #8
0
def _calc_currency_credit(conn, id_coupon, coupon, id_order, id_user,
                          match_order_items):
    credit_value = db_utils.select_dict(conn,
                                        'store_credit',
                                        'id_coupon',
                                        where={
                                            'id_coupon': id_coupon
                                        }).values()[0]
    if credit_value['redeemed_in_full']:
        raise ValidationError('COUPON_ERR_REDEEMED_FULL')

    redeemed_amount = db_utils.query(
        conn,
        "select COALESCE(sum(redeemed_amount), 0) from store_credit_redeemed "
        "where id_coupon=%s and order_status in (%s, %s) ", [
            id_coupon, ORDER_STATUS_FOR_COUPON.PENDING,
            ORDER_STATUS_FOR_COUPON.PAID
        ])[0][0]
    left_amount = credit_value['amount'] - redeemed_amount
    total_redeemable_amount = 0
    match_id_items = [item['item_id'] for item in match_order_items]

    shipments = get_shipments_by_order(conn, id_order)
    for shipment in shipments:
        if left_amount <= 0:
            continue
        shipping_list = get_shipping_list(conn, shipment['id'])
        price = sum([
            o['price'] * o['quantity'] for o in shipping_list
            if o['id_item'] in match_id_items
            and o['currency'] == credit_value['currency']
        ])
        redeemed_amount = abs(
            sum([
                o['price'] * o['quantity'] for o in shipping_list if
                o['id_sale'] == 0 and o['currency'] == credit_value['currency']
            ]))

        taxes = get_apply_before_coupons_taxes(conn, id_user,
                                               shipment['id_shop'],
                                               shipping_list[0]['id_sale'])
        price_with_tax = price + sum(
            [(price + redeemed_amount) * float(tax['rate']) / 100.0
             for tax in taxes])
        redeemable_amount = min(price_with_tax, left_amount)

        fake_item = {
            'id_sale':
            0,
            'id_variant':
            0,
            'id_brand':
            match_order_items[0]['brand_id'],
            'id_shop':
            match_order_items[0]['shop_id'],
            'name':
            '',
            'price':
            -min(price, left_amount),
            'currency':
            credit_value['currency'],
            'description':
            coupon['description'],
            'weight':
            0,
            'weight_unit':
            match_order_items[0]['weight_unit'],
            'barcode':
            '',
            'external_id':
            '',
            'item_detail':
            ujson.dumps({
                'name': '',
                'redeemable_credits': redeemable_amount,
            }),
            'type_name':
            '',
            'modified_by_coupon':
            id_coupon,
        }
        _create_fake_order_item(conn, id_order, match_id_items[0], fake_item)
        left_amount -= redeemable_amount
        total_redeemable_amount += redeemable_amount

    return to_round(total_redeemable_amount), credit_value['currency']
Exemple #9
0
def check_coupon_with_password(conn, password, users_id, id_order, user_info):
    coupons = db_utils.select_dict(conn,
                                   'coupons',
                                   'id',
                                   where={
                                       'password': password,
                                       'valid': True
                                   }).values()
    if len(coupons) == 0:
        raise ValidationError('COUPON_ERR_INVALID_PASSWORD')
    coupon = coupons[0]

    id_users = get_coupon_user_data(conn, coupon['id'])
    if id_users and int(users_id) not in id_users:
        raise ValidationError('COUPON_ERR_INVALID_COUPON')

    if coupon['expiration_time'] and \
            coupon['expiration_time'] < datetime.now():
        raise ValidationError('COUPON_ERR_INVALID_COUPON')

    results = db_utils.query(
        conn, "select id from coupon_redeemed "
        "where id_order=%s and id_coupon=%s and order_status in (%s,%s) "
        "union "
        "select id from store_credit_redeemed "
        "where id_order=%s and id_coupon=%s and order_status in (%s,%s) ", [
            id_order, coupon['id'], ORDER_STATUS_FOR_COUPON.PENDING,
            ORDER_STATUS_FOR_COUPON.PAID
        ] * 2)
    if len(results) > 0:
        raise ValidationError('COUPON_ERR_APPLIED_COUPON')

    if not coupon['stackable']:
        results = db_utils.query(
            conn, "select id from coupon_redeemed "
            "where id_order=%s and order_status in (%s, %s) "
            "union "
            "select id from store_credit_redeemed "
            "where id_order=%s and order_status in (%s, %s) ", [
                id_order, ORDER_STATUS_FOR_COUPON.PENDING,
                ORDER_STATUS_FOR_COUPON.PAID
            ] * 2)
        if len(results) > 0:
            raise ValidationError('COUPON_ERR_NOT_STACKABLE_COUPON')

    if coupon['max_redeemable']:
        if _get_redeemed_times(conn, coupon['id']) >= coupon['max_redeemable']:
            raise ValidationError('COUPON_ERR_USED_COUPON')

    if not coupon['redeemable_always']:
        if _once_coupon_limited(
                conn,
                id_coupon,
                users_id,
                user_info['fo_user_phone'],
                user_info['fo_user_addr'],
                user_info['user_agent'],
        ):
            raise ValidationError('COUPON_ERR_USED_COUPON')

    return coupon
Exemple #10
0
    def shipment_content(self, conn, id_shipment):
        shipping_list = get_shipping_list(conn, id_shipment)

        normal_items = []
        discount_lines = {}

        def _item_key(item):
            return ujson.dumps({
                'id_sale': item['id_sale'],
                "id_variant": item["id_variant"],
                "id_price_type": item["id_price_type"],
                "id_type": item["id_type"],
            })

        for shipping in shipping_list:
            promo = shipping["modified_by_coupon"] is not None
            promo_type = None
            manufacturer_promo = False
            if promo:
                coupons = db_utils.select_dict(
                    conn,
                    'coupons',
                    'id',
                    where={
                        'id': shipping['modified_by_coupon']
                    }).values()
                if len(coupons) > 0:
                    promo_type = COUPON_REWARD_TYPE.toReverseDict()[
                        coupons[0]['coupon_type']]
                    manufacturer_promo = coupons[0]['manufacturer']
            detail = ujson.loads(shipping['item_detail'])
            item = {
                "id_item": shipping["id_item"],
                "id_sale": shipping["id_sale"],
                "id_variant": shipping["id_variant"],
                "quantity": shipping["quantity"],
                "id_price_type": shipping["id_price_type"],
                "id_type": shipping["id_type"],
                "name": shipping["name"] or '',
                "type_name": shipping["type_name"] or '',
                "external_id": shipping["external_id"] or '',
                'promo': promo,
                'promo_type': promo_type,
                'manufacturer_promo': manufacturer_promo,
                'price': shipping['price'],
                'desc': shipping["description"],
                'redeemable_credits': detail.get('redeemable_credits'),
            }
            if shipping['id_sale'] and shipping['price'] < 0:
                if _item_key(item) not in discount_lines:
                    discount_lines[_item_key(item)] = []
                discount_lines[_item_key(item)].append(item)
            else:
                normal_items.append(item)

        content = []
        for item in normal_items:
            content.append(item)
            if _item_key(item) in discount_lines:
                content += discount_lines.pop(_item_key(item))
        for items in discount_lines.values():
            content += items
        return ujson.dumps(content)
Exemple #11
0
    def _on_get(self, req, resp, conn, **kwargs):
        id_brand = req.get_param('id_brand')
        if not id_brand:
            raise ValidationError('COUPON_ERR_INVALID_ID_BRAND')

        params = cgi.parse_qs(req.query_string)
        id_shops = params.get('id_shop') or []

        id_item = req.get_param('id_item')
        id_promotion_group = req.get_param('promotion_group')
        id_product_brand = req.get_param('item_brand')

        query = """
            select id from coupons
            where id_brand=%s and valid
              and (expiration_time is null or expiration_time >= now())
            order by creation_time
        """
        id_coupons = db_utils.query(conn, query, [id_brand])
        id_coupons = [v[0] for v in id_coupons]
        if id_shops:
            id_coupons = self._filter_by_shops(conn, id_brand, id_shops, id_coupons)
        if id_item:
            id_coupons = self._filter_by_id(conn, COUPON_CONDITION_IDTYPE.SALE,
                                            id_item, id_coupons)
        if id_product_brand:
            id_coupons = self._filter_by_id(conn, COUPON_CONDITION_IDTYPE.BRAND,
                                            id_product_brand, id_coupons)
        if id_promotion_group:
            id_coupons = self._filter_by_id(conn, COUPON_CONDITION_IDTYPE.GROUP,
                                            id_promotion_group, id_coupons)

        data = []
        for id_coupon in id_coupons:
            c_values = db_utils.select_dict(
                conn, 'coupons', 'id', where={'id': id_coupon}).values()[0]
            coupon_data = {
                'id': c_values['id'],
                'issuer': c_values['id_brand'],
                'stackable': 'true' if c_values['stackable'] else 'false',
                'author': c_values['id_bo_user'],
                'coupon_type': COUPON_REWARD_TYPE.toReverseDict().get(
                               c_values['coupon_type']),
                'desc': c_values['description'],
                'password': c_values['password'],
                'effective_time': str(c_values['effective_time'])[:19],
                'expiration_time': str(c_values['expiration_time'] or '')[:19],
                'redeemable_always':
                    'true' if c_values['redeemable_always'] else 'false',
                'max_redeemable': c_values['max_redeemable'] or '',
            }

            coupon_data.update({
                'id_users': get_coupon_user_data(conn, id_coupon),
            })
            coupon_data.update({
                'shops': [self._get_shop_details(id_shop)
                    for id_shop in get_coupon_shop_data(conn, id_coupon)]
            })
            conds, operation, threshold = get_coupon_condition_data(conn, id_coupon)
            require = {}
            if operation:
                require['operation'] = \
                        COUPON_CONDITION_OPERATION.toReverseDict()[operation]
            if threshold:
                require.update(threshold)
            if conds:
                require['match'] = conds
            if require:
                require.update({
                    'order': 'first' if c_values['first_order_only'] else 'any',
                })
                coupon_data['require'] = require

            reward = self._get_reward_data(conn, id_coupon,
                                         c_values['coupon_type'])
            coupon_data['reward'] = reward

            data.append(coupon_data)
        return {'coupons': to_unicode(data)}