def checkout(version, uname, param): print param # mice 为黄牛手机号标志,mice==1不可以下单 2015-08-22 db_user = db.app_user.find_one( {'uname': uname['uname']}, #, 'mice':{'$ne':1}}, { 'coupon': 1, 'address': 1, 'credit': 1, 'app_id': 1, 'mice': 1 }) if db_user == None: # 不应该发生 return {'ret': -9, 'msg': '未找到用户信息'} # 检查mice, 排除白名单 if db_user.get( 'mice') == 1 and uname['uname'] not in app_helper.WHITE_LIST: print 'mice !!!' return {'ret': -9, 'msg': '未找到用户信息'} app_id = db_user['app_id'] # 修改为付款的过期订单 r = db.order_app.update_many( { #'uname' : {'$in':uname.values()}, 'status': 'DUE', 'deadline': { '$lt': int(time.time()) } }, {'$set': { 'status': 'TIMEOUT' }}) # 查找shop db_shop = db.base_shop.find_one({'_id': ObjectId(param['shop_id'])}) if db_shop == None: return {'ret': -6, 'msg': 'shop_id错误'} # 查询收货地址 address = None for i in db_user['address']: if i[0] == param['addr_id']: address = list(i) break if address == None: return {'ret': -7, 'msg': 'addr_id错误'} # 获得 收货地址 坐标 if len(address) > 5: # 使用已有的gps地址 loc = address[5] else: ret, loc = lbs.addr_to_loc(address[3].encode('utf-8')) if ret < 0: # 重试一次 ret, loc = lbs.addr_to_loc(address[3].encode('utf-8')) if ret < 0: loc = {'lat': 0, 'lng': 0} print loc # 多边形检查 poly_shop = lbs.check_in_poly((loc['lat'], loc['lng']), db_shop.get('poly_xy', [])) if poly_shop == None: return {'ret': -6, 'msg': 'shop_id错误'} ########################################################################### # 用收货电话检查黄牛 2015-08-22 db_recv = db.recv_tel.find_one({'tel': address[2]}) if db_recv: one_more = 0 if uname['uname'] not in db_recv['unames']: # 补充疑似账号 db.recv_tel.update_one({'tel': address[2]}, {'$push': { 'unames': uname['uname'] }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现 mice mice = 1 for b in db_recv['unames']: if b in app_helper.WHITE_LIST: # 过滤白名单相关号码 mice = 0 break db.app_user.update_many({'uname': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) db.app_user.update_many({'openid': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) if one_more == 1: db.app_user.update_one({'uname': uname['uname']}, {'$set': { 'mice': mice }}) if mice == 1: print '!!! mice:', address[ 2] #, uname['uname'], db_recv['unames'] return {'ret': -9, 'msg': '黄牛下单1'} else: db.recv_tel.insert_one({'tel': address[2], 'unames': [uname['uname']]}) #print 'insert', address[2] # 用收货地址检查黄牛, 不准确,不能标注 2015-08-23 db_recv = db.recv_addr.find_one({'addr': address[3]}) if db_recv: one_more = 0 if uname['uname'] not in db_recv['unames']: db.recv_addr.update_one({'addr': address[3]}, {'$push': { 'unames': uname['uname'] }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现疑似mice,不标注,因为不确定 print '!!! maybe a mice:', address[3].encode( 'utf-8') #, uname['uname'], db_recv['unames'] else: db.recv_addr.insert_one({ 'addr': address[3], 'unames': [uname['uname']] }) #print 'insert', address[2] # 用app_id检查黄牛 appid_count = db.app_user.find({'app_id': app_id}, {'_id': 1}).count() if appid_count > 10 and app_id.strip( ) != '': # app_id 可能为空,新绑定的用户 # 改为10,2015-10-12 # 发现 mice db_mice = db.app_user.find({'app_id': app_id}, {'uname': 1}) mice = [] for m in db_mice: if m['uname'] in app_helper.WHITE_LIST: # 过滤白名单 mice = [] break else: mice.append(m['uname']) db.app_user.update_many({'uname': { '$in': mice }}, {'$set': { 'mice': 1 }}) if mice != []: print '!!! mice by app_id: ', mice return {'ret': -9, 'msg': '黄牛下单1'} # 查黄牛-结束 ########################################################################### # 查找优惠券 # 未查到,则不使用优惠券 coupon = None for i in db_user['coupon']: if i[0] == param['coupon_id']: coupon = list(i) break # 转换cart数据为json,应该有异常捕获 !!! #print param['cart'] cart = json.loads(param['cart']) #print cart if len(cart) == 0: return {'ret': -5, 'msg': '购物车无数据'} if version == 'v2': # v3 不在这生成订单号 if param['order_id'] == '': #cc = 1 #while cc!=None: # # 取得sku计数, 不与线下order共用 # db_sa = db.user.find_one_and_update( # {'uname' : 'settings'}, # {'$inc' : {'app_count' : 1}}, # {'app_count' : 1} # ) # order_id = 'n%06d%s' % (db_sa['app_count'], setting.order_fuffix) # # 防止订单号重复 # cc = db.order_app.find_one({'order_id' : order_id},{'_id':1}) order_id = app_helper.get_new_order_id(version) print 'new order_id', order_id else: order_id = param['order_id'] cc = db.order_app.find_one( { #'uname' : {'$in':uname.values()}, # 防止app的bug,重复order_id 'order_id': order_id, }, { 'status': 1, }) if cc != None and cc['status'] != 'DUE': # 检查订单状态,只有due才可以checkout print "BUG! order_id status" return {'ret': -99, 'msg': '订单状态错误'} # 订单状态:DUE, PAID, ONROAD, COMPLETED, CANCELED, FINISH # 默认运费 5元,免邮门槛 29元 order = { 'status': 'DUE', 'uname': uname['uname'], 'shop': db_shop['_id'], 'user': uname['uname'], 'order_id': order_id if version == 'v2' else '', 'order_source': app_helper.get_devive_type(param['app_id']), 'address': address, # 收货地址 'coupon': coupon, # 使用的优惠券 'cart': [], 'cost': '0.00', # 成本合计,参考 'total': '0.00', # 价格小计,加项 'coupon_disc': '0.00', # 优惠券抵扣,减项 'first_disc': '0.00', # 首单立减, 减项 'delivery_fee': '0.00', # 运费,加项 'due': '0.00', # 应付总金额 2015-11-24 'openid': uname['openid'], 'app_uname': uname['uname'], 'uname_id': db_user['_id'], 'type': 'HOUR', # 订单类型, 2015-11-19 # for processor 'next_status': '', 'lock': 0, 'man': 0, 'retry': 0, 'comment': '', 'b_time': int(time.time()), 'e_time': int(time.time()), 'deadline': int(time.time() + 60 * 15), 'poly_shop': 1 if poly_shop else 0, # 是否匹配到门店 2015-10-18 'credit_total': '0.00', # 余额支付金额 2015-11-24 'wxpay_total': '0.00', # 微信支付金额 'alipay_total': '0.00', # 支付宝支付金额 'use_credit': '0.00', # 部分支付时,余额支付金额 'due3': '0.00', # 第3方应付金额 use_credit + due3 = due } # 统计旧订单数,为0则是首单 2015-09-29 old_order_num = db.order_app.find( { 'user': { '$in': uname.values() }, 'status': { '$nin': ['DUE', 'TIMEOUT', 'CANCEL'] } }, { '_id': 1 }).count() # item = { # “product_id” : “k000011”, # “num” : “5”, # } # 应该只有 k-prod cart_to_return = [] cart_to_return_b3 = [] cate_001 = 0 b3_sku = 0 all_sku = 0 num_change = 0 buy_limit = 0 only_one = 0 for item in cart: is_b3 = False # sku db_sku = db.sku_store.find_one({'product_id': item['product_id']}, { 'app_title': 1, 'is_onsale': 1, 'special_price': 1, 'ref_price': 1, 'maximun': 1, 'list_in_app': 1, }) if db_sku == None: # 应该不会发生 print 'Error: db_sku==None' continue all_sku += 1 if db_sku['list_in_app'] == -3: # B3 整箱预售 # 不启动B3 2015-10-27 r = db.inventory.find_one( # 线上销售要检查库存 { 'product_id' : item['product_id'], 'list_in_app' : {'$ne' : 0}, 'shop' : ObjectId(setting.B3_shop), }, { 'cost_price' : 1, 'ref_prod_id' : 1, 'price' : 1, 'sku' : 1, 'num' : 1, 'category' : 1, 'first_order' : 1 } ) b3_sku += 1 is_b3 = True # 标记是B3商品, v3 elif poly_shop: # 门店库存 r = db.inventory.find_one( # 线上销售要检查库存 { 'product_id' : item['product_id'], 'list_in_app' : {'$ne' : 0}, 'shop' : db_shop['_id'], }, { 'cost_price':1, 'ref_prod_id':1, 'price':1, 'sku':1, 'num':1, 'category':1, 'first_order':1 } ) else: # 不在送货范围 r = None if r: # 如果库存数据中没此sku,会忽略掉,此情况应该不会发生 new_num = int(item['num']) new_num = new_num if new_num <= r['num'] else r['num'] new_num = max(0, new_num) # 发现过小于零的情况,微信 # 检查是不是 001 (水果) 分类 if r['category'] == '001': cate_001 += 1 # 检查是否限购 if db_sku['maximun'] > 0: ''' # 每日限购,生成当天的时间tick tday = app_helper.time_str(format=1) begin_d = '%s 00:00:00' % tday end_d = '%s 23:59:59' % tday begin_t = int(time.mktime(time.strptime(begin_d,"%Y-%m-%d %H:%M:%S"))) end_t = int(time.mktime(time.strptime(end_d,"%Y-%m-%d %H:%M:%S"))) print begin_d, end_d, begin_t, end_t # 检查时间段内购买记录 c = db.order_app.find({ 'uname' : {'$in':uname.values()}, 'order_id' : {'$ne':order_id}, 'status' : {'$ne':'TIMEOUT'}, 'cart.product_id' : item['product_id'], '$and' : [{'b_time' : {'$gt' : begin_t}}, {'b_time' : {'$lt' : end_t}}], }, {'_id':1}).count() print 'findings: ',c if c>0: # 限购商品只允许购买1次 new_num=0 buy_limit += 1 else: new_num=min(new_num, db_sku['maximun']) print 'limit : ',new_num ''' # 每单限购 if new_num > db_sku['maximun']: new_num = db_sku['maximun'] print 'limit : ', new_num # 首单可见商品,非首单用户 2015-09-30 if r.has_key('first_order' ) and r['first_order'] == 1 and old_order_num > 0: # 非首单用户,不让购买,还是有人能买到,靠! new_num = 0 # v3 检查是否是互斥商品 if version == 'v3' and item['product_id'] in app_helper.only_one: if only_one > 0: # 已有互斥商品,此商品清零 new_num = 0 else: only_one += 1 # v3 检查是否买X送Y if version == 'v3' and item[ 'product_id'] in app_helper.buy_X_give_Y.keys(): numX = app_helper.buy_X_give_Y[item['product_id']][0] numY = app_helper.buy_X_give_Y[item['product_id']][1] #new_num = int(item['num']) new_num_give = int(new_num / numX) * numY new_num = new_num if new_num + new_num_give <= r[ 'num'] else int(r['num'] / (numX + numY)) * numX new_num = max(0, new_num) # 预防小于零的情况 new_num_give = int(new_num / numX) * numY # 更新赠品数量 new_item = { 'product_id': item['product_id'], 'num': item['num'], 'num2': new_num, 'price': r['price'], 'title': db_sku['app_title'], } # v3 买X送Y数量 if version == 'v3': if item['product_id'] in app_helper.buy_X_give_Y.keys(): new_item['numyy'] = new_num_give else: new_item['numyy'] = 0 if int(new_num) != int(item['num']): num_change += 1 # 是否有优惠价格 if db_sku['is_onsale']==1 and \ float(db_sku['special_price'])<float(r['price']): # 优惠价格比门店价格低 new_item['price'] = db_sku['special_price'] # 计算总价 item_price = round(new_num * float(new_item['price']), 2) new_item['price'] = '%.2f' % item_price if version == 'v3' and is_b3: cart_to_return_b3.append(new_item) else: cart_to_return.append(new_item) # 返回到app的cart不包含cost cost_price = r['cost_price'] #if item[0][0]=='w': # w-prod 信息都用 u-prod的替换 # new_item['product_id'] = r['ref_prod_id'] # new_item['w_id'] = item[0] # # 查询成本, 从对应u-prod当前成本 # r2 = db.inventory.find_one({ # u-prod # 'shop' : db_shop['shop'], # 'product_id' : r['ref_prod_id'], # }, {'cost_price':1}) # cost_price = r2['cost_price'] # 计算成本 item_cost = round(new_num * float(cost_price), 2) new_item['cost'] = '%.2f' % item_cost # 加入cart order['cart'].append(new_item) # 累计售价和成本 order['total'] = '%.2f' % (float(order['total']) + item_price) order['cost'] = '%.2f' % (float(order['cost']) + item_cost) else: # 店内未找到库存, !!!应该不会发生 new_item = { 'product_id': item['product_id'], 'num': item['num'], 'num2': 0, 'price': '0.00', 'cost': '0.00', 'title': db_sku['app_title'], } cart_to_return.append(new_item) # 返回到app的cart不包含cost order['cart'].append(new_item) # 记录判断数量变化 if int(new_item['num2']) != int(item['num']): num_change += 1 tt = float(order['total']) if tt > 0: # 免邮门槛 if str(order['shop']) in app_helper.delivery_by_shop.keys(): delivery_fee = app_helper.delivery_by_shop[str( order['shop'])]['delivery_fee'] free_delivery = app_helper.delivery_by_shop[str( order['shop'])]['free_delivery'] else: delivery_fee = app_helper.delivery_fee free_delivery = app_helper.free_delivery #if tt<29: # 免邮门槛 29 if tt < free_delivery: # 免邮门槛 order['delivery_fee'] = '%.2f' % delivery_fee # 运费5元 # 首单立减 first_promote元, 商品总额大于 first_promote_threshold元 if cate_001 > 0 and old_order_num == 0: # 符合首单条件,且有一个水果商品 print '首单' if str(db_shop['_id']) in app_helper.first_promote2_shop and \ (tt+float(order['delivery_fee']))>=app_helper.first_promote2_threshold: # 站点落在 指定站点范围内,使用首单立减2 print '首单立减 - 指定站点' order['first_disc'] = '%.2f' % app_helper.first_promote2 elif (tt + float(order['delivery_fee']) ) >= app_helper.first_promote_threshold: # 其他站点使用首单立减1 print '首单立减' order['first_disc'] = '%.2f' % app_helper.first_promote # 优惠券, 检查有效期, 优惠券门槛为10元 if float(order['first_disc'])==0.0 and coupon!=None and \ coupon[3]==1 and app_helper.time_str(format=1)<=coupon[1]: print '检查抵用券' if len(coupon) > 5 and coupon[5] == 'apple' and cate_001 < 1: # 水果券,但没有水果 2015-09-29 print '水果券没水果' order['coupon'] = None elif len(coupon) > 5 and coupon[5] == 'b3' and b3_sku < 1: # 整箱券,但没有整箱 2015-10-18 print '整箱券没整箱' order['coupon'] = None else: if len(coupon) > 4: # (id, 有效期, 金额, 是否已用, 门槛) 2015-09-27 # 有门槛信息,使用优惠券门槛信息 if (tt + float(order['delivery_fee'])) < coupon[4]: order['coupon'] = None else: order['coupon_disc'] = coupon[2] else: # 使用默认条件 if float(coupon[2]) == 6.0 and ( tt + float(order['delivery_fee'])) < 29.9: order['coupon'] = None elif float(coupon[2]) == 9.0 and ( tt + float(order['delivery_fee'])) < 39.9: order['coupon'] = None elif (tt + float(order['delivery_fee'])) < 14.9: order['coupon'] = None else: order['coupon_disc'] = coupon[2] else: order['coupon'] = None # 计算应付:价格合计 - 优惠券 - 首单立减 + 运费 print(tt + float(order['delivery_fee']) - float(order['coupon_disc']) - float(order['first_disc'])) print tt, float(order['delivery_fee']), float( order['coupon_disc']), float(order['first_disc']) order['due'] = '%.2f' % (tt + float(order['delivery_fee']) - float( order['coupon_disc']) - float(order['first_disc'])) # 不能是负的, 要付一点 if float(order['due']) <= 0: order['due'] = '0.10' # 是否使用余额(部分)支付, 2015-11-19 if param.has_key('use_credit') and param['use_credit'] == '1': # 使用余额 my_due = float(order['due']) my_credit = db_user.get('credit', 0.0) if my_credit > my_due: order['due3'] = '0.00' order['use_credit'] = '%.2f' % my_due else: order['due3'] = '%.2f' % (my_due - my_credit) order['use_credit'] = '%.2f' % my_credit else: order['use_credit'] = '0.00' order['due3'] = order['due'] # 准备可用的优惠券 2015-09-11 coupon_list = [] for i in db_user['coupon']: if app_helper.time_str(format=1) > i[1]: # 过期抵用券 continue elif i[3] != 1: continue # 检查优惠券条件 b3_sku if tt > 0 and float(order['first_disc']) == 0.0: if len(i) > 5 and i[5] == 'apple' and cate_001 < 1: # 水果券没水果 continue if len(i) > 5 and i[5] == 'b3' and b3_sku < 1: # 整箱券没整箱 2015-10-18 continue if len(i) > 4: # 带门槛优惠券 if (tt + float(order['delivery_fee'])) < i[4]: continue else: # 过滤不符合条件的优惠券 if float(i[2]) == 6.0 and ( tt + float(order['delivery_fee'])) < 29.9: continue elif float(i[2]) == 9.0 and ( tt + float(order['delivery_fee'])) < 39.9: continue elif (tt + float(order['delivery_fee'])) < 14.9: continue coupon_list.append({ 'id': i[0], 'valid': i[1], 'cash': i[2], 'status': 'unused', 'msg1': '条件1', 'msg2': '条件2', }) coupon_list = quick(coupon_list) # 如果没有,则insert #db.order_app.replace_one({'order_id':order_id}, order, upsert=True) if version == 'v2': db.order_app.update_one({'order_id': order_id}, { '$set': order, '$push': { 'history': (app_helper.time_str(), uname['uname'], '提交结算') } }, upsert=True) elif version == 'v3': db.app_user.update_one( {'uname': uname['uname']}, {'$set': { 'cart_order.%s' % param['session']: order }}) # 提示信息 #print all_sku, b3_sku if poly_shop == False: msg_alert = True if b3_sku > 0: if all_sku > b3_sku: #message = '很抱歉,普通商品无法配送到当前地址,商品已更新' #,整箱预售商品可正常购买' msg_alert = False message = '' else: # 只有 b3 商品时不提醒 msg_alert = False message = '' else: message = '很抱歉,收货地址不在配送范围内,购物车商品已清空' else: if num_change > 0: msg_alert = True message = '库存不足,已更新商品数量,请查看' elif buy_limit > 0: msg_alert = True message = '部分商品限购,已更新商品数量,请查看' else: msg_alert = False message = '' if version == 'v2': ret_json = { # 返回结果,实际有库存的结果, 'ret': 0, 'data': { 'order_id': order['order_id'], 'shop_id': str(order['shop']), 'shop': db_shop['name'], # 可能会变,如果地址与门店不匹配的时候 'addr_id': address[0], 'cart_num': len(order['cart']), 'cart': cart_to_return, 'total': order['total'], 'coupon_list': coupon_list, # 可用的优惠券 'coupon': coupon[0] if order['coupon'] else '', 'coupon_disc': order['coupon_disc'], 'first_disc': order['first_disc'], 'delivery_fee': order['delivery_fee'], 'due': order['due'], 'credit': '%.2f' % db_user.get('credit', 0.0), 'alert': msg_alert, 'message': message, } } elif version == 'v3': hh = time.localtime().tm_hour if hh >= 9 and hh < 20: alert_title = False cart_title = '' else: alert_title = True if hh >= 20 and hh <= 23: cart_title = '目前是掌柜打烊时间,预计明日9点送出' else: cart_title = '目前是掌柜打烊时间,预计今日9点送出' if b3_sku > 0: if hh < 16: # 明天 tomorrow_tick = int(time.time()) + 3600 * 24 tomorrow = time.strftime("%m月%d日", time.localtime(tomorrow_tick)) cart_title_b3 = '以下预售商品,预计明天%s送达' % tomorrow else: # 后天 the_day_after_tick = int(time.time()) + 3600 * 24 * 2 the_day_after = time.strftime( "%m月%d日", time.localtime(the_day_after_tick)) cart_title_b3 = '以下预售商品,预计后天%s送达' % the_day_after else: cart_title_b3 = '' ret_json = { # 返回结果,实际有库存的结果, 'ret': 0, 'data': { 'shop_id': str(order['shop']), 'shop': db_shop['name'], # 可能会变,如果地址与门店不匹配的时候 'addr_id': address[0], 'cart_num': len(order['cart']), 'cart': cart_to_return, 'cart_b3': cart_to_return_b3, 'total': order['total'], 'coupon_list': coupon_list, # 可用的优惠券 'coupon': coupon[0] if order['coupon'] else '', 'coupon_disc': order['coupon_disc'], 'first_disc': order['first_disc'], 'delivery_fee': order['delivery_fee'], 'due': order['due3'], # 返回的事第3方需支付的金额 2015-11-24 'use_credit': order['use_credit'], # 使用余额的金额 2015-11-19 'credit': '%.2f' % db_user.get('credit', 0.0), 'alert': msg_alert, 'message': message, 'alert_title': alert_title, 'cart_title': cart_title, 'alert_title_b3': True, 'cart_title_b3': cart_title_b3, } } print ret_json return ret_json
def POST(self): web.header('Content-Type', 'application/json') param = web.input(openid='', session_id='', type='', data='') if param.type == '': return json.dumps({'ret': -2, 'msg': '参数错误'}) if param.type not in ['GPS', 'NAME']: return json.dumps({'ret': -3, 'msg': 'type参数错误'}) if param.openid == '' and param.session_id == '': return json.dumps({'ret': -2, 'msg': '参数错误1'}) # 同时支持openid和session_id if param.openid != '': uname = app_helper.check_openid(param.openid) else: uname = app_helper.wx_logged(param.session_id) if uname: # 准备用户坐标 if param.type == 'NAME': ret, loc = lbs.addr_to_loc(param['data'].encode('utf-8')) print ret, loc if ret < 0: # 重试一次,网络可能会失败 ret, loc = lbs.addr_to_loc(param['data'].encode('utf-8')) print ret, loc if ret < 0: loc = {'lat': 0, 'lng': 0} else: loc0 = param.data.split(',') # 31.20474193,121.620708272 loc = {'lat': float(loc0[0]), 'lng': float(loc0[1])} # 找最近距离的店 min_d = 999999 min_shop = None poly_shop = None # 多边形匹配 db_shop = db.base_shop.find( {'type': { '$in': ['chain', 'store', 'dark'] }}) for s in db_shop: if s.get('app_shop', 1) == 0: # 忽略不支持线上销售的店 continue #d=lbs.geo_distance(s['loc']['lat'],s['loc']['lng'],loc['lat'],loc['lng']) #print 'd = ', d, min_d #if d<s.get('radius', 2) and d<min_d: # 默认半径2公里 # min_d=d # min_shop=(s['_id'],s['name'],s['address']) # 多边形检查 poly = s.get('poly_xy', []) if len(poly) == 0: # 没有多边形数据 print "缺少多边形数据!" continue if lbs.wn_PnPoly((loc['lat'], loc['lng']), poly) != 0: print 'bingo! poly_shop' poly_shop = (s['_id'], s['name'], s['address']) break if poly_shop == None and min_shop == None: print '不在配送范围内' return json.dumps({'ret': -6, 'msg': '不在配送范围内'}) if poly_shop == None: # 返回最近shop print 'choose:', min_shop[1].encode('utf-8') return json.dumps({ 'ret': 0, 'data': { 'shop_id': str(min_shop[0]), 'shop_name': min_shop[1], 'address': min_shop[2], } }) else: # 返回多边形匹配shop print 'choose:', poly_shop[1].encode('utf-8') return json.dumps({ 'ret': 0, 'data': { 'shop_id': str(poly_shop[0]), 'shop_name': poly_shop[1], 'address': poly_shop[2], } }) else: return json.dumps({'ret': -4, 'msg': '无效的openid'})
def POST(self): if helper.logged(helper.PRIV_USER, 'PLAT_BASE_SHOP'): render = helper.create_render() user_data = web.input(shop_name='', shortname='', abstract='', available='1', address='', people='1', type='', worker=0, note='', app_shop='0', radius='2', poly='') if user_data.shop_name == '': return render.info('店名不能为空!') if user_data.type == '': return render.info('门店类型不能为空!') # 取得lbs坐标 ret, loc0 = lbs.addr_to_loc(user_data['address'].encode('utf-8')) if ret < 0: loc0 = {'lat': 0, 'lng': 0} # 取得多边形坐标 #poly=user_data['poly'].encode('utf-8').split(',') # 地址信息 #poly_xy=[] #if len(poly)>1: # for i in poly: # ret, loc = lbs.addr_to_loc(i) # if ret<0: # loc = (0,0) # poly_xy.append((loc['lat'],loc['lng'])) # poly_xy.append(poly_xy[0]) poly = user_data['poly'].encode('utf-8').split(';') # 已经是百度坐标 poly_xy = [] if len(poly) > 1: for i in poly: poly_xy.append(eval(i)) poly_xy.append(poly_xy[0]) db.base_shop.insert_one({ 'name': user_data['shop_name'], 'shortname': user_data['shortname'], 'abstract': user_data['abstract'], 'address': user_data['address'], 'loc': loc0, 'people': user_data['people'], 'type': user_data['type'], 'available': int(user_data['available']), 'worker': int(user_data['worker']), 'image': user_data['image'].split(','), 'note': user_data['note'], 'refer': 0, 'app_shop': int(user_data['app_shop']), 'radius': int(user_data['radius']), 'poly': user_data['poly'], 'poly_xy': poly_xy, 'history': [(helper.time_str(), helper.get_session_uname(), '新建')], # 纪录操作历史 }) db.base_image.update_many( {'image': { '$in': user_data['image'].split(',') }}, {'$inc': { 'refer': 1 }}) return render.info('成功保存!', '/plat/base_shop') else: raise web.seeother('/')
def POST(self, version='v2'): web.header('Content-Type', 'application/json') if version not in ('v2','v3'): return json.dumps({'ret' : -999, 'msg' : '版本错误!'}) print 'version=',version param = web.input(app_id='',session='',name='',tel='',addr='',title='',detail='',city='',loc='',sign='') if '' in (param.app_id, param.session, param.name, param.tel, param.addr, param.sign): return json.dumps({'ret' : -2, 'msg' : '参数错误'}) # v3 参数检查 if version=='v3' and '' in (param.title, param.detail, param.city, param.loc): return json.dumps({'ret' : -2, 'msg' : '参数错误'}) uname = app_helper.app_logged(param.session) # 检查session登录 if uname: #验证签名 if version=='v2': md5_str = app_helper.generate_sign([param.app_id, param.session, param.name, param.tel, param.addr]) elif version=='v3': md5_str = app_helper.generate_sign([param.app_id, param.session, param.name, param.tel, param.addr, param.title, param.detail, param.city, param.loc]) if md5_str!=param.sign: return json.dumps({'ret' : -1, 'msg' : '签名验证错误'}) # 判断地址是否有对应门店,否则不在送货范围内 alert = False message = '' if version=='v2': # 获得 收货地址 坐标 ret, loc = lbs.addr_to_loc(param.addr.strip().encode('utf-8')) print ret, loc if ret<0: loc = {'lat': 0, 'lng': 0} alert = True message = '地址定位失败,请重新输入地址' else: poly_shop, loc_shop = lbs.locate_shop((loc['lat'],loc['lng'])) if poly_shop==None: print '不在配送范围内' alert = True message = '很抱歉,收货地址不在配送范围内,请更改地址' #,整箱预售商品可正常购买' # 更新个人资料 new_addr = ( app_helper.my_rand(), param.name.strip(), param.tel.strip(), param.addr.strip(), int(time.time()), loc, ) elif version=='v3': # 使用提示地址的坐标进行匹配 loc0 = param.loc.split(',') # 31.20474193,121.620708272 if len(loc0)<2 or '' in loc0: loc = {'lat': 0, 'lng': 0} alert = True message = '地址定位失败,请重新输入地址' else: loc = {'lat' : float(loc0[0]), 'lng' : float(loc0[1])} print loc poly_shop, loc_shop = lbs.locate_shop((loc['lat'],loc['lng'])) if poly_shop==None: print '不在配送范围内' alert = True message = '很抱歉,收货地址不在配送范围内,请更改地址' #,整箱预售商品可正常购买' # 更新个人资料 new_addr = ( app_helper.my_rand(), param.name.strip(), param.tel.strip(), param.addr.strip(), int(time.time()), loc, param.title.strip(), param.detail.strip(), param.city.strip(), ) r = db.app_user.update_one({'uname':uname['uname']}, {'$push' : {'address' : new_addr}}) # 返回 return json.dumps({'ret' : 0, 'data' : { 'addr_id' : new_addr[0], 'alert' : alert, 'message' : message, }}) else: return json.dumps({'ret' : -4, 'msg' : '无效的session'})
def POST(self): web.header('Content-Type', 'application/json') param = web.input(openid='', session_id='', name='', tel='', addr='', city='') if '' in (param.name, param.tel, param.addr, param.city): return json.dumps({'ret': -2, 'msg': '参数错误'}) if param.openid == '' and param.session_id == '': return json.dumps({'ret': -2, 'msg': '参数错误1'}) # 同时支持openid和session_id if param.openid != '': uname = app_helper.check_openid(param.openid) else: uname = app_helper.wx_logged(param.session_id) if uname: # 判断地址是否有对应门店,否则不在送货范围内 alert = False sort_tick = int(time.time()) message = '' # 获得 收货地址 坐标, 设置城市, v3 ret, loc = lbs.addr_to_loc(param.addr.strip().encode('utf-8'), city=param.city.strip().encode('utf-8')) print ret, loc if ret < 0: loc = {'lat': 0, 'lng': 0} alert = False #True message = '地址定位失败,请重新输入地址' sort_tick = 0 else: poly_shop, loc_shop = lbs.locate_shop((loc['lat'], loc['lng'])) if poly_shop == None: print '不在配送范围内' alert = False # True # 拼团不提示 message = '很抱歉,收货地址不在配送范围内,请更改地址' #,整箱预售商品可正常购买' sort_tick = 0 # 更新个人资料 new_addr = ( app_helper.my_rand(), param.name.strip(), param.tel.strip(), param.addr.strip(), sort_tick, loc, '', # app 的title '', # app 的detail param.city.strip(), ) r = db.app_user.update_one({'openid': uname['openid']}, {'$push': { 'address': new_addr }}) # 返回 return json.dumps({ 'ret': 0, 'data': { 'addr_id': new_addr[0], 'alert': alert, 'message': message, } }) else: return json.dumps({'ret': -4, 'msg': '无效的openid'})
def POST(self, version='v2'): web.header('Content-Type', 'application/json') if version not in ('v2','v3'): return json.dumps({'ret' : -999, 'msg' : '版本错误!'}) print 'version=',version param = web.input(app_id='', type='', data='', gps='', sign='') if '' in (param.app_id, param.type, param.sign): return json.dumps({'ret' : -2, 'msg' : '参数错误'}) if param.type not in ['GPS', 'NAME', 'LOC']: return json.dumps({'ret' : -7, 'msg' : 'type参数错误'}) #验证签名 md5_str = app_helper.generate_sign([param.app_id, param.type, param.data, param.gps]) if md5_str!=param.sign: return json.dumps({'ret' : -1, 'msg' : '签名验证错误'}) # 准备用户坐标 print param.type.encode('utf-8'), param.data.encode('utf-8') if param.type=='NAME': ret, loc = lbs.addr_to_loc(param['data'].encode('utf-8')) print ret, loc if ret<0: # 重试一次,网络可能会失败 ret, loc = lbs.addr_to_loc(param['data'].encode('utf-8')) print ret, loc if ret<0: loc = {'lat': 0, 'lng': 0} elif param.type=='GPS': loc0 = param.data.split(',') # 31.20474193,121.620708272 if len(loc0)<2 or '' in loc0: loc = {'lat': 0, 'lng': 0} else: ret, loc0 = lbs.geo_convert(float(loc0[0]), float(loc0[1])) if ret==0: loc = {'lat': loc0[0]['y'], 'lng': loc0[0]['x']} else: loc = {'lat': 0, 'lng': 0} elif param.type=='LOC': # 使用联想地址提供的坐标(百度坐标,不需要转换) loc0 = param.data.split(',') # 31.20474193,121.620708272 loc = {'lat': float(loc0[0]), 'lng': float(loc0[1])} print loc # 找最近距离的店 poly_shop, loc_shop = lbs.locate_shop((loc['lat'],loc['lng'])) if poly_shop==None: print '不在配送范围内' #return json.dumps({'ret' : -6, 'msg' : '很抱歉,普通商品无法配送到当前收货地址,整箱预售商品可正常购买'}) return json.dumps({'ret' : -6, 'msg' : '很抱歉,收货地址不在配送范围内,请更改地址'}) # 计算gps坐标到站点距离 distance = 0 if param.gps!='': loc0 = param.gps.split(',') # 31.20474193,121.620708272 纬度,经度 if len(loc0)==2: distance = lbs.geo_distance(loc_shop['lat'],loc_shop['lng'], float(loc0[0]),float(loc0[1])) # 返回多边形匹配shop print 'choose:', poly_shop[1].encode('utf-8') if version=='v2': ret_data = {'ret' : 0, 'data' : { 'shop_id' : str(poly_shop[0]), 'shop_name' : poly_shop[1], #'address' : poly_shop[2], 'distance' : int(distance), 'alert' : False, #True if distance>app_helper.max_alert_distance else False, 'message' : ('您当前定位的地址距收货地址超过%d公里,请确认后购买' % app_helper.max_alert_distance) if distance>app_helper.max_alert_distance else '', }} elif version=='v3': # by 站点 配送费 str_shop = str(poly_shop[0]) if str_shop in app_helper.delivery_by_shop.keys(): delivery_fee = app_helper.delivery_by_shop[str_shop]['delivery_fee'] free_delivery = app_helper.delivery_by_shop[str_shop]['free_delivery'] else: delivery_fee = app_helper.delivery_fee free_delivery = app_helper.free_delivery # by 站点, banner if str_shop in app_helper.BANNER_shop.keys(): BANNER = app_helper.BANNER_shop[str_shop] BANNER_URL = app_helper.BANNER_URL_shop[str_shop] else: BANNER = app_helper.BANNER BANNER_URL = app_helper.BANNER_URL ret_data = {'ret' : 0, 'data' : { 'shop_id' : str_shop, 'shop_name' : poly_shop[1], #'address' : poly_shop[2], 'distance' : int(distance), 'alert' : False, #True if distance>app_helper.max_alert_distance else False, 'message' : ('您当前定位的地址距收货地址超过%d公里,请确认后购买' % app_helper.max_alert_distance) if distance>app_helper.max_alert_distance else '', 'delivery_fee' : '%.2f' % delivery_fee, 'free_delivery' : '%.2f' % free_delivery, 'first_promote' : '%.2f' % app_helper.first_promote, 'banner' : BANNER, 'banner_url' : BANNER_URL, }} #print ret_data return json.dumps(ret_data)
def pt_checkout(uname, param): db_user = db.app_user.find_one( {'openid': uname['openid']}, #, 'mice':{'$ne':1}}, { 'coupon': 1, 'address': 1, 'credit': 1, 'mice': 1 }) if db_user == None: # 不应该发生 return {'ret': -99, 'msg': '未找到用户信息'} # 检查mice, 排除白名单 if db_user.get( 'mice') == 1 and uname['uname'] not in app_helper.WHITE_LIST: print 'mice !!!' return {'ret': -99, 'msg': '未找到用户信息'} # 先要核对送货地址是否在门店送货范围内!!!!!!! -- 需补充 # 查找shop #db_shop = db.base_shop.find_one({'_id':ObjectId(param.shop_id)}) #if db_shop==None: # return {'ret' : -6, 'msg' : 'shop_id错误'} # 查询收货地址 address = None for i in db_user['address']: if i[0] == param['addr_id']: address = list(i) break if address == None: return {'ret': -7, 'msg': 'addr_id错误'} # 获得 收货地址 坐标 if len(address) > 5: # 使用已有的gps地址 loc = address[5] else: ret, loc = lbs.addr_to_loc(address[3].encode('utf-8')) if ret < 0: # 重试一次 ret, loc = lbs.addr_to_loc(address[3].encode('utf-8')) if ret < 0: loc = {'lat': 0, 'lng': 0} print loc # 检查是否能匹配到门店 poly_shop, loc_shop = lbs.locate_shop((loc['lat'], loc['lng'])) if poly_shop == None: print '匹配不到门店' # poly_shop[0] = id # poly_shop[1] = name # poly_shop[2] = address ########################################################################### # 用收货电话检查黄牛 2015-08-22 db_recv = db.recv_tel.find_one({'tel': address[2]}) if db_recv: one_more = 0 if uname['openid'] not in db_recv['unames']: # 补充疑似账号 db.recv_tel.update_one({'tel': address[2]}, {'$push': { 'unames': uname['openid'] }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现 mice mice = 1 for b in db_recv['unames']: if b in app_helper.WHITE_LIST: # 过滤白名单相关号码 mice = 0 break db.app_user.update_many({'uname': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) db.app_user.update_many({'openid': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) if one_more == 1: db.app_user.update_one({'openid': uname['openid']}, {'$set': { 'mice': mice }}) if mice == 1: print '!!! mice:', address[2] #, uname, db_recv['unames'] return {'ret': -99, 'msg': '黄牛下单1'} else: db.recv_tel.insert_one({ 'tel': address[2], 'unames': [uname['openid']] }) #print 'insert', address[2] # 用收货地址检查黄牛, 不准确,不能标注 2015-08-23 db_recv = db.recv_addr.find_one({'addr': address[3]}) if db_recv: one_more = 0 if uname['openid'] not in db_recv['unames']: db.recv_addr.update_one({'addr': address[3]}, {'$push': { 'unames': uname['openid'] }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现疑似mice,不标注,因为不确定 print '!!! maybe a mice:', address[3].encode( 'utf-8') #, uname['openid'], db_recv['unames'] else: db.recv_addr.insert_one({ 'addr': address[3], 'unames': [uname['openid']] }) #print 'insert', address[2] # 查黄牛-结束 ########################################################################### # 查找优惠券 # 未查到,则不使用优惠券 coupon = None for i in db_user['coupon']: if i[0] == param['coupon_id']: coupon = list(i) break # 转换cart数据为json,应该有异常捕获 !!! cart = json.loads(param['cart']) print cart if len(cart) == 0: return {'ret': -5, 'msg': '购物车无数据'} #if not cart[0].has_key('tuan_id'): # return {'ret' : -5, 'msg' : '购物车数据错误'} # 订单状态:DUE, PAID, ONROAD, COMPLETED, CANCELED, FINISH # 默认运费 5元,免邮门槛 29元 now_tick = int(time.time()) # 检查活动是否可继续 db_pt_sku = db.pt_store.find_one({ 'tuan_id': cart[0]['tuan_id'], 'region_id': { '$in': [param['region_id']] }, #'online' : 1, }) if db_pt_sku == None: # tuan_id 错误 return {'ret': -8, 'msg': '未找到拼团活动信息'} cart[0]['title'] = db_pt_sku['title'] if db_pt_sku['sale_out'] == 1: return {'ret': -9, 'msg': '此拼团活动已售罄'} if len(param['pt_order_id']) == 0: # 新开团 # 新开团检查是否下架和过期,已开团不检查 if param['region_id'] not in db_pt_sku['online']: return {'ret': -9, 'msg': '很抱歉,该拼团活动刚刚下架,无法继续下单'} if db_pt_sku['expire_tick'] < now_tick: return {'ret': -9, 'msg': '很抱歉,该拼团活动刚刚结束,无法继续下单'} # 准备新的活动订单 expire_hour = 24 # 测试1小时 db_pt_order = { 'tuan_id': cart[0]['tuan_id'], 'pt_order_id': '', # 提交付款后生成 'region_id': param['region_id'], 'expire_tick': now_tick + 3600 * expire_hour, 'expire_time': app_helper.time_str(now_tick + 3600 * expire_hour), 'create_tick': now_tick, 'create_time': app_helper.time_str(), 'leader': uname['openid'], 'member': [], 'need': db_pt_sku['tuan_size'] if cart[0]['type'] == 'TUAN' else 1, 'type': 'TUAN' if cart[0]['type'] == 'TUAN' else 'SINGLE', 'status': 'WAIT', # 等待开团 } # 身份 position = 'LEADER' else: # 已开团,检查是否可参团 db_pt_order = db.pt_order.find_one( {'pt_order_id': param['pt_order_id']}) if db_pt_order == None: return {'ret': -8, 'msg': '未找到活动订单'} # 新开团检查是否下架和过期,已开团不检查, need == tuan_size if (db_pt_order['need'] == db_pt_sku['tuan_size']) and (param['region_id'] not in db_pt_sku['online']): return {'ret': -9, 'msg': '很抱歉,该拼团活动刚刚下架,无法继续下单'} if db_pt_order['status'] == 'SUCC': return {'ret': -9, 'msg': '很抱歉,您慢了一步,该团已满员无法继续下单'} if db_pt_order['status'] == 'FAIL2': return {'ret': -9, 'msg': '很抱歉,该商品已售罄,无法继续下单'} if db_pt_order[ 'status'] == 'FAIL1' or db_pt_order['expire_tick'] < now_tick: return {'ret': -9, 'msg': '很抱歉,该拼团活动刚刚结束,无法继续下单'} # 检查是否已在此团 for m in db_pt_order['member']: if m['openid'] == uname['openid']: return {'ret': -9, 'msg': '你已参加此团,不能重复参团!'} # 身份 if len(db_pt_order['member']) == 1: position = 'SCEOND' else: position = 'MEMBER' order = { 'status': 'DUE', 'uname': uname['openid'], 'shop_0': poly_shop[0] if poly_shop != None else ObjectId( setting.PT_shop[db_pt_order['region_id']]), 'shop': ObjectId(setting.PT_shop[db_pt_order['region_id']]), #'shop_0' : poly_shop[0] if poly_shop!=None else '', 'user': uname['openid'], 'order_id': '', #order_id, 'order_source': 'wx_tuan', # 2015-10-20 'address': address, # 收货地址 'coupon': coupon, # 使用的优惠券 'cart': cart, # 购物车 'cost': '0.00', # 成本合计,参考 'total': '0.00', # 价格小计,加项 'coupon_disc': '0.00', # 优惠券抵扣,减项 'first_disc': '0.00', # 首单立减, 减项 'delivery_fee': '0.00', # 运费,加项 'due': '0.00', # 应付价格 'openid': uname['openid'], 'app_uname': uname['uname'], 'uname_id': db_user['_id'], # for processor 'next_status': '', 'lock': 0, 'man': 0, 'retry': 0, 'comment': '', 'b_time': int(time.time()), 'e_time': int(time.time()), 'deadline': int(time.time() + 60 * 15), # 拼团使用 'pt_order_id': param['pt_order_id'], 'type': db_pt_order['type'], 'region_id': db_pt_order['region_id'], 'position': position, } if order['type'] == 'TUAN': # 拼团价格 order['total'] = order['due'] = db_pt_sku['tuan_price'] else: # 单人购价格 order['total'] = order['due'] = db_pt_sku['price'] if float(order['due']) < 0: order['due'] = '0.10' # 保存在用户信息里,微信不回重复登录,所以只保留一处,不用关联session,与app不同 if len(param['pt_order_id']) == 0: # 新开团 update_set = { 'cart_order_wx': [order, db_pt_order], } else: update_set = { 'cart_order_wx': [order], } db.app_user.update_one({'openid': uname['openid']}, {'$set': update_set}) image_host = 'http://%s/image/product' % setting.image_host # 返回信息 position = 'VISITOR' for i in db_pt_order['member']: if i['openid'] == uname['openid']: position = i['position'] break ret_data = { 'region_id': order['region_id'], 'addr_id': address[0], 'cart': [ { 'tuan_id': cart[0]['tuan_id'], 'title1': db_pt_sku['title'], 'image': [ '%s/%s/%s' % (image_host, x[:2], x) for x in db_pt_sku['image'] ], 'status': db_pt_order['status'], 'price': order['total'], 'type': '%d人团' % db_pt_sku['tuan_size'] if order['type'] == 'TUAN' else '单人购买', }, ], 'coupon_list': [], 'total': order['total'], 'coupon': order['coupon'], 'coupon_disc': order['coupon_disc'], 'due': order['due'], 'alert_title': True, 'cart_title': '免配送费,组团成功后我们会尽快为您安排发货' if order['type'] == 'TUAN' else '免配送费,下单后我们会尽快为您安排发货', 'position': position, 'need': db_pt_order['need'], } return {'ret': 0, 'data': ret_data}