python学习

This commit is contained in:
2019-08-06 14:17:42 +08:00
parent 6569d29d7e
commit 54761c6262
52 changed files with 2943 additions and 647 deletions

817
.idea/workspace.xml generated

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,6 @@ def iPagination( params ):
ret['range'] = range( ret['from'],ret['end'] + 1 )
return ret
'''
统一渲染方法
'''
@@ -108,7 +107,7 @@ def selectFilterObj( obj,field ):
return ret
def getDictFilterField( db_model,select_filed,key_field,id_list ):
def getDictListFilterField( db_model,select_filed,key_field,id_list ):
ret = {}
query = db_model.query
if id_list and len( id_list ) > 0:

View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
import hashlib,requests,random,string,json
from application import app,db
from common.models.member.MemberCart import MemberCart
from common.libs.Helper import getCurrentDate
class CartService():
@staticmethod
def deleteItem( member_id = 0,items = None ):
if member_id < 1 or not items:
return False
for item in items:
MemberCart.query.filter_by( food_id = item['id'],member_id = member_id ).delete()
db.session.commit()
return True
@staticmethod
def setItems( member_id = 0,food_id = 0,number = 0 ):
if member_id < 1 or food_id < 1 or number < 1:
return False
cart_info = MemberCart.query.filter_by( food_id = food_id, member_id= member_id ).first()
if cart_info:
model_cart = cart_info
else:
model_cart = MemberCart()
model_cart.member_id = member_id
model_cart.created_time = getCurrentDate()
model_cart.food_id = food_id
model_cart.quantity = number
model_cart.updated_time = getCurrentDate()
db.session.add(model_cart)
db.session.commit()
return True

View File

@@ -0,0 +1,191 @@
# -*- coding: utf-8 -*-
import hashlib,time,random,decimal,json
from application import app,db
from common.models.food.Food import Food
from common.models.food.FoodSaleChangeLog import FoodSaleChangeLog
from common.models.pay.PayOrder import PayOrder
from common.models.pay.PayOrderItem import PayOrderItem
from common.models.pay.PayOrderCallbackData import PayOrderCallbackData
from common.libs.Helper import getCurrentDate
from common.libs.queue.QueueService import QueueService
from common.libs.food.FoodService import FoodService
class PayService():
def __init__(self):
pass
def createOrder(self,member_id,items = None,params = None):
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
pay_price = decimal.Decimal( 0.00 )
continue_cnt = 0
food_ids = []
for item in items:
if decimal.Decimal( item['price'] ) < 0 :
continue_cnt += 1
continue
pay_price = pay_price + decimal.Decimal( item['price'] ) * int( item['number'] )
food_ids.append( item['id'] )
if continue_cnt >= len(items ) :
resp['code'] = -1
resp['msg'] = '商品items为空~~'
return resp
yun_price = params['yun_price'] if params and 'yun_price' in params else 0
note = params['note'] if params and 'note' in params else ''
express_address_id = params['express_address_id'] if params and 'express_address_id' in params else 0
express_info = params['express_info'] if params and 'express_info' in params else {}
yun_price = decimal.Decimal( yun_price )
total_price = pay_price + yun_price
try:
#为了防止并发库存出问题了我们坐下selectfor update, 这里可以给大家演示下
tmp_food_list = db.session.query( Food ).filter( Food.id.in_( food_ids ) )\
.with_for_update().all()
tmp_food_stock_mapping = {}
for tmp_item in tmp_food_list:
tmp_food_stock_mapping[ tmp_item.id ] = tmp_item.stock
model_pay_order = PayOrder()
model_pay_order.order_sn = self.geneOrderSn()
model_pay_order.member_id = member_id
model_pay_order.total_price = total_price
model_pay_order.yun_price = yun_price
model_pay_order.pay_price = pay_price
model_pay_order.note = note
model_pay_order.status = -8
model_pay_order.express_status = -8
model_pay_order.express_address_id = express_address_id
model_pay_order.express_info = json.dumps( express_info )
model_pay_order.updated_time = model_pay_order.created_time = getCurrentDate()
db.session.add( model_pay_order )
#db.session.flush()
for item in items:
tmp_left_stock = tmp_food_stock_mapping[ item['id'] ]
if decimal.Decimal(item['price']) < 0:
continue
if int( item['number'] ) > int( tmp_left_stock ):
raise Exception( "您购买的这美食太火爆了,剩余:%s,你购买%s~~"%( tmp_left_stock,item['number'] ) )
tmp_ret = Food.query.filter_by( id = item['id'] ).update({
"stock":int(tmp_left_stock) - int(item['number'])
})
if not tmp_ret:
raise Exception("下单失败请重新下单")
tmp_pay_item = PayOrderItem()
tmp_pay_item.pay_order_id = model_pay_order.id
tmp_pay_item.member_id = member_id
tmp_pay_item.quantity = item['number']
tmp_pay_item.price = item['price']
tmp_pay_item.food_id = item['id']
tmp_pay_item.note = note
tmp_pay_item.updated_time = tmp_pay_item.created_time = getCurrentDate()
db.session.add( tmp_pay_item )
#db.session.flush()
FoodService.setStockChangeLog( item['id'],-item['number'],"在线购买" )
db.session.commit()
resp['data'] = {
'id' : model_pay_order.id,
'order_sn' : model_pay_order.order_sn,
'total_price':str( total_price )
}
except Exception as e:
db.session.rollback()
print( e )
resp['code'] = -1
resp['msg'] = "下单失败请重新下单"
resp['msg'] = str(e)
return resp
return resp
def closeOrder(self,pay_order_id = 0):
if pay_order_id < 1:
return False
pay_order_info = PayOrder.query.filter_by( id = pay_order_id ,status = -8 ).first()
if not pay_order_info:
return False
pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_id ).all()
if pay_order_items:
#需要归还库存
for item in pay_order_items:
tmp_food_info = Food.query.filter_by( id = item.food_id ).first()
if tmp_food_info:
tmp_food_info.stock = tmp_food_info.stock + item.quantity
tmp_food_info.updated_time = getCurrentDate()
db.session.add( tmp_food_info )
db.session.commit()
FoodService.setStockChangeLog( item.food_id, item.quantity, "订单取消")
pay_order_info.status = 0
pay_order_info.updated_time = getCurrentDate()
db.session.add( pay_order_info )
db.session.commit()
return True
def orderSuccess(self,pay_order_id = 0,params = None):
try:
pay_order_info = PayOrder.query.filter_by( id = pay_order_id ).first()
if not pay_order_info or pay_order_info.status not in [ -8,-7 ]:
return True
pay_order_info.pay_sn = params['pay_sn'] if params and 'pay_sn' in params else ''
pay_order_info.status = 1
pay_order_info.express_status = -7
pay_order_info.updated_time = getCurrentDate()
db.session.add( pay_order_info )
pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_id ).all()
for order_item in pay_order_items:
tmp_model_sale_log = FoodSaleChangeLog()
tmp_model_sale_log.food_id = order_item.food_id
tmp_model_sale_log.quantity = order_item.quantity
tmp_model_sale_log.price = order_item.price
tmp_model_sale_log.member_id = order_item.member_id
tmp_model_sale_log.created_time = getCurrentDate()
db.session.add( tmp_model_sale_log )
db.session.commit()
except Exception as e:
db.session.rollback()
print(e)
return False
#加入通知队列,做消息提醒和
QueueService.addQueue( "pay",{
"member_id": pay_order_info.member_id,
"pay_order_id":pay_order_info.id
})
return True
def addPayCallbackData(self,pay_order_id = 0,type = 'pay',data = ''):
model_callback = PayOrderCallbackData()
model_callback.pay_order_id = pay_order_id
if type == "pay":
model_callback.pay_data = data
model_callback.refund_data = ''
else:
model_callback.refund_data = data
model_callback.pay_data = ''
model_callback.created_time = model_callback.updated_time = getCurrentDate()
db.session.add( model_callback )
db.session.commit()
return True
def geneOrderSn(self):
m = hashlib.md5()
sn = None
while True:
str = "%s-%s"%( int( round( time.time() * 1000) ),random.randint( 0,9999999 ) )
m.update(str.encode("utf-8"))
sn = m.hexdigest()
if not PayOrder.query.filter_by( order_sn = sn ).first():
break
return sn

View File

@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
import hashlib,requests,uuid,json,datetime
import xml.etree.ElementTree as ET
from application import app,db
from common.models.pay.OauthAccessToken import OauthAccessToken
from common.libs.Helper import getCurrentDate
class WeChatService():
def __init__(self,merchant_key = None):
self.merchant_key = merchant_key
def create_sign(self, pay_data):
'''
生成签名
:return:
'''
stringA = '&'.join(["{0}={1}".format(k, pay_data.get(k)) for k in sorted(pay_data)])
stringSignTemp = '{0}&key={1}'.format(stringA, self.merchant_key)
sign = hashlib.md5( stringSignTemp.encode("utf-8") ).hexdigest()
return sign.upper()
def get_pay_info(self,pay_data = None):
'''
获取支付信息
:param xml_data:
:return:
'''
sign = self.create_sign( pay_data )
pay_data ['sign'] = sign
xml_data = self.dict_to_xml( pay_data )
headers = {'Content-Type': 'application/xml'}
url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
r = requests.post( url= url, data=xml_data.encode('utf-8'),headers = headers)
r.encoding = "utf-8"
app.logger.info( r.text )
if r.status_code == 200:
prepay_id = self.xml_to_dict( r.text ).get('prepay_id')
pay_sign_data = {
'appId': pay_data.get('appid'),
'timeStamp': pay_data.get('out_trade_no'),
'nonceStr': pay_data.get('nonce_str'),
'package': 'prepay_id={0}'.format(prepay_id),
'signType': 'MD5'
}
pay_sign = self.create_sign( pay_sign_data )
pay_sign_data.pop('appId')
pay_sign_data['paySign'] = pay_sign
pay_sign_data['prepay_id'] = prepay_id
return pay_sign_data
return False
def dict_to_xml(self,dict_data):
'''
dict to xml
:param dict_data:
:return:
'''
xml = ["<xml>"]
for k, v in dict_data.items():
xml.append("<{0}>{1}</{0}>".format(k, v))
xml.append("</xml>")
return "".join(xml)
def xml_to_dict(self,xml_data):
'''
xml to dict
:param xml_data:
:return:
'''
xml_dict = {}
root = ET.fromstring(xml_data)
for child in root:
xml_dict[child.tag] = child.text
return xml_dict
def get_nonce_str(self):
'''
获取随机字符串
:return:
'''
return str(uuid.uuid4()).replace('-', '')
def getAccessToken(self):
token = None
token_info = OauthAccessToken.query.filter( OauthAccessToken.expired_time >= getCurrentDate() ).first()
if token_info:
token = token_info.access_token
return token
config_mina = app.config['MINA_APP']
url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}"\
.format( config_mina['appid'],config_mina['appkey'] )
r = requests.get( url = url )
if r.status_code != 200 or not r.text:
return token
data = json.loads( r.text )
now = datetime.datetime.now()
date = now + datetime.timedelta(seconds=data['expires_in'] - 200)
model_token = OauthAccessToken()
model_token.access_token = data['access_token']
model_token.expired_time = date.strftime( "%Y-%m-%d %H:%M:%S" )
model_token.created_time = getCurrentDate()
db.session.add( model_token )
db.session.commit()
return data['access_token']

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
import json
from common.models.queue.QueueList import QueueList
from common.libs.Helper import getCurrentDate
from application import app,db
class QueueService():
@staticmethod
def addQueue( queue_name,data = None ):
model_queue = QueueList()
model_queue.queue_name = queue_name
if data:
model_queue.data = json.dumps( data )
model_queue.created_time = model_queue.updated_time = getCurrentDate()
db.session.add( model_queue )
db.session.commit()
return True

View File

