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
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
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'], })
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
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)
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
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)
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']
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
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)
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)}