@@ -0,0 +1,13 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Integer, String
from sqlalchemy.schema import FetchedValue
from application import db
class WxShareHistory(db.Model):
__tablename__ = 'wx_share_history'
id = db.Column(db.Integer, primary_key=True)
member_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
share_url = db.Column(db.String(200), nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,26 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Index, Integer, String
from sqlalchemy.schema import FetchedValue
from application import db
class MemberAddress(db.Model):
__tablename__ = 'member_address'
__table_args__ = (
db.Index('idx_member_id_status', 'member_id', 'status'),
)
id = db.Column(db.Integer, primary_key=True)
member_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
nickname = db.Column(db.String(20), nullable=False, server_default=db.FetchedValue())
mobile = db.Column(db.String(11), nullable=False, server_default=db.FetchedValue())
province_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
province_str = db.Column(db.String(50), nullable=False, server_default=db.FetchedValue())
city_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
city_str = db.Column(db.String(50), nullable=False, server_default=db.FetchedValue())
area_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
area_str = db.Column(db.String(50), nullable=False, server_default=db.FetchedValue())
address = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue())
status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
is_default = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,15 @@
# coding: utf-8
from sqlalchemy import BigInteger, Column, DateTime, Integer
from sqlalchemy.schema import FetchedValue
from application import db
class MemberCart(db.Model):
__tablename__ = 'member_cart'
id = db.Column(db.Integer, primary_key=True)
member_id = db.Column(db.BigInteger, nullable=False, index=True, server_default=db.FetchedValue())
food_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
quantity = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,25 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Integer, String
from sqlalchemy.schema import FetchedValue
from application import db
class MemberComments(db.Model):
__tablename__ = 'member_comments'
id = db.Column(db.Integer, primary_key=True)
member_id = db.Column(db.Integer, nullable=False, index=True, server_default=db.FetchedValue())
food_ids = db.Column(db.String(200), nullable=False, server_default=db.FetchedValue())
pay_order_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
score = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
content = db.Column(db.String(200), nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
@property
def score_desc(self):
score_map = {
"10": "好评",
"6": "中评",
"0": "差评",
}
return score_map[ str( self.score ) ]

View File

@@ -0,0 +1,21 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Index, Integer, String, Text
from sqlalchemy.schema import FetchedValue
from application import db
class OauthMemberBind(db.Model):
__tablename__ = 'oauth_member_bind'
__table_args__ = (
db.Index('idx_type_openid', 'type', 'openid'),
)
id = db.Column(db.Integer, primary_key=True)
member_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
client_type = db.Column(db.String(20), nullable=False, server_default=db.FetchedValue())
type = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
openid = db.Column(db.String(80), nullable=False, server_default=db.FetchedValue())
unionid = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue())
extra = db.Column(db.Text, nullable=False)
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,13 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Integer, String
from sqlalchemy.schema import FetchedValue
from application import db
class OauthAccessToken(db.Model):
__tablename__ = 'oauth_access_token'
id = db.Column(db.Integer, primary_key=True)
access_token = db.Column(db.String(600), nullable=False, server_default=db.FetchedValue())
expired_time = db.Column(db.DateTime, nullable=False, index=True, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,51 @@
# coding: utf-8
from sqlalchemy import BigInteger, Column, DateTime, Index, Integer, Numeric, String, Text
from sqlalchemy.schema import FetchedValue
from application import db,app
class PayOrder(db.Model):
__tablename__ = 'pay_order'
__table_args__ = (
db.Index('idx_member_id_status', 'member_id', 'status'),
)
id = db.Column(db.Integer, primary_key=True)
order_sn = db.Column(db.String(40), nullable=False, unique=True, server_default=db.FetchedValue())
member_id = db.Column(db.BigInteger, nullable=False, server_default=db.FetchedValue())
total_price = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
yun_price = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
pay_price = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
pay_sn = db.Column(db.String(128), nullable=False, server_default=db.FetchedValue())
prepay_id = db.Column(db.String(128), nullable=False, server_default=db.FetchedValue())
note = db.Column(db.Text, nullable=False)
status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
express_status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
express_address_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
express_info = db.Column(db.String(100), nullable=False, server_default=db.FetchedValue())
comment_status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
pay_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
@property
def pay_status(self):
tmp_status = self.status
if self.status == 1:
tmp_status = self.express_status
if self.express_status == 1 and self.comment_status == 0:
tmp_status = -5
if self.express_status == 1 and self.comment_status == 1:
tmp_status = 1
return tmp_status
@property
def status_desc(self):
return app.config['PAY_STATUS_DISPLAY_MAPPING'][ str( self.pay_status )]
@property
def order_number(self):
order_number = self.created_time.strftime("%Y%m%d%H%M%S")
order_number = order_number + str(self.id).zfill(5)
return order_number

View File

@@ -0,0 +1,15 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Integer, Text
from sqlalchemy.schema import FetchedValue
from application import db
class PayOrderCallbackData(db.Model):
__tablename__ = 'pay_order_callback_data'
id = db.Column(db.Integer, primary_key=True)
pay_order_id = db.Column(db.Integer, nullable=False, unique=True, server_default=db.FetchedValue())
pay_data = db.Column(db.Text, nullable=False)
refund_data = db.Column(db.Text, nullable=False)
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,19 @@
# coding: utf-8
from sqlalchemy import BigInteger, Column, DateTime, Integer, Numeric, Text
from sqlalchemy.schema import FetchedValue
from application import db
class PayOrderItem(db.Model):
__tablename__ = 'pay_order_item'
id = db.Column(db.Integer, primary_key=True)
pay_order_id = db.Column(db.Integer, nullable=False, index=True, server_default=db.FetchedValue())
member_id = db.Column(db.BigInteger, nullable=False, server_default=db.FetchedValue())
quantity = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
price = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
food_id = db.Column(db.Integer, nullable=False, index=True, server_default=db.FetchedValue())
note = db.Column(db.Text, nullable=False)
status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,15 @@
# coding: utf-8
from sqlalchemy import Column, DateTime, Integer, String
from sqlalchemy.schema import FetchedValue
from application import db
class QueueList(db.Model):
__tablename__ = 'queue_list'
id = db.Column(db.Integer, primary_key=True)
queue_name = db.Column(db.String(30), nullable=False, server_default=db.FetchedValue())
data = db.Column(db.String(500), nullable=False, server_default=db.FetchedValue())
status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,19 @@
# coding: utf-8
from sqlalchemy import Column, Date, DateTime, Index, Integer, Numeric
from sqlalchemy.schema import FetchedValue
from application import db
class StatDailyFood(db.Model):
__tablename__ = 'stat_daily_food'
__table_args__ = (
db.Index('date_food_id', 'date', 'food_id'),
)
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date, nullable=False)
food_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
total_count = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
total_pay_money = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,19 @@
# coding: utf-8
from sqlalchemy import Column, Date, DateTime, Index, Integer, Numeric
from sqlalchemy.schema import FetchedValue
from application import db
class StatDailyMember(db.Model):
__tablename__ = 'stat_daily_member'
__table_args__ = (
db.Index('idx_date_member_id', 'date', 'member_id'),
)
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date, nullable=False)
member_id = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
total_shared_count = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
total_pay_money = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -0,0 +1,18 @@
# coding: utf-8
from sqlalchemy import Column, Date, DateTime, Integer, Numeric
from sqlalchemy.schema import FetchedValue
from application import db
class StatDailySite(db.Model):
__tablename__ = 'stat_daily_site'
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date, nullable=False, index=True)
total_pay_money = db.Column(db.Numeric(10, 2), nullable=False, server_default=db.FetchedValue())
total_member_count = db.Column(db.Integer, nullable=False)
total_new_member_count = db.Column(db.Integer, nullable=False)
total_order_count = db.Column(db.Integer, nullable=False)
total_shared_count = db.Column(db.Integer, nullable=False)
updated_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())
created_time = db.Column(db.DateTime, nullable=False, server_default=db.FetchedValue())

View File

@@ -7,8 +7,7 @@ AUTH_COOKIE_NAME = "mooc_food"
##过滤url
IGNORE_URLS = [
"^/user/login",
"^/api"
"^/user/login"
]
IGNORE_CHECK_LOGIN_URLS = [
@@ -16,7 +15,9 @@ IGNORE_CHECK_LOGIN_URLS = [
"^/favicon.ico"
]
API_IGNORE_URLS = [
"^/api"
]
PAGE_SIZE = 50
PAGE_DISPLAY = 10
@@ -29,7 +30,7 @@ STATUS_MAPPING = {
MINA_APP = {
'appid':'wx2c65877d37fc29bf',
'appkey':'8c61791794cde415042924a9714542a9',
'appkey':'b670fb4798ec6abf4bab32ae3cf14a61',
'paykey':'xxxxxxxxxxxxxx换自己的',
'mch_id':'xxxxxxxxxxxx换自己的',
'callback_url':'/api/order/callback'
@@ -43,4 +44,20 @@ UPLOAD = {
APP = {
'domain':'http://127.0.0.1:9000'
}
PAY_STATUS_MAPPING = {
"1":"已支付",
"-8":"待支付",
"0":"已关闭"
}
PAY_STATUS_DISPLAY_MAPPING = {
"0":"订单关闭",
"1":"支付成功",
"-8":"待支付",
"-7":"待发货",
"-6":"待确认",
"-5":"待评价"
}

3
jobs/bash_jobs Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
export ops_config=production
. /data/www/python3_vir/bin/activate

57
jobs/launcher.py Normal file
View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from application import app,manager
from flask_script import Command,Option
import argparse,sys,traceback
'''
python manage.py runjob -m Test ( jobs/tasks/Test.py )
python manage.py runjob -m test/Index ( jobs/tasks/test/Index.py )
* name or flags - 名称或选项字符串列表, e.g. foo or -f, --foo.
* action - 参数如果定义了选项表示这是一个操作参数至于调用时做哪种操作由用户输入或者default决定。
* nargs - 应该使用的命令行参数数。.
* const - 某些动作或参数个数的常数值。.
* default - 如果命令行没有对输入这个参数相应的值则此参数用default给出的值.
* type -将用户输入的值转化为哪种类型.
* choices - 参数可输入值的范围或选择.
* required - 命令行输入的值是否可以被忽略(布尔量).
* help - 参数的简要描述.
* metavar - useage中显示的参数的名称.
* dest - 要添加到解析参数返回的对象中的属性的名称.
'''
class runJob( Command ):
capture_all_args = True
def run(self,*args,**kwargs):
args = sys.argv[2:]
parser = argparse.ArgumentParser( add_help = True )
parser.add_argument("-m","--name",dest = "name",metavar = "name", help="指定job名",required=True)
parser.add_argument("-a","--act",dest = "act",metavar = "act", help="Job动作",required=False)
parser.add_argument("-p","--param",dest = "param",nargs = "*", metavar = "param",help="业务参数",default = '',required=False)
params = parser.parse_args( args )
params_dict = params.__dict__
ret_params = {}
for item in params_dict.keys():
ret_params[ item ] = params_dict[ item ]
if "name" not in ret_params or not ret_params['name']:
return self.tips()
module_name = ret_params['name'].replace( "/","." )
try:
import_string = "from jobs.tasks.%s import JobTask as job_target" % ( module_name )
exec( import_string , globals() )
target = job_target()
target.run( ret_params )
except Exception as e:
traceback.print_exc()
def tips(self):
tip_msg = '''
请正确调度Job
python manage runjob -m Test ( jobs/tasks/Test.py )
python manage runjob -m test/Index ( jobs/tasks/test/Index.py )
'''
app.logger.info( tip_msg )
return False

9
jobs/readme.md Normal file
View File

@@ -0,0 +1,9 @@
Job 列表
======
* 队列Job
* * * * * { . ~/.bash_jobs && cd /data/www/Order && python manager.py runjob -m queue/index ;} >> /data/www/logs/queue_list.`date +\%Y_\%m_\%d`.log 2>&1
* * * * * { . ~/.bash_jobs && cd /data/www/Order && python manager.py runjob -m pay/index ;} >> /data/www/logs/pay_index.`date +\%Y_\%m_\%d`.log 2>&1
1 2 * * { . ~/.bash_jobs && cd /data/www/Order && python manager.py runjob -m stat/daily -a member ;} >> /data/www/logs/pay_index.`date +\%Y_\%m_\%d`.log 2>&1
2 2 * * * { . ~/.bash_jobs && cd /data/www/Order && python manager.py runjob -m stat/daily -a food ;} >> /data/www/logs/pay_index.`date +\%Y_\%m_\%d`.log 2>&1
3 2 * * * { . ~/.bash_jobs && cd /data/www/Order && python manager.py runjob -m stat/daily -a site ;} >> /data/www/logs/pay_index.`date +\%Y_\%m_\%d`.log 2>&1

26
jobs/tasks/pay/index.py Normal file
View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from common.models.pay.PayOrder import PayOrder
from common.libs.Helper import getFormatDate
from common.libs.pay.PayService import PayService
import datetime
from application import app,db
'''
python manager.py runjob -m pay/index
'''
class JobTask():
def __init__(self):
pass
def run(self,params):
now = datetime.datetime.now()
date_before_30min = now + datetime.timedelta( minutes = -30 )
list = PayOrder.query.filter_by( status = -8 ).\
filter( PayOrder.created_time <= getFormatDate( date = date_before_30min ) ).all()
if not list:
app.logger.info("no data~~")
return
pay_target = PayService()
for item in list:
pay_target.closeOrder( pay_order_id = item.id )
app.logger.info("it's over~~")

110
jobs/tasks/queue/index.py Normal file
View File

@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
from application import app,db
from common.models.queue.QueueList import QueueList
import json,requests,datetime
from common.libs.Helper import getCurrentDate
from common.libs.pay.WeChatService import WeChatService
from common.models.pay.PayOrder import PayOrder
from common.models.pay.PayOrderItem import PayOrderItem
from common.models.member.OauthMemberBind import OauthMemberBind
from common.models.food.Food import Food
from common.models.food.FoodSaleChangeLog import FoodSaleChangeLog
from sqlalchemy import func
'''
python manager.py runjob -m queue/index
'''
class JobTask():
def __init__(self):
pass
def run(self,params):
list = QueueList.query.filter_by(status = -1 )\
.order_by( QueueList.id.asc() ).limit(1).all()
for item in list:
if item.queue_name == "pay":
self.handlePay( item )
item.status = 1
item.updated_time = getCurrentDate()
db.session.add( item )
db.session.commit()
def handlePay(self,item ):
data = json.loads( item.data )
if 'member_id' not in data or 'pay_order_id' not in data:
return False
oauth_bind_info = OauthMemberBind.query.filter_by(member_id=data['member_id']).first()
if not oauth_bind_info:
return False
pay_order_info = PayOrder.query.filter_by( id = data['pay_order_id']).first()
if not pay_order_info:
return False
#更新销售总量
pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_info.id ).all()
notice_content = []
if pay_order_items:
date_from = datetime.datetime.now().strftime( "%Y-%m-01 00:00:00" )
date_to = datetime.datetime.now().strftime( "%Y-%m-31 23:59:59" )
for item in pay_order_items:
tmp_food_info = Food.query.filter_by( id = item.food_id ).first()
if not tmp_food_info:
continue
notice_content.append( "%s %s"%( tmp_food_info.name,item.quantity) )
#当月数量
tmp_stat_info = db.session.query(FoodSaleChangeLog, func.sum(FoodSaleChangeLog.quantity).label("total")) \
.filter( FoodSaleChangeLog.food_id == item.food_id )\
.filter( FoodSaleChangeLog.created_time >= date_from,FoodSaleChangeLog.created_time <= date_to ).first()
tmp_month_count = tmp_stat_info[ 1 ] if tmp_stat_info[ 1 ] else 0
tmp_food_info.total_count += 1
tmp_food_info.month_count = tmp_month_count
db.session.add( tmp_food_info )
db.session.commit()
keyword1_val = pay_order_info.note if pay_order_info.note else ''
keyword2_val = "".join( notice_content )
keyword3_val = str( pay_order_info.total_price )
keyword4_val = str( pay_order_info.order_number )
keyword5_val = ""
if pay_order_info.express_info:
express_info = json.loads( pay_order_info.express_info )
keyword5_val = str( express_info['address'] )
#发送模板消息
target_wechat = WeChatService( )
access_token = target_wechat.getAccessToken()
headers = {'Content-Type': 'application/json'}
url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s"%access_token
params = {
"touser": oauth_bind_info.openid,
"template_id":"8aqlWFAjZZ_NnR0_vOvHGcwHglvIlAYRaUyOmFD5kvs",
"page": "pages/my/order_list",
"form_id": pay_order_info.prepay_id,
"data": {
"keyword1": {
"value": keyword1_val
},
"keyword2": {
"value": keyword2_val
},
"keyword3": {
"value": keyword3_val
},
"keyword4": {
"value": keyword4_val
},
"keyword5": {
"value": keyword5_val
}
}
}
r = requests.post(url=url, data= json.dumps( params ).encode('utf-8'), headers=headers)
r.encoding = "utf-8"
app.logger.info(r.text)
return True

215
jobs/tasks/stat/daily.py Normal file
View File

@@ -0,0 +1,215 @@
# -*- coding: utf-8 -*-
from application import app,db
from common.libs.Helper import getFormatDate,getCurrentDate
from common.models.member.Member import Member
from common.models.pay.PayOrder import PayOrder
from common.models.stat.StatDailyFood import StatDailyFood
from common.models.stat.StatDailySite import StatDailySite
from common.models.stat.StatDailyMember import StatDailyMember
from common.models.food.WxShareHistory import WxShareHistory
from common.models.food.FoodSaleChangeLog import FoodSaleChangeLog
from sqlalchemy import func
import random
'''
python manager.py runjob -m stat/daily -a member|food|site -p 2018-07-01
'''
class JobTask():
def __init__(self):
pass
def run(self, params):
act = params['act'] if 'act' in params else ''
date = params['param'][0] if params['param'] and len(params['param']) else getFormatDate(format="%Y-%m-%d")
if not act:
return
date_from = date + " 00:00:00"
date_to = date + " 23:59:59"
func_params = {
'act': act,
'date':date,
'date_from':date_from,
'date_to':date_to
}
if act == "member":
self.statMember( func_params )
elif act == "food":
self.statFood( func_params )
elif act == "site":
self.statSite( func_params)
elif act == "test":
self.test()
app.logger.info("it's over~~")
return
'''
会员统计
'''
def statMember(self,params):
act = params['act']
date = params['date']
date_from = params['date_from']
date_to = params['date_to']
app.logger.info( "act:{0},from:{1},to:{2}".format( act,date_from,date_to ) )
member_list = Member.query.all()
if not member_list:
app.logger.info( "no member list" )
return
for member_info in member_list:
tmp_stat_member = StatDailyMember.query.filter_by( date = date,member_id = member_info.id ).first()
if tmp_stat_member:
tmp_model_stat_member = tmp_stat_member
else:
tmp_model_stat_member = StatDailyMember()
tmp_model_stat_member.date = date
tmp_model_stat_member.member_id = member_info.id
tmp_model_stat_member.created_time = getCurrentDate()
tmp_stat_pay = db.session.query( func.sum(PayOrder.total_price).label("total_pay_money")) \
.filter( PayOrder.member_id == member_info.id ,PayOrder.status == 1 )\
.filter( PayOrder.created_time >= date_from,PayOrder.created_time <= date_to ).first()
tmp_stat_share_count = WxShareHistory.query.filter( PayOrder.member_id == member_info.id )\
.filter( PayOrder.created_time >= date_from,PayOrder.created_time <= date_to ).count()
tmp_model_stat_member.total_shared_count = tmp_stat_share_count
tmp_model_stat_member.total_pay_money = tmp_stat_pay[ 0 ] if tmp_stat_pay[ 0 ] else 0.00
'''
为了测试效果模拟数据
'''
tmp_model_stat_member.total_shared_count = random.randint(50,100)
tmp_model_stat_member.total_pay_money = random.randint(1000,1010)
tmp_model_stat_member.updated_time = getCurrentDate()
db.session.add( tmp_model_stat_member )
db.session.commit()
return
'''
Food统计
'''
def statFood(self,params):
act = params['act']
date = params['date']
date_from = params['date_from']
date_to = params['date_to']
app.logger.info( "act:{0},from:{1},to:{2}".format( act,date_from,date_to ) )
stat_food_list = db.session.query(FoodSaleChangeLog.food_id, func.sum(FoodSaleChangeLog.quantity).label("total_count"),
func.sum(FoodSaleChangeLog.price).label("total_pay_money")) \
.filter(FoodSaleChangeLog.created_time >= date_from, FoodSaleChangeLog.created_time <= date_to)\
.group_by( FoodSaleChangeLog.food_id ).all()
if not stat_food_list:
app.logger.info("no data")
return
for item in stat_food_list:
tmp_food_id = item[ 0 ]
tmp_stat_food = StatDailyFood.query.filter_by(date=date, food_id = tmp_food_id ).first()
if tmp_stat_food:
tmp_model_stat_food = tmp_stat_food
else:
tmp_model_stat_food = StatDailyFood()
tmp_model_stat_food.date = date
tmp_model_stat_food.food_id = tmp_food_id
tmp_model_stat_food.created_time = getCurrentDate()
tmp_model_stat_food.total_count = item[1]
tmp_model_stat_food.total_pay_money = item[2]
tmp_model_stat_food.updated_time = getCurrentDate()
'''
为了测试效果模拟数据
'''
tmp_model_stat_food.total_count = random.randint(50, 100)
tmp_model_stat_food.total_pay_money = random.randint(1000, 1010)
db.session.add( tmp_model_stat_food )
db.session.commit()
return
'''
site统计
'''
def statSite(self,params):
act = params['act']
date = params['date']
date_from = params['date_from']
date_to = params['date_to']
app.logger.info( "act:{0},from:{1},to:{2}".format( act,date_from,date_to ) )
stat_pay = db.session.query(func.sum(PayOrder.total_price).label("total_pay_money")) \
.filter(PayOrder.status == 1) \
.filter(PayOrder.created_time >= date_from, PayOrder.created_time <= date_to).first()
stat_member_count = Member.query.count()
stat_new_member_count = Member.query.filter(Member.created_time >= date_from,
Member.created_time <= date_to).count()
stat_order_count = PayOrder.query.filter_by( status = 1 )\
.filter(PayOrder.created_time >= date_from, PayOrder.created_time <= date_to)\
.count()
stat_share_count = WxShareHistory.query.filter(WxShareHistory.created_time >= date_from
, WxShareHistory.created_time <= date_to).count()
tmp_stat_site = StatDailySite.query.filter_by(date=date).first()
if tmp_stat_site:
tmp_model_stat_site = tmp_stat_site
else:
tmp_model_stat_site = StatDailySite()
tmp_model_stat_site.date = date
tmp_model_stat_site.created_time = getCurrentDate()
tmp_model_stat_site.total_pay_money = stat_pay[ 0 ] if stat_pay[ 0 ] else 0.00
tmp_model_stat_site.total_new_member_count = stat_new_member_count
tmp_model_stat_site.total_member_count = stat_member_count
tmp_model_stat_site.total_order_count = stat_order_count
tmp_model_stat_site.total_shared_count = stat_share_count
tmp_model_stat_site.updated_time = getCurrentDate()
'''
为了测试效果模拟数据
'''
tmp_model_stat_site.total_pay_money = random.randint(1000, 1010)
tmp_model_stat_site.total_new_member_count = random.randint(50, 100)
tmp_model_stat_site.total_member_count += tmp_model_stat_site.total_new_member_count
tmp_model_stat_site.total_order_count = random.randint(900, 1000)
tmp_model_stat_site.total_shared_count = random.randint(1000, 2000)
db.session.add(tmp_model_stat_site)
db.session.commit()
def test(self):
import datetime
from common.libs.Helper import getFormatDate
now = datetime.datetime.now()
for i in reversed( range( 1,30 ) ):
date_before = now + datetime.timedelta( days = -i )
date = getFormatDate( date = date_before,format = "%Y-%m-%d" )
tmp_params = {
'act': 'test',
'date': date,
'date_from': date + " 00:00:00",
'date_to': date + " 23:59:59"
}
self.testFood( date )
self.statFood( tmp_params )
self.statMember( tmp_params )
self.statSite( tmp_params )
def testFood(self,date):
from common.models.food.Food import Food
list = Food.query.all()
if list:
for item in list:
model = FoodSaleChangeLog()
model.food_id = item.id
model.quantity = random.randint( 1,10 )
model.price = model.quantity * item.price
model.member_id = 1
model.created_time = date + " " + getFormatDate( format = "%H:%M:%S")
db.session.add( model )
db.session.commit()

View File

@@ -2,10 +2,14 @@
from application import app,manager
from flask_script import Server
import www
from jobs.launcher import runJob
##web server
manager.add_command( "runserver", Server( host='0.0.0.0',port=app.config['SERVER_PORT'],use_debugger = True ,use_reloader = True) )
#job entrance
manager.add_command('runjob', runJob() )
def main():
manager.run( )

2
mina

Submodule mina updated: fb3fd6da10...2205b70d34

View File

@@ -0,0 +1,172 @@
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request, jsonify,g
from application import app,db
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate
from common.models.member.MemberAddress import MemberAddress
@route_api.route("/my/address/index")
def myAddressList():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
list = MemberAddress.query.filter_by( status = 1, member_id = member_info.id )\
.order_by( MemberAddress.id.desc() ).all()
data_list = []
if list:
for item in list:
tmp_data = {
"id":item.id,
"nickname":item.nickname,
"mobile":item.mobile,
"is_default":item.is_default,
"address":"%s%s%s%s"%( item.province_str,item.city_str,item.area_str,item.address ),
}
data_list.append( tmp_data )
resp['data']['list'] = data_list
return jsonify(resp)
@route_api.route("/my/address/set",methods = [ "POST" ])
def myAddressSet():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
id = int( req['id'] ) if 'id' in req and req['id'] else 0
nickname = req['nickname'] if 'nickname' in req else ''
address = req['address'] if 'address' in req else ''
mobile = req['mobile'] if 'mobile' in req else ''
province_id = int( req['province_id'] ) if ( 'province_id' in req and req['province_id'] ) else 0
province_str = req['province_str'] if 'province_str' in req else ''
city_id = int( req['city_id'] ) if ( 'city_id' in req and req['city_id'])else 0
city_str = req['city_str'] if 'city_str' in req else ''
district_id = int( req['district_id'] ) if ( 'district_id' in req and req['district_id'] ) else 0
district_str = req['district_str'] if 'district_str' in req else ''
member_info = g.member_info
if not nickname:
resp['code'] = -1
resp['msg'] = "请填写联系人姓名~~"
return jsonify(resp)
if not mobile:
resp['code'] = -1
resp['msg'] = "请填写手机号码~~"
return jsonify(resp)
if province_id < 1:
resp['code'] = -1
resp['msg'] = "请选择地区~~"
return jsonify(resp)
if city_id < 1:
resp['code'] = -1
resp['msg'] = "请选择地区~~"
return jsonify(resp)
if district_id < 1:
district_str = ''
if not address:
resp['code'] = -1
resp['msg'] = "请填写详细地址~~"
return jsonify(resp)
if not member_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
address_info = MemberAddress.query.filter_by( id = id,member_id = member_info.id ).first()
if address_info:
model_address = address_info
else:
default_address_count = MemberAddress.query.filter_by( is_default = 1,member_id = member_info.id ,status = 1).count()
model_address = MemberAddress()
model_address.member_id = member_info.id
model_address.is_default = 1 if default_address_count == 0 else 0
model_address.created_time = getCurrentDate()
model_address.nickname = nickname
model_address.mobile = mobile
model_address.address = address
model_address.province_id = province_id
model_address.province_str = province_str
model_address.city_id = city_id
model_address.city_str = city_str
model_address.area_id = district_id
model_address.area_str = district_str
model_address.updated_time = getCurrentDate()
db.session.add(model_address )
db.session.commit()
return jsonify(resp)
@route_api.route("/my/address/info")
def myAddressInfo():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
id = int( req['id'] ) if 'id' in req else 0
member_info = g.member_info
if id < 1 or not member_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
address_info = MemberAddress.query.filter_by( id = id ).first()
if not address_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
resp['data']['info'] = {
"nickname":address_info.nickname,
"mobile":address_info.mobile,
"address":address_info.address,
"province_id":address_info.province_id,
"province_str":address_info.province_str,
"city_id":address_info.city_id,
"city_str":address_info.city_str,
"area_id":address_info.area_id,
"area_str":address_info.area_str
}
return jsonify(resp)
@route_api.route("/my/address/ops",methods = [ "POST" ])
def myAddressOps():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
id = int(req['id']) if 'id' in req else 0
act = req['act'] if 'act' in req else ''
member_info = g.member_info
if id < 1 or not member_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
address_info = MemberAddress.query.filter_by(id=id,member_id = member_info.id).first()
if not address_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
if act == "del":
address_info.status = 0
address_info.updated_time = getCurrentDate()
db.session.add(address_info)
db.session.commit()
elif act == "default":
MemberAddress.query.filter_by( member_id=member_info.id)\
.update({ 'is_default' :0 })
address_info.is_default = 1
address_info.updated_time = getCurrentDate()
db.session.add(address_info)
db.session.commit()
return jsonify(resp)

View File

@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request,jsonify,g
from common.models.food.Food import Food
from common.models.member.MemberCart import MemberCart
from common.libs.member.CartService import CartService
from common.libs.Helper import selectFilterObj,getDictFilterField
from common.libs.UrlManager import UrlManager
from application import app,db
import json
@route_api.route("/cart/index")
def cartIndex():
resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
member_info = g.member_info
if not member_info:
resp['code'] = -1
resp['msg'] = "获取失败,伪登录~~"
return jsonify(resp)
cart_list = MemberCart.query.filter_by( member_id=member_info.id).all()
data_cart_list = []
if cart_list:
food_ids = selectFilterObj( cart_list,"food_id" )
food_map = getDictFilterField( Food,Food.id,"id",food_ids )
for item in cart_list:
tmp_food_info = food_map[ item.food_id ]
tmp_data = {
"id":item.id,
"number":item.quantity,
"food_id": item.food_id,
"name":tmp_food_info.name,
"price":str( tmp_food_info.price ),
"pic_url": UrlManager.buildImageUrl( tmp_food_info.main_image ),
"active":True
}
data_cart_list.append( tmp_data )
resp['data']['list'] = data_cart_list
return jsonify(resp)
@route_api.route("/cart/set", methods=["POST"])
def setCart():
resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
req = request.values
food_id = int(req['id']) if 'id' in req else 0
number = int(req['number']) if 'number' in req else 0
if food_id < 1 or number < 1:
resp['code'] = -1
resp['msg'] = "添加购物车失败-1~~"
return jsonify(resp)
member_info = g.member_info
if not member_info:
resp['code'] = -1
resp['msg'] = "添加购物车失败-2~~"
return jsonify(resp)
food_info = Food.query.filter_by( id = food_id ).first()
if not food_info:
resp['code'] = -1
resp['msg'] = "添加购物车失败-3~~"
return jsonify(resp)
if food_info.stock < number:
resp['code'] = -1
resp['msg'] = "添加购物车失败,库存不足~~"
return jsonify(resp)
ret = CartService.setItems( member_id=member_info.id,food_id = food_info.id,number = number )
if not ret:
resp['code'] = -1
resp['msg'] = "添加购物车失败-4~~"
return jsonify(resp)
return jsonify(resp)
@route_api.route("/cart/del", methods=["POST"])
def delCart():
resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
req = request.values
params_goods = req['goods'] if 'goods' in req else None
items = []
if params_goods:
items = json.loads(params_goods)
if not items or len( items ) < 1:
return jsonify(resp)
member_info = g.member_info
if not member_info:
resp['code'] = -1
resp['msg'] = "删除购物车失败-1~~"
return jsonify(resp)
ret = CartService.deleteItem( member_id = member_info.id, items = items )
if not ret:
resp['code'] = -1
resp['msg'] = "删除购物车失败-2~~"
return jsonify(resp)
return jsonify(resp)

142
web/controllers/api/Food.py Normal file
View File

@@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request,jsonify,g
from common.models.food.FoodCat import FoodCat
from common.models.food.Food import Food
from common.models.member.MemberCart import MemberCart
from common.models.member.MemberComments import MemberComments
from common.models.member.Member import Member
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate,getDictFilterField,selectFilterObj
from application import app,db
from sqlalchemy import or_
@route_api.route("/food/index" )
def foodIndex():
resp = { 'code':200 ,'msg':'操作成功~','data':{} }
cat_list = FoodCat.query.filter_by( status = 1 ).order_by( FoodCat.weight.desc() ).all()
data_cat_list = []
data_cat_list.append({
'id': 0,
'name': "全部"
})
if cat_list:
for item in cat_list:
tmp_data = {
'id':item.id,
'name':item.name
}
data_cat_list.append( tmp_data )
resp['data']['cat_list'] = data_cat_list
food_list = Food.query.filter_by( status = 1 )\
.order_by( Food.total_count.desc(),Food.id.desc() ).limit(3).all()
data_food_list = []
if food_list:
for item in food_list:
tmp_data = {
'id':item.id,
'pic_url':UrlManager.buildImageUrl( item.main_image )
}
data_food_list.append( tmp_data )
resp['data']['banner_list'] = data_food_list
return jsonify( resp )
@route_api.route("/food/search" )
def foodSearch():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
cat_id = int( req['cat_id'] ) if 'cat_id' in req else 0
mix_kw = str(req['mix_kw']) if 'mix_kw' in req else ''
p = int( req['p'] ) if 'p' in req else 1
if p < 1:
p = 1
page_size = 10
offset = ( p - 1 ) * page_size
query = Food.query.filter_by(status=1 )
if cat_id > 0:
query = query.filter_by(cat_id = cat_id)
if mix_kw:
rule = or_(Food.name.ilike("%{0}%".format(mix_kw)), Food.tags.ilike("%{0}%".format(mix_kw)))
query = query.filter(rule)
food_list = query.order_by(Food.total_count.desc(), Food.id.desc())\
.offset( offset ).limit( page_size ).all()
data_food_list = []
if food_list:
for item in food_list:
tmp_data = {
'id': item.id,
'name': "%s"%( item.name ),
'price': str( item.price ),
'min_price':str( item.price ),
'pic_url': UrlManager.buildImageUrl(item.main_image)
}
data_food_list.append(tmp_data)
resp['data']['list'] = data_food_list
resp['data']['has_more'] = 0 if len( data_food_list ) < page_size else 1
return jsonify(resp)
@route_api.route("/food/info" )
def foodInfo():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
id = int(req['id']) if 'id' in req else 0
food_info = Food.query.filter_by( id = id ).first()
if not food_info or not food_info.status :
resp['code'] = -1
resp['msg'] = "美食已下架"
return jsonify(resp)
member_info = g.member_info
cart_number = 0
if member_info:
cart_number = MemberCart.query.filter_by( member_id = member_info.id ).count()
resp['data']['info'] = {
"id":food_info.id,
"name":food_info.name,
"summary":food_info.summary,
"total_count":food_info.total_count,
"comment_count":food_info.comment_count,
'main_image':UrlManager.buildImageUrl( food_info.main_image ),
"price":str( food_info.price ),
"stock":food_info.stock,
"pics":[ UrlManager.buildImageUrl( food_info.main_image ) ]
}
resp['data']['cart_number'] = cart_number
return jsonify(resp)
@route_api.route("/food/comments")
def foodComments():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
id = int(req['id']) if 'id' in req else 0
query = MemberComments.query.filter( MemberComments.food_ids.ilike("%_{0}_%".format(id)) )
list = query.order_by( MemberComments.id.desc() ).limit(5).all()
data_list = []
if list:
member_map = getDictFilterField( Member,Member.id,"id",selectFilterObj( list,"member_id" ) )
for item in list:
if item.member_id not in member_map:
continue
tmp_member_info = member_map[ item.member_id ]
tmp_data = {
'score':item.score_desc,
'date': item.created_time.strftime("%Y-%m-%d %H:%M:%S"),
"content":item.content,
"user":{
'nickname':tmp_member_info.nickname,
'avatar_url':tmp_member_info.avatar,
}
}
data_list.append( tmp_data )
resp['data']['list'] = data_list
resp['data']['count'] = query.count()
return jsonify(resp)

View File

@@ -1,36 +1,38 @@
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request,jsonify
from application import app,db
from flask import request,jsonify,g
from application import app,db
import requests,json
from common.models.member.Member import Member
from common.models.member.Oauth_member_bind import OauthMemberBind
from common.models.member.OauthMemberBind import OauthMemberBind
from common.models.food.WxShareHistory import WxShareHistory
from common.libs.Helper import getCurrentDate
from common.libs.member.MemberService import MemberService
@route_api.route("/member/login",methods = [ "GET","POST" ])
def login():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
resp = { 'code':200 ,'msg':'操作成功~','data':{} }
req = request.values
code = req['code'] if 'code' in req else ''
app.logger.info(code)
if not code or len(code) < 1:
if not code or len( code ) < 1:
resp['code'] = -1
resp['msg'] = "需要code"
return jsonify(resp)
openid = MemberService.getWeChatOpenId(code)
openid = MemberService.getWeChatOpenId( code )
if openid is None:
resp['code'] = -1
resp['msg'] = "调用微信出错"
return jsonify(resp)
nickname = req['nickName'] if 'nickName' in req else ''
sex = req['gender'] if 'gender' in req else 0
avatar = req['avatarUrl'] if 'avatarUrl' in req else ''
'''
判断是否已经测试过,注册了直接返回一些信息
'''
bind_info = OauthMemberBind.query.filter_by(openid=openid, type=1).first()
bind_info = OauthMemberBind.query.filter_by( openid = openid,type = 1 ).first()
if not bind_info:
model_member = Member()
model_member.nickname = nickname
@@ -51,10 +53,11 @@ def login():
db.session.commit()
bind_info = model_bind
member_info = Member.query.filter_by(id=bind_info.member_id).first()
member_info = Member.query.filter_by(id = bind_info.member_id).first()
token = "%s#%s" % (MemberService.geneAuthCode(member_info), member_info.id)
resp['data'] = {'token': token}
return jsonify(resp)
return jsonify( resp )
@route_api.route("/member/check-reg",methods = [ "GET","POST" ])
@@ -87,4 +90,30 @@ def checkReg():
token = "%s#%s"%( MemberService.geneAuthCode( member_info ),member_info.id )
resp['data'] = { 'token':token }
return jsonify(resp)
@route_api.route("/member/share",methods = [ "POST" ])
def memberShare():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
url = req['url'] if 'url' in req else ''
member_info = g.member_info
model_share = WxShareHistory()
if member_info:
model_share.member_id = member_info.id
model_share.share_url = url
model_share.created_time = getCurrentDate()
db.session.add(model_share)
db.session.commit()
return jsonify(resp)
@route_api.route("/member/info")
def memberInfo():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
resp['data']['info'] = {
"nickname":member_info.nickname,
"avatar_url":member_info.avatar
}
return jsonify(resp)

179
web/controllers/api/My.py Normal file
View File

@@ -0,0 +1,179 @@
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request, jsonify,g
from common.models.food.Food import Food
from application import app,db
from common.models.pay.PayOrder import PayOrder
from common.models.pay.PayOrderItem import PayOrderItem
from common.libs.UrlManager import UrlManager
from common.libs.Helper import selectFilterObj,getDictFilterField,getCurrentDate
from common.models.member.MemberComments import MemberComments
import json,datetime
@route_api.route("/my/order")
def myOrderList():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
req = request.values
status = int( req['status'] ) if 'status' in req else 0
query = PayOrder.query.filter_by( member_id = member_info.id )
if status == -8 :#等待付款
query = query.filter( PayOrder.status == -8 )
elif status == -7:#待发货
query = query.filter( PayOrder.status == 1,PayOrder.express_status == -7,PayOrder.comment_status == 0 )
elif status == -6:#待确认
query = query.filter(PayOrder.status == 1, PayOrder.express_status == -6,PayOrder.comment_status == 0)
elif status == -5:#待评价
query = query.filter(PayOrder.status == 1, PayOrder.express_status == 1,PayOrder.comment_status == 0)
elif status == 1:#已完成
query = query.filter(PayOrder.status == 1, PayOrder.express_status == 1,PayOrder.comment_status == 1 )
else:
query = query.filter( PayOrder.status == 0 )
pay_order_list = query.order_by( PayOrder.id.desc() ).all()
data_pay_order_list = []
if pay_order_list:
pay_order_ids = selectFilterObj( pay_order_list,"id" )
pay_order_item_list = PayOrderItem.query.filter( PayOrderItem.pay_order_id.in_( pay_order_ids ) ).all()
food_ids = selectFilterObj( pay_order_item_list,"food_id" )
food_map = getDictFilterField( Food,Food.id,"id",food_ids )
pay_order_item_map = {}
if pay_order_item_list:
for item in pay_order_item_list:
if item.pay_order_id not in pay_order_item_map:
pay_order_item_map[ item.pay_order_id ] = []
tmp_food_info = food_map[ item.food_id ]
pay_order_item_map[item.pay_order_id].append({
'id':item.id,
'food_id':item.food_id,
'quantity':item.quantity,
'price':str( item.price ),
'pic_url':UrlManager.buildImageUrl( tmp_food_info.main_image ),
'name':tmp_food_info.name
})
for item in pay_order_list:
tmp_data = {
'status':item.pay_status,
'status_desc':item.status_desc,
'date':item.created_time.strftime("%Y-%m-%d %H:%M:%S"),
'order_number':item.order_number,
'order_sn':item.order_sn,
'note':item.note,
'total_price':str( item.total_price ),
'goods_list':pay_order_item_map[ item.id ]
}
data_pay_order_list.append( tmp_data )
resp['data']['pay_order_list'] = data_pay_order_list
return jsonify(resp)
@route_api.route("/my/order/info")
def myOrderInfo():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
req = request.values
order_sn = req['order_sn'] if 'order_sn' in req else ''
pay_order_info = PayOrder.query.filter_by( member_id=member_info.id ,order_sn = order_sn).first()
if not pay_order_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
express_info = {}
if pay_order_info.express_info:
express_info = json.loads( pay_order_info.express_info )
tmp_deadline = pay_order_info.created_time + datetime.timedelta(minutes=30)
info = {
"order_sn":pay_order_info.order_sn,
"status":pay_order_info.pay_status,
"status_desc":pay_order_info.status_desc,
"pay_price":str( pay_order_info.pay_price),
"yun_price":str( pay_order_info.yun_price),
"total_price":str( pay_order_info.total_price),
"address":express_info,
"goods": [],
"deadline":tmp_deadline.strftime("%Y-%m-%d %H:%M")
}
pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_info.id ).all()
if pay_order_items:
food_ids = selectFilterObj( pay_order_items , "food_id")
food_map = getDictFilterField(Food, Food.id, "id", food_ids)
for item in pay_order_items:
tmp_food_info = food_map[item.food_id]
tmp_data = {
"name": tmp_food_info.name,
"price": str( item.price ),
"unit": item.quantity,
"pic_url": UrlManager.buildImageUrl( tmp_food_info.main_image ),
}
info['goods'].append( tmp_data )
resp['data']['info'] = info
return jsonify(resp)
@route_api.route("/my/comment/add",methods = [ "POST" ])
def myCommentAdd():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
req = request.values
order_sn = req['order_sn'] if 'order_sn' in req else ''
score = req['score'] if 'score' in req else 10
content = req['content'] if 'content' in req else ''
pay_order_info = PayOrder.query.filter_by( member_id=member_info.id ,order_sn = order_sn).first()
if not pay_order_info:
resp['code'] = -1
resp['msg'] = "系统繁忙,请稍后再试~~"
return jsonify(resp)
if pay_order_info.comment_status:
resp['code'] = -1
resp['msg'] = "已经评价过了~~"
return jsonify(resp)
pay_order_items = PayOrderItem.query.filter_by( pay_order_id = pay_order_info.id ).all()
food_ids = selectFilterObj( pay_order_items,"food_id" )
tmp_food_ids_str = '_'.join(str(s) for s in food_ids if s not in [None])
model_comment = MemberComments()
model_comment.food_ids = "_%s_"%tmp_food_ids_str
model_comment.member_id = member_info.id
model_comment.pay_order_id = pay_order_info.id
model_comment.score = score
model_comment.content = content
db.session.add( model_comment )
pay_order_info.comment_status = 1
pay_order_info.updated_time = getCurrentDate()
db.session.add( pay_order_info )
db.session.commit()
return jsonify(resp)
@route_api.route("/my/comment/list" )
def myCommentList():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
comment_list = MemberComments.query.filter_by( member_id=member_info.id )\
.order_by(MemberComments.id.desc()).all()
data_comment_list = []
if comment_list:
pay_order_ids = selectFilterObj( comment_list,"pay_order_id" )
pay_order_map = getDictFilterField( PayOrder,PayOrder.id,"id",pay_order_ids )
for item in comment_list:
tmp_pay_order_info = pay_order_map[ item.pay_order_id ]
tmp_data = {
"date":item.created_time.strftime("%Y-%m-%d %H:%M:%S"),
"content":item.content,
"order_number":tmp_pay_order_info.order_number
}
data_comment_list.append( tmp_data )
resp['data']['list'] = data_comment_list
return jsonify(resp)

View File

@@ -0,0 +1,223 @@
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from flask import request, jsonify,g
from application import app, db
import json, decimal
from common.models.food.Food import Food
from common.models.pay.PayOrder import PayOrder
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate
from common.libs.pay.PayService import PayService
from common.libs.pay.WeChatService import WeChatService
from common.libs.member.CartService import CartService
from common.models.member.MemberAddress import MemberAddress
from common.models.member.OauthMemberBind import OauthMemberBind
@route_api.route("/order/info", methods=[ "POST" ])
def orderInfo():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
params_goods = req['goods'] if 'goods' in req else None
member_info = g.member_info
params_goods_list = []
if params_goods:
params_goods_list = json.loads(params_goods)
food_dic = {}
for item in params_goods_list:
food_dic[item['id']] = item['number']
food_ids = food_dic.keys()
food_list = Food.query.filter(Food.id.in_(food_ids)).all()
data_food_list = []
yun_price = pay_price = decimal.Decimal(0.00)
if food_list:
for item in food_list:
tmp_data = {
"id": item.id,
"name": item.name,
"price": str(item.price),
'pic_url': UrlManager.buildImageUrl(item.main_image),
'number': food_dic[item.id]
}
pay_price = pay_price + item.price * int( food_dic[item.id] )
data_food_list.append(tmp_data)
# 获取地址
address_info = MemberAddress.query.filter_by( is_default = 1,member_id = member_info.id,status = 1 ).first()
default_address = ''
if address_info:
default_address = {
"id": address_info.id,
"name": address_info.nickname,
"mobile": address_info.mobile,
"address":"%s%s%s%s"%( address_info.province_str,address_info.city_str,address_info.area_str,address_info.address )
}
resp['data']['food_list'] = data_food_list
resp['data']['pay_price'] = str(pay_price)
resp['data']['yun_price'] = str(yun_price)
resp['data']['total_price'] = str(pay_price + yun_price)
resp['data']['default_address'] = default_address
return jsonify(resp)
@route_api.route("/order/create", methods=[ "POST"])
def orderCreate():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
type = req['type'] if 'type' in req else ''
note = req['note'] if 'note' in req else ''
express_address_id = int( req['express_address_id'] ) if 'express_address_id' in req and req['express_address_id'] else 0
params_goods = req['goods'] if 'goods' in req else None
items = []
if params_goods:
items = json.loads(params_goods)
if len( items ) < 1:
resp['code'] = -1
resp['msg'] = "下单失败:没有选择商品~~"
return jsonify(resp)
address_info = MemberAddress.query.filter_by( id = express_address_id ).first()
if not address_info or not address_info.status:
resp['code'] = -1
resp['msg'] = "下单失败:快递地址不对~~"
return jsonify(resp)
member_info = g.member_info
target = PayService()
params = {
"note":note,
'express_address_id':address_info.id,
'express_info':{
'mobile':address_info.mobile,
'nickname':address_info.nickname,
"address":"%s%s%s%s"%( address_info.province_str,address_info.city_str,address_info.area_str,address_info.address )
}
}
resp = target.createOrder( member_info.id ,items ,params)
#如果是来源购物车的,下单成功将下单的商品去掉
if resp['code'] == 200 and type == "cart":
CartService.deleteItem( member_info.id,items )
return jsonify( resp )
@route_api.route("/order/pay", methods=[ "POST"])
def orderPay():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
member_info = g.member_info
req = request.values
order_sn = req['order_sn'] if 'order_sn' in req else ''
pay_order_info = PayOrder.query.filter_by( order_sn = order_sn,member_id = member_info.id ).first()
if not pay_order_info:
resp['code'] = -1
resp['msg'] = "系统繁忙。请稍后再试~~"
return jsonify(resp)
oauth_bind_info = OauthMemberBind.query.filter_by( member_id = member_info.id ).first()
if not oauth_bind_info:
resp['code'] = -1
resp['msg'] = "系统繁忙。请稍后再试~~"
return jsonify(resp)
config_mina = app.config['MINA_APP']
notify_url = app.config['APP']['domain'] + config_mina['callback_url']
target_wechat = WeChatService( merchant_key=config_mina['paykey'] )
data = {
'appid': config_mina['appid'],
'mch_id': config_mina['mch_id'],
'nonce_str': target_wechat.get_nonce_str(),
'body': '订餐', # 商品描述
'out_trade_no': pay_order_info.order_sn, # 商户订单号
'total_fee': int( pay_order_info.total_price * 100 ),
'notify_url': notify_url,
'trade_type': "JSAPI",
'openid': oauth_bind_info.openid
}
pay_info = target_wechat.get_pay_info( pay_data=data)
#保存prepay_id为了后面发模板消息
pay_order_info.prepay_id = pay_info['prepay_id']
db.session.add( pay_order_info )
db.session.commit()
resp['data']['pay_info'] = pay_info
return jsonify(resp)
@route_api.route("/order/callback", methods=[ "POST"])
def orderCallback():
result_data = {
'return_code': 'SUCCESS',
'return_msg': 'OK'
}
header = {'Content-Type': 'application/xml'}
config_mina = app.config['MINA_APP']
target_wechat = WeChatService(merchant_key=config_mina['paykey'])
callback_data = target_wechat.xml_to_dict( request.data )
app.logger.info( callback_data )
sign = callback_data['sign']
callback_data.pop( 'sign' )
gene_sign = target_wechat.create_sign( callback_data )
app.logger.info(gene_sign)
if sign != gene_sign:
result_data['return_code'] = result_data['return_msg'] = 'FAIL'
return target_wechat.dict_to_xml(result_data), header
if callback_data['result_code'] != 'SUCCESS':
result_data['return_code'] = result_data['return_msg'] = 'FAIL'
return target_wechat.dict_to_xml(result_data), header
order_sn = callback_data['out_trade_no']
pay_order_info = PayOrder.query.filter_by(order_sn=order_sn).first()
if not pay_order_info:
result_data['return_code'] = result_data['return_msg'] = 'FAIL'
return target_wechat.dict_to_xml(result_data), header
if int( pay_order_info.total_price * 100 ) != int( callback_data['total_fee'] ):
result_data['return_code'] = result_data['return_msg'] = 'FAIL'
return target_wechat.dict_to_xml(result_data), header
if pay_order_info.status == 1:
return target_wechat.dict_to_xml(result_data), header
target_pay = PayService()
target_pay.orderSuccess( pay_order_id = pay_order_info.id,params = { "pay_sn":callback_data['transaction_id'] } )
target_pay.addPayCallbackData( pay_order_id = pay_order_info.id, data = request.data)
return target_wechat.dict_to_xml(result_data), header
@route_api.route("/order/ops", methods=[ "POST"])
def orderOps():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
member_info = g.member_info
order_sn = req['order_sn'] if 'order_sn' in req else ''
act = req['act'] if 'act' in req else ''
pay_order_info = PayOrder.query.filter_by(order_sn=order_sn, member_id=member_info.id).first()
if not pay_order_info:
resp['code'] = -1
resp['msg'] = "系统繁忙。请稍后再试~~"
return jsonify(resp)
if act == "cancel":
target_pay = PayService( )
ret = target_pay.closeOrder( pay_order_id=pay_order_info.id )
if not ret:
resp['code'] = -1
resp['msg'] = "系统繁忙。请稍后再试~~"
return jsonify(resp)
elif act == "confirm":
pay_order_info.express_status = 1
pay_order_info.updated_time = getCurrentDate()
db.session.add( pay_order_info )
db.session.commit()
return jsonify(resp)

View File

@@ -1,7 +1,12 @@
# -*- coding: utf-8 -*-
from flask import Blueprint
route_api = Blueprint('api_page',__name__ )
route_api = Blueprint( 'api_page',__name__ )
from web.controllers.api.Member import *
from web.controllers.api.Food import *
from web.controllers.api.Order import *
from web.controllers.api.My import *
from web.controllers.api.Cart import *
from web.controllers.api.Address import *
@route_api.route("/")
def index():

103
web/controllers/chart.py Normal file
View File

@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
from application import app,db
from flask import Blueprint,jsonify
from common.libs.Helper import ops_render
from common.libs.Helper import getFormatDate
from common.models.stat.StatDailySite import StatDailySite
import datetime
route_chart = Blueprint( 'chart_page',__name__ )
@route_chart.route("/dashboard")
def dashboard():
now = datetime.datetime.now()
date_before_30days = now + datetime.timedelta(days=-30)
date_from = getFormatDate(date=date_before_30days, format="%Y-%m-%d")
date_to = getFormatDate(date=now, format="%Y-%m-%d")
list = StatDailySite.query.filter(StatDailySite.date >= date_from) \
.filter(StatDailySite.date <= date_to).order_by(StatDailySite.id.asc()) \
.all()
resp = {'code': 200, 'msg': '操作成功~~', 'data': {}}
data = {
"categories":[],
"series":[
{
"name":"会员总数",
"data":[]
},
{
"name": "订单总数",
"data": []
},
]
}
if list:
for item in list:
data['categories'].append( getFormatDate( date = item.date ,format = "%Y-%m-%d") )
data['series'][0]['data'].append( item.total_member_count )
data['series'][1]['data'].append( item.total_order_count )
resp['data'] = data
return jsonify(resp)
@route_chart.route("/finance")
def finance():
now = datetime.datetime.now()
date_before_30days = now + datetime.timedelta(days=-30)
date_from = getFormatDate(date=date_before_30days, format="%Y-%m-%d")
date_to = getFormatDate(date=now, format="%Y-%m-%d")
list = StatDailySite.query.filter(StatDailySite.date >= date_from) \
.filter(StatDailySite.date <= date_to).order_by(StatDailySite.id.asc()) \
.all()
resp = {'code': 200, 'msg': '操作成功~~', 'data': {}}
data = {
"categories":[],
"series":[
{
"name":"日营收报表",
"data":[]
}
]
}
if list:
for item in list:
data['categories'].append( getFormatDate( date = item.date ,format = "%Y-%m-%d") )
data['series'][0]['data'].append( float( item.total_pay_money ) )
resp['data'] = data
return jsonify(resp)
@route_chart.route("/share")
def share():
now = datetime.datetime.now()
date_before_30days = now + datetime.timedelta(days=-30)
date_from = getFormatDate(date=date_before_30days, format="%Y-%m-%d")
date_to = getFormatDate(date=now, format="%Y-%m-%d")
list = StatDailySite.query.filter(StatDailySite.date >= date_from) \
.filter(StatDailySite.date <= date_to).order_by(StatDailySite.id.asc()) \
.all()
resp = {'code': 200, 'msg': '操作成功~~', 'data': {}}
data = {
"categories":[],
"series":[
{
"name":"日分享",
"data":[]
}
]
}
if list:
for item in list:
data['categories'].append( getFormatDate( date = item.date ,format = "%Y-%m-%d") )
data['series'][0]['data'].append( item.total_shared_count )
resp['data'] = data
return jsonify(resp)

View File

@@ -1,17 +1,174 @@
# -*- coding: utf-8 -*-
from flask import Blueprint
from flask import Blueprint,request,redirect,jsonify
from common.libs.Helper import ops_render
from common.models.member.Member import Member
from common.models.food.Food import Food
from common.models.pay.PayOrder import PayOrder
from common.models.pay.PayOrderItem import PayOrderItem
from application import app,db
from common.libs.UrlManager import UrlManager
from common.libs.Helper import iPagination,selectFilterObj,getDictListFilterField,getDictFilterField,getCurrentDate
from sqlalchemy import func
import json
route_finance = Blueprint( 'finance_page',__name__ )
@route_finance.route( "/index" )
def index():
return ops_render( "finance/index.html" )
resp_data = {}
req = request.values
page = int(req['p']) if ('p' in req and req['p']) else 1
query = PayOrder.query
if 'status' in req and int( req['status'] ) > -1 :
query = query.filter( PayOrder.status == int( req['status'] ) )
page_params = {
'total': query.count(),
'page_size': app.config['PAGE_SIZE'],
'page': page,
'display': app.config['PAGE_DISPLAY'],
'url': request.full_path.replace("&p={}".format(page), "")
}
pages = iPagination(page_params)
offset = (page - 1) * app.config['PAGE_SIZE']
pay_list = query.order_by(PayOrder.id.desc()).offset(offset).limit(app.config['PAGE_SIZE']).all()
data_list = []
if pay_list:
pay_order_ids = selectFilterObj( pay_list,"id" )
pay_order_items_map = getDictListFilterField( PayOrderItem,PayOrderItem.pay_order_id,"pay_order_id", pay_order_ids )
food_mapping = {}
if pay_order_items_map:
food_ids = []
for item in pay_order_items_map:
tmp_food_ids = selectFilterObj( pay_order_items_map[ item ],"food_id" )
tmp_food_ids = {}.fromkeys(tmp_food_ids).keys()
food_ids = food_ids + list( tmp_food_ids )
#food_ids里面会有重复的要去重
food_mapping = getDictFilterField( Food,Food.id,"id", food_ids )
for item in pay_list:
tmp_data = {
"id":item.id,
"status_desc":item.status_desc,
"order_number":item.order_number,
"price":item.total_price,
"pay_time":item.pay_time,
"created_time":item.created_time.strftime("%Y%m%d%H%M%S")
}
tmp_foods = []
tmp_order_items = pay_order_items_map[ item.id ]
for tmp_order_item in tmp_order_items:
tmp_food_info = food_mapping[ tmp_order_item.food_id ]
tmp_foods.append( {
'name':tmp_food_info.name,
'quantity':tmp_order_item.quantity
} )
tmp_data['foods'] = tmp_foods
data_list.append( tmp_data )
resp_data['list'] = data_list
resp_data['pages'] = pages
resp_data['search_con'] = req
resp_data['pay_status_mapping'] = app.config['PAY_STATUS_MAPPING']
resp_data['current'] = 'index'
return ops_render( "finance/index.html",resp_data )
@route_finance.route( "/pay-info" )
def payInfo():
return ops_render( "finance/pay_info.html" )
def info():
resp_data = {}
req = request.values
id = int(req['id']) if 'id' in req else 0
reback_url = UrlManager.buildUrl("/finance/index")
if id < 1:
return redirect( reback_url )
pay_order_info = PayOrder.query.filter_by( id = id ).first()
if not pay_order_info:
return redirect(reback_url)
member_info = Member.query.filter_by( id = pay_order_info.member_id ).first()
if not member_info:
return redirect(reback_url)
order_item_list = PayOrderItem.query.filter_by( pay_order_id = pay_order_info.id ).all()
data_order_item_list = []
if order_item_list:
food_map = getDictFilterField(Food, Food.id, "id", selectFilterObj(order_item_list, "food_id"))
for item in order_item_list:
tmp_food_info = food_map[ item.food_id ]
tmp_data = {
"quantity":item.quantity,
"price":item.price,
"name":tmp_food_info.name
}
data_order_item_list.append( tmp_data )
address_info = {}
if pay_order_info.express_info:
address_info = json.loads(pay_order_info.express_info)
resp_data['pay_order_info'] = pay_order_info
resp_data['pay_order_items'] = data_order_item_list
resp_data['member_info'] = member_info
resp_data['address_info'] = address_info
resp_data['current'] = 'index'
return ops_render( "finance/pay_info.html",resp_data )
@route_finance.route( "/account" )
def account():
return ops_render( "finance/account.html" )
def set():
resp_data = {}
req = request.values
page = int(req['p']) if ('p' in req and req['p']) else 1
query = PayOrder.query.filter_by( status = 1 )
page_params = {
'total': query.count(),
'page_size': app.config['PAGE_SIZE'],
'page': page,
'display': app.config['PAGE_DISPLAY'],
'url': request.full_path.replace("&p={}".format(page), "")
}
pages = iPagination(page_params)
offset = (page - 1) * app.config['PAGE_SIZE']
list = query.order_by(PayOrder.id.desc()).offset(offset).limit(app.config['PAGE_SIZE']).all()
stat_info = db.session.query( PayOrder,func.sum( PayOrder.total_price ).label("total") )\
.filter( PayOrder.status == 1 ).first()
app.logger.info ( stat_info )
resp_data['list'] = list
resp_data['pages'] = pages
resp_data['total_money'] = stat_info[ 1 ] if stat_info[ 1 ] else 0.00
resp_data['current'] = 'account'
return ops_render( "finance/account.html",resp_data )
@route_finance.route("/ops", methods=[ "POST"])
def orderOps():
resp = {'code': 200, 'msg': '操作成功~', 'data': {}}
req = request.values
id = req['id'] if 'id' in req else 0
act = req['act'] if 'act' in req else ''
pay_order_info = PayOrder.query.filter_by( id = id ).first()
if not pay_order_info:
resp['code'] = -1
resp['msg'] = "系统繁忙。请稍后再试~~"
return jsonify(resp)
if act == "express":
pay_order_info.express_status = -6
pay_order_info.updated_time = getCurrentDate()
db.session.add( pay_order_info )
db.session.commit()
return jsonify(resp)

View File

@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
from flask import Blueprint,request,jsonify,redirect
from common.libs.Helper import ops_render,getCurrentDate,iPagination,getDictFilterField
from application import app,db
from common.models.food.Food import Food
from common.libs.Helper import ops_render
from common.models.food.FoodCat import FoodCat
from application import app,db
from common.libs.Helper import getCurrentDate,iPagination,getDictFilterField
from common.libs.food.FoodService import FoodService
from common.models.food.FoodStockChangeLog import FoodStockChangeLog
from common.libs.UrlManager import UrlManager
from common.libs.food.FoodService import FoodService
from decimal import Decimal
from sqlalchemy import or_
route_food = Blueprint( 'food_page',__name__ )
@@ -48,10 +48,27 @@ def index():
resp_data['current'] = 'index'
return ops_render( "food/index.html",resp_data )
@route_food.route( "/info" )
def info():
return ops_render( "food/info.html" )
resp_data = {}
req = request.args
id = int(req.get("id", 0))
reback_url = UrlManager.buildUrl("/food/index")
if id < 1:
return redirect( reback_url )
info = Food.query.filter_by( id =id ).first()
if not info:
return redirect( reback_url )
stock_change_list = FoodStockChangeLog.query.filter( FoodStockChangeLog.food_id == id )\
.order_by( FoodStockChangeLog.id.desc() ).all()
resp_data['info'] = info
resp_data['stock_change_list'] = stock_change_list
resp_data['current'] = 'index'
return ops_render( "food/info.html",resp_data )
@route_food.route( "/set" ,methods = [ 'GET','POST'] )
@@ -59,16 +76,16 @@ def set():
if request.method == "GET":
resp_data = {}
req = request.args
id = int(req.get('id', 0))
info = Food.query.filter_by(id=id).first()
id = int( req.get('id',0) )
info = Food.query.filter_by( id = id ).first()
if info and info.status != 1:
return redirect(UrlManager.buildUrl("/food/index"))
return redirect( UrlManager.buildUrl("/food/index") )
cat_list = FoodCat.query.all()
resp_data['info'] = info
resp_data['cat_list'] = cat_list
resp_data['current'] = 'index'
return ops_render("food/set.html", resp_data)
return ops_render( "food/set.html" ,resp_data)
resp = {'code': 200, 'msg': '操作成功~~', 'data': {}}
req = request.values
@@ -121,6 +138,9 @@ def set():
resp['code'] = -1
resp['msg'] = "请输入标签,便于搜索~~"
return jsonify(resp)
food_info = Food.query.filter_by(id=id).first()
before_stock = 0
if food_info:
@@ -143,7 +163,7 @@ def set():
db.session.add(model_food)
ret = db.session.commit()
FoodService.setStockChangeLog(model_food.id, int(stock) - int(before_stock), "后台修改")
FoodService.setStockChangeLog( model_food.id,int(stock) - int(before_stock),"后台修改" )
return jsonify(resp)
@@ -163,7 +183,6 @@ def cat():
resp_data['current'] = 'cat'
return ops_render( "food/cat.html",resp_data )
@route_food.route( "/cat-set",methods = [ "GET","POST" ] )
def catSet():
if request.method == "GET":
@@ -202,7 +221,6 @@ def catSet():
db.session.commit()
return jsonify( resp )
@route_food.route("/cat-ops",methods = [ "POST" ])
def catOps():
resp = {'code': 200, 'msg': '操作成功~~', 'data': {}}
@@ -235,3 +253,38 @@ def catOps():
db.session.add( food_cat_info )
db.session.commit()
return jsonify(resp)
@route_food.route("/ops",methods=["POST"])
def ops():
resp = { 'code':200,'msg':'操作成功~~','data':{} }
req = request.values
id = req['id'] if 'id' in req else 0
act = req['act'] if 'act' in req else ''
if not id :
resp['code'] = -1
resp['msg'] = "请选择要操作的账号~~"
return jsonify(resp)
if act not in [ 'remove','recover' ]:
resp['code'] = -1
resp['msg'] = "操作有误,请重试~~"
return jsonify(resp)
food_info = Food.query.filter_by( id = id ).first()
if not food_info:
resp['code'] = -1
resp['msg'] = "指定美食不存在~~"
return jsonify(resp)
if act == "remove":
food_info.status = 0
elif act == "recover":
food_info.status = 1
food_info.updated_time = getCurrentDate()
db.session.add(food_info)
db.session.commit()
return jsonify( resp )

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
from application import app
from flask import request,g,jsonify
from common.models.member.Member import Member
from common.libs.member.MemberService import MemberService
import re
'''
api认证
'''
@app.before_request
def before_request_api():
api_ignore_urls = app.config['API_IGNORE_URLS']
path = request.path
if '/api' not in path:
return
member_info = check_member_login()
g.member_info = None
if member_info:
g.member_info = member_info
pattern = re.compile('%s' % "|".join( api_ignore_urls ))
if pattern.match(path):
return
if not member_info :
resp = {'code': -1, 'msg': '未登录~', 'data': {}}
return jsonify(resp)
return
'''
判断用户是否已经登录
'''
def check_member_login():
auth_cookie = request.headers.get("Authorization")
if auth_cookie is None:
return False
auth_info = auth_cookie.split("#")
if len(auth_info) != 2:
return False
try:
member_info = Member.query.filter_by(id=auth_info[1]).first()
except Exception:
return False
if member_info is None:
return False
if auth_info[0] != MemberService.geneAuthCode( member_info ):
return False
if member_info.status != 1:
return False
return member_info

View File

@@ -0,0 +1,16 @@
;
var finance_index_ops = {
init:function(){
this.eventBind();
},
eventBind:function(){
var that = this;
$(".wrap_search select[name=status]").change( function(){
$(".wrap_search").submit();
});
}
};
$(document).ready( function(){
finance_index_ops.init();
});

View File

@@ -0,0 +1,40 @@
;
var finance_pay_info_ops = {
init:function(){
this.eventBind();
},
eventBind:function(){
$(".express_send").click(function(){
var data_id = $(this).attr("data");
var callback = {
'ok':function(){
$.ajax({
url:common_ops.buildUrl( "/finance/ops" ),
type:'POST',
data:{
act:"express",
id:data_id
},
dataType:'json',
success:function( res ){
var callback = null;
if( res.code == 200 ){
callback = function(){
window.location.href = window.location.href;
}
}
common_ops.alert( res.msg,callback );
}
});
},
'cancel':null
};
common_ops.confirm( "确定已发货了?", callback );
});
}
};
$(document).ready( function(){
finance_pay_info_ops.init();
});

View File

@@ -56,8 +56,7 @@
<div class="row border-bottom">
<nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">
<div class="navbar-header">
<a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="javascript:void(0);"><i
class="fa fa-bars"></i> </a>
<a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="javascript:void(0);"><i class="fa fa-bars"></i> </a>
</div>
<ul class="nav navbar-top-links navbar-right">
<li>
@@ -67,20 +66,18 @@
</li>
<li class="dropdown user_info">
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0);">
<img alt="image" class="img-circle"
src="{{ buildStaticUrl('/images/common/avatar.png') }}"/>
<img alt="image" class="img-circle" src="{{ buildStaticUrl('/images/common/avatar.png') }}"/>
</a>
<ul class="dropdown-menu dropdown-messages">
<li>
<div class="dropdown-messages-box">
姓名:{{current_user.nickname}} <a href="{{ buildUrl('/user/edit') }}"
class="pull-right">编辑</a>
姓名:{{ current_user.nickname }} <a href="{{ buildUrl('/user/edit') }}" class="pull-right">编辑</a>
</div>
</li>
<li class="divider"></li>
<li>
<div class="dropdown-messages-box">
手机号码:{{ current_user.mobile}}
手机号码:{{ current_user.mobile }}
</div>
</li>
<li class="divider"></li>
@@ -108,7 +105,6 @@
<input name="domain" value="{{ config.APP.domain }}">
<input name="prefix_url" value="{{ config.UPLOAD.prefix_url }}">
</div>
<script src="{{ buildStaticUrl('/plugins/jquery-2.1.1.js') }}"></script>
<script src="{{ buildStaticUrl('/bootstrap/bootstrap.min.js') }}"></script>
<script src="{{ buildStaticUrl('/plugins/layer/layer.js') }}"></script>

View File

@@ -0,0 +1,14 @@
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li {% if current == "index" %} class="current" {% endif %}>
<a href="{{ buildUrl('/finance/index') }}">订单列表</a>
</li>
<li {% if current == "account" %} class="current" {% endif %}>
<a href="{{ buildUrl('/finance/account') }}">财务流水</a>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li {% if current == "index" %} class="current" {% endif %}>
<a href="{{ buildUrl('/member/index') }}">会员列表</a>
</li>
<li {% if current == "comment" %} class="current" {% endif %}>
<a href="{{ buildUrl('/member/comment') }}">会员评论</a>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,20 @@
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li {% if current == "index" %} class="current" {% endif %}>
<a href="{{ buildUrl('/stat/index') }}">财务统计</a>
</li>
<li {% if current == "food" %} class="current" {% endif %}>
<a href="{{ buildUrl('/stat/food') }}">售卖统计</a>
</li>
<li {% if current == "member" %} class="current" {% endif %}>
<a href="{{ buildUrl('/stat/member') }}">会员消费统计</a>
</li>
<li {% if current == "share" %} class="current" {% endif %}>
<a href="{{ buildUrl('/stat/share') }}">分享统计</a>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -1,22 +1,9 @@
{% extends "common/layout_main.html" %}
{% block content %}
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li>
<a href="{{ buildUrl('/finance/index') }}">订单列表</a>
</li>
<li class="current">
<a href="{{ buildUrl('/finance/account') }}">财务流水</a>
</li>
</ul>
</div>
</div>
</div>
{% include "common/tab_finance.html" %}
<div class="row">
<div class="col-lg-12 m-t">
<p>总收款金额:5.35</p>
<p>总收款金额:{{ total_money }}</p>
</div>
<div class="col-lg-12">
<table class="table table-bordered m-t">
@@ -28,21 +15,21 @@
</tr>
</thead>
<tbody>
{% if list %}
{% for item in list %}
<tr>
<td>20180224387</td>
<td>0.05</td>
<td>2018-02-24 12:37</td>
<td>{{ item.order_number }}</td>
<td>{{ item.total_price }}</td>
<td>{{ item.pay_time }}</td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="3">暂无数据~~</td></tr>
{% endif %}
</tbody>
</table>
<div class="row">
<div class="col-lg-12">
<span class="pagination_count" style="line-height: 40px;">共1条记录 | 每页50条</span>
<ul class="pagination pagination-lg pull-right" style="margin: 0 0 ;">
<li class="active"><a href="javascript:void(0);">1</a></li>
</ul>
</div>
</div>
<!--分页代码已被封装到统一模板文件中-->
{% include 'common/pagenation.html' %}
</div>
</div>
{% endblock %}

View File

@@ -1,19 +1,6 @@
{% extends "common/layout_main.html" %}
{% block content %}
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li class="current">
<a href="{{ buildUrl('/finance/index') }}">订单列表</a>
</li>
<li>
<a href="{{ buildUrl('/finance/account') }}">财务流水</a>
</li>
</ul>
</div>
</div>
</div>
{% include "common/tab_finance.html" %}
<div class="row">
<div class="col-lg-12">
<form class="form-inline wrap_search">
@@ -21,9 +8,9 @@
<div class="form-group">
<select name="status" class="form-control inline">
<option value="-1">请选择状态</option>
<option value="1">已支付</option>
<option value="-8">待支付</option>
<option value="0">已关闭</option>
{% for tmp_key in pay_status_mapping %}
<option value="{{ tmp_key }}" {% if tmp_key == search_con['status'] %} selected {% endif %}>{{ pay_status_mapping[ tmp_key ] }}</option>
{% endfor %}
</select>
</div>
</div>
@@ -42,33 +29,36 @@
</tr>
</thead>
<tbody>
{% if list %}
{% for item in list %}
<tr>
<td>20171231347</td>
<td>{{ item.order_number }}</td>
<td>
小鸡炖蘑菇 × 1<br>
{% for item_food in item.foods %}
{{ item_food.name }} × {{ item_food.quantity }}
{% endfor %}
</td>
<td>0.01</td>
<td>{{ item.price }}</td>
<td>{{ item.pay_time }}</td>
<td>{{ item.status_desc }}</td>
<td>{{ item.created_time }}</td>
<td>
</td>
<td>已关闭</td>
<td>2017-12-31 13:35</td>
<td>
<a href="{{ buildUrl('/finance/pay-info') }}">
<a href="{{ buildUrl('/finance/pay-info') }}?id={{ item.id }}">
<i class="fa fa-eye fa-lg"></i>
</a>
</td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="7">暂无数据~~</td></tr>
{% endif %}
</tbody>
</table>
<!--分页代码已被封装到统一模板文件中-->
<div class="row">
<div class="col-lg-12">
<span class="pagination_count" style="line-height: 40px;">共1条记录 | 每页50条</span>
<ul class="pagination pagination-lg pull-right" style="margin: 0 0 ;">
<li class="active"><a href="javascript:void(0);">1</a></li>
</ul>
</div>
</div>
{% include 'common/pagenation.html' %}
</div>
</div>
{% endblock %}
{% block js %}
<script src="{{ buildStaticUrl('/js/finance/index.js') }}"></script>
{% endblock %}

View File

@@ -1,36 +1,26 @@
{% extends "common/layout_main.html" %}
{% block content %}
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li class="current">
<a href="{{ buildUrl('/finance/index') }}">订单列表</a>
</li>
<li>
<a href="{{ buildUrl('/finance/account') }}">财务流水</a>
</li>
</ul>
</div>
</div>
</div>
{% include "common/tab_finance.html" %}
<div class="row m-t wrap_info">
<div class="col-lg-12">
<div class="row">
<div class="col-lg-12">
<div class="m-b-md">
{% if pay_order_info.status == 1 and pay_order_info.express_status == -7 %}
<a class="btn btn-outline btn-primary pull-right express_send" href="javascript:void(0);" data="{{ pay_order_info.id }}">确认发货</a>
{% endif %}
<div class="m-b-md">
<h2>订单信息</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<p class="m-t">订单编号:20180605398</p>
<p>会员姓名:Mr 杨</p>
<p>订单总价:1.00</p>
<p>订单状态:已关闭</p>
<p>创建时间2018-06-05 21:13</p>
<p>收货地址:北京市海淀区5558855测试13145310973</p>
<p class="m-t">订单编号:{{ pay_order_info.order_number }}</p>
<p>会员姓名:{{ member_info.nickname }}</p>
<p>订单总价:{{ pay_order_info.total_price }}</p>
<p>订单状态:{{ pay_order_info.status_desc }}</p>
<p>创建时间:{{ pay_order_info.created_time }}</p>
<p>收货地址:{{ address_info.nickname }}{{ address_info.mobile }}{{ address_info.address }}</p>
</div>
</div>
<div class="row m-t">
@@ -58,12 +48,14 @@
</tr>
</thead>
<tbody>
<tr>
<td>11</td>
<td>1</td>
<td>1.00</td>
</tr>
</tbody>
{% for item in pay_order_items %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.quantity }}</td>
<td>{{ item.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
@@ -74,3 +66,6 @@
</div>
</div>
{% endblock %}
{% block js %}
<script src="{{ buildStaticUrl('/js/finance/pay_info.js') }}"></script>
{% endblock %}

View File

@@ -1,7 +1,7 @@
{% extends "common/layout_main.html" %}
{% block content %}
{% include "common/tab_food.html" %}
<div class="row">
<div class="row">tab_food
<div class="col-lg-12">
<form class="form-inline wrap_search">
<div class="row m-t p-w-m">

View File

@@ -1,19 +1,6 @@
{% extends "common/layout_main.html" %}
{% block content %}
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li>
<a href="{{ buildUrl('/food/index') }}">美食列表</a>
</li>
<li class="current">
<a href="{{ buildUrl('/food/cat') }}">分类列表</a>
</li>
</ul>
</div>
</div>
</div>
{% include "common/tab_food.html" %}
<div class="row m-t wrap_cat_set">
<div class="col-lg-12">
<h2 class="text-center">分类设置</h2>
@@ -21,7 +8,7 @@
<div class="form-group">
<label class="col-lg-2 control-label">分类名称:</label>
<div class="col-lg-10">
<input type="text" name="name" class="form-control" placeholder="请输入分类名称~~" value="info.name">
<input type="text" name="name" class="form-control" placeholder="请输入分类名称~~" value="{{ info.name }}">
</div>
</div>
<div class="hr-line-dashed"></div>
@@ -34,7 +21,7 @@
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-lg-4 col-lg-offset-2">
<input type="hidden" name="id" value="{{ info.id }}">
<input type="hidden" name="id" value="{{ info.id }}">
<button class="btn btn-w-m btn-outline btn-primary save">保存</button>
</div>
</div>

View File

@@ -1,19 +1,6 @@
{% extends "common/layout_main.html" %}
{% block content %}
<div class="row border-bottom">
<div class="col-lg-12">
<div class="tab_title">
<ul class="nav nav-pills">
<li class="current">
<a href="{{ buildUrl('/food/index') }}">美食列表</a>
</li>
<li>
<a href="{{ buildUrl('/food/cat') }}">分类列表</a>
</li>
</ul>
</div>
</div>
</div>
{% include "common/tab_food.html" %}
<style type="text/css">
.wrap_info img {
width: 70%;
@@ -24,7 +11,7 @@
<div class="row">
<div class="col-lg-12">
<div class="m-b-md">
<a class="btn btn-outline btn-primary pull-right" href="{{ buildUrl('/food/set') }}">
<a class="btn btn-outline btn-primary pull-right" href="{{ buildUrl('/food/set') }}?id={{ info.id }}">
<i class="fa fa-pencil"></i>编辑
</a>
<h2>美食信息</h2>
@@ -33,13 +20,13 @@
</div>
<div class="row">
<div class="col-lg-12">
<p class="m-t">美食名:小鸡炖蘑菇</p>
<p>售价:45.00</p>
<p>库存总量:88</p>
<p>图书标签:好吃</p>
<p>封面图:<img src="{{ buildStaticUrl('/images/common/logo.png') }}" style="width: 50px;height: 50px;"></p>
<p class="m-t">美食名:{{ info.name }}</p>
<p>售价:{{ info.price }}</p>
<p>库存总量:{{ info.stock }}</p>
<p>图书标签:{{ info.tags }}</p>
<p>封面图:<img src="{{ buildImageUrl( info.main_image ) }}" style="width: 50px;height: 50px;"></p>
<p>描述:</p>
<p>小鸡炖蘑菇~~~~</p>
<p>{{ info.summary | safe }}</p>
<p></p>
</div>
</div>
@@ -88,71 +75,17 @@
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>订单过期释放库存</td>
<td>2018-03-14 20:00:02</td>
</tr>
<tr>
<td>-1</td>
<td>在线购买</td>
<td>2018-03-14 19:14:32</td>
</tr>
<tr>
<td>1</td>
<td>订单过期释放库存</td>
<td>2018-03-14 10:11:14</td>
</tr>
<tr>
<td>-1</td>
<td>在线购买</td>
<td>2018-03-14 10:10:21</td>
</tr>
<tr>
<td>1</td>
<td>订单过期释放库存</td>
<td>2018-03-12 23:00:02</td>
</tr>
<tr>
<td>-1</td>
<td>在线购买</td>
<td>2018-03-12 22:28:11</td>
</tr>
<tr>
<td>1</td>
<td>订单过期释放库存</td>
<td>2018-03-11 17:00:02</td>
</tr>
<tr>
<td>-1</td>
<td>在线购买</td>
<td>2018-03-11 16:29:48</td>
</tr>
<tr>
<td>1</td>
<td>订单过期释放库存</td>
<td>2018-03-10 14:30:02</td>
</tr>
<tr>
<td>1</td>
<td>订单过期释放库存</td>
<td>2018-03-10 14:30:02</td>
</tr>
<tr>
<td>-1</td>
<td>在线购买</td>
<td>2018-03-10 13:57:43</td>
</tr>
<tr>
<td>-1</td>
<td>在线购买</td>
<td>2018-03-10 13:56:09</td>
</tr>
<tr>
<td>88</td>
<td></td>
<td>2018-03-01 14:40:02</td>
</tr>
{% if stock_change_list %}
{% for item in stock_change_list %}
<tr>
<td>{{ item.unit }}</td>
<td>{{ item.note }}</td>
<td>{{ item.created_time }}</td>
</tr>
{% endfor %}
{% else %}
<tr><td colspan="3">暂无数据~~</td></tr>
{% endif %}
</tbody>
</table>
</div>

17
www.py
View File

@@ -5,29 +5,32 @@ from application import app
统一拦截处理和统一错误处理
'''
from web.interceptors.AuthInterceptor import *
from web.interceptors.ApiAuthInterceptor import *
from web.interceptors.ErrorInterceptor import *
'''
蓝图功能对所有的url进行蓝图功能配置
'''
from web.controllers.index import route_index
from web.controllers.user.User import route_user
from web.controllers.static import route_static
from web.controllers.account.Account import route_account
from web.controllers.finance.Finance import route_finance
from web.controllers.food.Food import route_food
from web.controllers.account.Account import route_account
from web.controllers.member.Member import route_member
from web.controllers.finance.Finance import route_finance
from web.controllers.stat.Stat import route_stat
from web.controllers.api import route_api
from web.controllers.upload.Upload import route_upload
from web.controllers.chart import route_chart
app.register_blueprint( route_index,url_prefix = "/" )
app.register_blueprint( route_user,url_prefix = "/user" )
app.register_blueprint( route_static,url_prefix = "/static" )
app.register_blueprint( route_account,url_prefix = "/account" )
app.register_blueprint(route_finance,url_prefix="/finance")
app.register_blueprint(route_member,url_prefix="/member")
app.register_blueprint(route_food,url_prefix="/food")
app.register_blueprint(route_stat,url_prefix="/stat")
app.register_blueprint( route_food,url_prefix = "/food" )
app.register_blueprint( route_member,url_prefix = "/member" )
app.register_blueprint( route_finance,url_prefix = "/finance" )
app.register_blueprint( route_stat,url_prefix = "/stat" )
app.register_blueprint( route_api,url_prefix = "/api" )
app.register_blueprint( route_upload,url_prefix = "/upload" )
app.register_blueprint( route_chart,url_prefix = "/chart" )