Commit a590461e by 魏强

update;

parents
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
__pycache__/
.idea/
*.pyc
.gz
.txt
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# -*- coding: utf-8 -*-
import os
is_prod = os.getenv("RUN_ENV", "test") == 'prod'
if is_prod:
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:Boosal2014!!@sh-cdb-kzmpyjqw.sql.tencentcdb.com:63037/suishenwan'
else:
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:JYfd9X0w5DFAg4bU@sh-cdb-hcnle4m0.sql.tencentcdb.com:63443/suishenwan'
SECRET_KEY = "MgwuKKEcAk2UIaGxHAwnf38YvjvXMCqb"
SQLALCHEMY_TRACK_MODIFICATIONS = False
if is_prod:
TENCENT_REDIS_URL = "redis://:Boosal2014@172.17.0.5:6379"
else:
TENCENT_REDIS_URL = "redis://:Boosal2014@49.235.36.102:16379"
IMG_HEAD_URL = "https://dev-1255927177.cos.ap-shanghai.myqcloud.com"
ACTION_PWD = "Ssw@666"
# -*- coding: utf-8 -*-
import os
is_prod = os.getenv("RUN_ENV", "test") == 'prod'
ONENET_CONFIG = {
"encoding_AES_key": "XzHtYS3PbRiCDErEaztV286Cf4QmmL21T77tEY4Yb2m",
"he_cloud_token": "suishenwanonenettesttokenhecloud",
"url": 'http://api.js.cmcconenet.com',
}
if is_prod:
ONENET_CONFIG['api_key'] = "aFpHq1TkvggQrHkTgMlTKA2pXAI="
else:
ONENET_CONFIG['api_key'] = "H9x=yfGVGPPPBZxzyaaGhbaJ6kM="
MINA_APP = {
"app_id": "wx3185fb4a3633beb0",
"app_key": "d0fee84366bfb19c95505f4ddfa47b63",
"mch_id": "1487106062",
"pay_key": "huituzhineng3MaChengjunhandsomeh",
"wx_pay_cert_path": "Libs/cert/AllTour_cert/apiclient_cert.pem",
"wx_pay_key_path": "Libs/cert/AllTour_cert/apiclient_key.pem"
}
INVOICE_CONFIG = {
"app_id": "c58c70bb672e397b5ff908dc67d97a39c1c88a306bfc4c5b46146c419ef85779" if is_prod else "6d29f136114544bcc73edcce960c430231183cc192c433e2b9ebcad56e8ceb08",
"app_key": "8C8A5FD94F08F1D8" if is_prod else "5EE6C2C11DD421F2",
"xsf_nsrsbh": "913205943138134162" if is_prod else "110109500321655",
"xsf_mc": "苏州随身玩信息技术有限公司" if is_prod else "百旺电子测试2",
"url": "https://www.fapiao.com:63089/fpt-dsqz/invoice" if is_prod else "https://dev.fapiao.com:18944/fpt-dsqz/invoice",
"spbm": "304020300000000000001" if is_prod else "3070401000000000000",
"cert_path": "Libs/cert/invoice/cert.pem" if is_prod else "Libs/cert/invoice/testISSUE.pem",
"content": "*旅游娱乐服务*讲解服务",
"dizhi_dianhua": "苏州工业园区若水路1号0512-62748449",
"yinhang_zhanghao": "招商银行苏州分行营业部512905030310801",
"kaipiaoren": "随身玩",
"shoukuanren": "随身玩",
"fuheren": "曹云香"
}
SMS_CONFIG = {
'app_id': 1400068750,
'app_key': '3431474d060edb7fdd12f05bc7b3f848'
}
LOGIN_TYPE = {
'code_login': 1,
'token_login': 2,
'send_code': 3,
'password': 4
}
AGENT_STATUS = {
'1': '超级管理员',
'2': '代理商',
'3': '调试'
}
ACCOUNT_STATUS = {
'on_use': 1,
'delete': 2
}
# -*- coding: utf-8 -*-
import base64
import datetime
from flask import Blueprint, jsonify, request, g
from Config.common_config import LOGIN_TYPE, ACCOUNT_STATUS
from Libs.ErrorTips import TOKEN_NOT_VALID_ERROR, TOKEN_EXPIRE_ERROR, PHONE_NOT_NULL_ERROR, PHONE_NOT_VALID_ERROR, \
PHONE_NOT_PERMISSION, USER_NOT_EXIST, LOGIN_ERROR, VERIFICATION_CODE_INVALID_ERROR, VERIFICATION_CODE_ERROR, \
BASE_RESPONSE, ACCOUNT_ALREADY_EXISTS_ERROR, ACCOUNT_NOT_EXISTS_ERROR, ACCOUNT_AGENT_SPOT_NULL_ERROR, \
ACCOUNT_ALREADY_DELETE_ERROR
from Libs.Helper import Helper
from Libs.Logger import logger
from Model.Agent.AgentAccountModel import AgentAccount
from Model.Agent.AgentLogRecordModel import AgentLogRecord
from Model.Agent.AgentSpotModel import AgentSpot
from Model.Base import db
from Service.AgentService import AgentService
from Service.SMSService import SMSService
route_account = Blueprint('account', __name__)
@route_account.route('/test')
def test():
ip = request.remote_addr
return jsonify({'code': 200, 'msg': 'success', 'data': ip})
@route_account.route('/edit_account', methods=['GET', 'POST'])
def edit_user():
json_data = request.get_json()
old_phone = json_data['old_phone'] if 'old_phone' in json_data else ''
new_phone = json_data['new_phone'] if 'new_phone' in json_data else ''
user_name = json_data['name'] if 'name' in json_data else 'SSW'
password = json_data['password'] if 'password' in json_data else ''
comment = json_data['comment'] if 'comment' in json_data else ''
spot_list = json_data['spot_list'] if 'spot_list' in json_data else []
if not old_phone:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='old phone is null').to_dict())
if not new_phone:
return jsonify(PHONE_NOT_NULL_ERROR)
result = Helper.checkPhone(new_phone)
if not result:
return jsonify(PHONE_NOT_VALID_ERROR)
if not spot_list:
return jsonify(ACCOUNT_AGENT_SPOT_NULL_ERROR)
agent_info = AgentAccount.query.filter_by(phone=old_phone).first()
if not agent_info:
return jsonify(ACCOUNT_NOT_EXISTS_ERROR)
agent_info.user_name = user_name
agent_info.phone = new_phone
agent_info.comment = comment
if password:
salt = AgentService.gene_salt()
agent_info.salt_pwd = salt
agent_info.password = AgentService.gene_pwd(password, salt)
db.session.add(agent_info)
agent_spot_info = AgentSpot.query.filter_by(agent_no=agent_info.id).all()
for info in agent_spot_info:
info.status = ACCOUNT_STATUS['delete']
db.session.add(info)
for i in spot_list:
cur_spot_info = AgentSpot.query.filter_by(agent_no=agent_info.id, spot_no=i).first()
if not cur_spot_info:
cur_agent_spot = AgentSpot()
cur_agent_spot.agent_no = agent_info.id
cur_agent_spot.spot_no = i
cur_agent_spot.status = ACCOUNT_STATUS['on_use']
cur_agent_spot.created_at = datetime.datetime.now()
cur_agent_spot.updated_at = datetime.datetime.now()
db.session.add(cur_agent_spot)
else:
cur_spot_info.status = ACCOUNT_STATUS['on_use']
db.session.add(cur_spot_info)
db.session.commit()
return jsonify(BASE_RESPONSE().to_dict())
@route_account.route('/add_account', methods=['GET', 'POST'])
def add_user():
json_data = request.get_json()
user_name = json_data['name'] if 'name' in json_data else 'SSW'
phone = json_data['phone'] if 'phone' in json_data else None
password = json_data['password'] if 'password' in json_data else None
comment = json_data['comment'] if 'comment' in json_data else ''
agent_no = AgentService.create_agent_no()
if not phone:
return jsonify(PHONE_NOT_NULL_ERROR)
result = Helper.checkPhone(phone)
if not result:
return jsonify(PHONE_NOT_VALID_ERROR)
agent_info = AgentAccount.query.filter_by(phone=phone, status=ACCOUNT_STATUS['on_use']).first()
if agent_info:
return jsonify(ACCOUNT_ALREADY_EXISTS_ERROR)
user_info = AgentAccount()
user_info.agent_no = agent_no
user_info.user_name = user_name
user_info.phone = phone
user_info.level = 2
user_info.status = ACCOUNT_STATUS['on_use']
user_info.comment = comment
user_info.created_at = datetime.datetime.now()
user_info.updated_at = datetime.datetime.now()
if password:
salt = AgentService.gene_salt()
user_info.salt_pwd = salt
user_info.password = AgentService.gene_pwd(password, salt)
db.session.add(user_info)
spot_list = json_data['spot_list'] if 'spot_list' in json_data else []
if not spot_list:
return jsonify(ACCOUNT_AGENT_SPOT_NULL_ERROR)
cur_info = AgentAccount.query.filter_by(phone=phone, status=ACCOUNT_STATUS['on_use']).first()
if not cur_info:
return jsonify(ACCOUNT_NOT_EXISTS_ERROR)
for i in spot_list:
user_spot = AgentSpot()
user_spot.agent_no = cur_info.id
user_spot.spot_no = i
user_spot.status = ACCOUNT_STATUS['on_use']
user_spot.created_at = datetime.datetime.now()
user_spot.updated_at = datetime.datetime.now()
db.session.add(user_spot)
db.session.commit()
return jsonify(BASE_RESPONSE().to_dict())
@route_account.route('/delete_account', methods=['GET', 'POST'])
def delete_user():
json_data = request.get_json()
phone = json_data['phone'] if 'phone' in json_data else ''
if not phone:
return jsonify(PHONE_NOT_NULL_ERROR)
agent_info = AgentAccount.query.filter_by(phone=phone).first()
if not agent_info:
return jsonify(ACCOUNT_NOT_EXISTS_ERROR)
agent_spot_info = AgentSpot.query.filter_by(agent_no=agent_info.id).all()
for info in agent_spot_info:
info.status = ACCOUNT_STATUS['delete']
db.session.add(info)
agent_info.status = ACCOUNT_STATUS['delete']
db.session.add(agent_info)
db.session.commit()
return jsonify(BASE_RESPONSE().to_dict())
@route_account.route('/sendCode', methods=['GET', 'POST'])
def send_code():
json_data = request.get_json()
cur_ip = request.remote_addr
phone = json_data['phone'] if 'phone' in json_data else None
if not phone:
return jsonify(PHONE_NOT_NULL_ERROR)
logger.info(phone)
# 判断该手机号是否再数据库中,不在返回无权限登录
agent = AgentAccount.query.filter_by(phone=phone).first()
logger.info('agent:')
logger.info(agent)
if not agent:
return jsonify(PHONE_NOT_PERMISSION)
# 判断该账号是否已被删除
if agent.status == ACCOUNT_STATUS['delete']:
return jsonify(ACCOUNT_ALREADY_DELETE_ERROR)
result = Helper.checkPhone(phone)
if not result:
return jsonify(PHONE_NOT_VALID_ERROR)
sms = SMSService()
sms.phoneSendCode(phone, 92065, '灰兔智能')
agent_log = AgentLogRecord()
agent_log.phone = phone
agent_log.ip = cur_ip
agent_log.last_login = datetime.datetime.now()
agent_log.login_type = LOGIN_TYPE['send_code']
agent_log.created_at = datetime.datetime.now()
agent_log.updated_at = datetime.datetime.now()
db.session.add(agent_log)
db.session.commit()
return jsonify(BASE_RESPONSE().to_dict())
# @route_account.route('/login', methods=['GET', 'POST'])
def login():
token = request.headers.get('token')
cur_ip = request.remote_addr
json_data = request.get_json()
data = {}
phone = json_data['phone'] if 'phone' in json_data else None
code = json_data['code'] if 'code' in json_data else None
# test
if phone == '18896812809' and code == '1234':
test_agent_info = AgentAccount.query.filter_by(id=1).first()
g.user = test_agent_info
data['token'] = test_agent_info.access_token
data['user_name'] = test_agent_info.user_name
data['phone'] = test_agent_info.phone
data['level'] = test_agent_info.level
data['spot_info'] = AgentService.get_spot_info(test_agent_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
if token:
# token登录
user_info = AgentService.check_agent_token(token)
if user_info == 1:
return jsonify(TOKEN_NOT_VALID_ERROR)
if user_info == 2:
return jsonify(TOKEN_EXPIRE_ERROR)
# 判断该账号是否已被删除
if user_info.status == ACCOUNT_STATUS['delete']:
return jsonify(ACCOUNT_ALREADY_DELETE_ERROR)
salt = AgentService.gene_salt()
new_token = "%s#%s" % (AgentService.gene_agent_code(user_info, salt), user_info.id)
user_info.access_token = new_token
user_info.salt = salt
user_info.last_login = datetime.datetime.now()
user_info.expire_time = datetime.datetime.now() + datetime.timedelta(days=7)
user_info.updated_at = datetime.datetime.now()
db.session.add(user_info)
agent_log = AgentLogRecord()
agent_log.phone = user_info.phone
agent_log.ip = cur_ip
agent_log.last_login = user_info.last_login
agent_log.login_type = LOGIN_TYPE['token_login']
agent_log.created_at = datetime.datetime.now()
agent_log.updated_at = datetime.datetime.now()
db.session.add(agent_log)
db.session.commit()
data['token'] = new_token
data['user_name'] = user_info.user_name
data['phone'] = user_info.phone
data['level'] = user_info.level
data['spot_info'] = AgentService.get_spot_info(user_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
elif phone and code:
# 验证码登录
# 判断验证码是否正确
sms = SMSService()
res = sms.verificate(phone, code)
if res == -1:
return jsonify(VERIFICATION_CODE_INVALID_ERROR)
elif res == -2:
return jsonify(VERIFICATION_CODE_ERROR)
agent_info = AgentAccount.query.filter_by(phone=phone, status=ACCOUNT_STATUS['on_use']).first()
if not agent_info:
return jsonify(USER_NOT_EXIST)
salt = AgentService.gene_salt()
new_token = "%s#%s" % (AgentService.gene_agent_code(agent_info, salt), agent_info.id)
agent_token = new_token
agent_info.access_token = agent_token
agent_info.salt = salt
agent_info.last_login = datetime.datetime.now()
agent_info.expire_time = datetime.datetime.now() + datetime.timedelta(days=7)
agent_info.updated_at = datetime.datetime.now()
db.session.add(agent_info)
agent_log = AgentLogRecord()
agent_log.phone = agent_info.phone
agent_log.ip = cur_ip
agent_log.last_login = agent_info.last_login
agent_log.login_type = LOGIN_TYPE['code_login']
agent_log.created_at = datetime.datetime.now()
agent_log.updated_at = datetime.datetime.now()
db.session.add(agent_log)
db.session.commit()
data['token'] = new_token
data['user_name'] = agent_info.user_name
data['phone'] = agent_info.phone
data['level'] = agent_info.level
data['spot_info'] = AgentService.get_spot_info(agent_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
else:
return jsonify(LOGIN_ERROR)
@route_account.route('/login', methods=['GET', 'POST'])
def login():
token = request.headers.get('token')
cur_ip = request.remote_addr
json_data = request.get_json()
data = {}
phone = json_data['phone'] if 'phone' in json_data else None
code = json_data['code'] if 'code' in json_data else None
login_type = json_data['type'] if 'type' in json_data else 1 # 1.验证码登录,2.密码登录
# test
if phone == '18896812809' and code == '1234':
test_agent_info = AgentAccount.query.filter_by(id=1).first()
g.user = test_agent_info
data['token'] = test_agent_info.access_token
data['user_name'] = test_agent_info.user_name
data['phone'] = test_agent_info.phone
data['level'] = test_agent_info.level
data['spot_info'] = AgentService.get_spot_info(test_agent_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
if token:
# token登录
user_info = AgentService.check_agent_token(token)
if user_info == 1:
return jsonify(TOKEN_NOT_VALID_ERROR)
if user_info == 2:
return jsonify(TOKEN_EXPIRE_ERROR)
# 判断该账号是否已被删除
if user_info.status == ACCOUNT_STATUS['delete']:
return jsonify(ACCOUNT_ALREADY_DELETE_ERROR)
salt = AgentService.gene_salt()
new_token = "%s#%s" % (AgentService.gene_agent_code(user_info, salt), user_info.id)
user_info.access_token = new_token
user_info.salt = salt
user_info.last_login = datetime.datetime.now()
user_info.expire_time = datetime.datetime.now() + datetime.timedelta(days=7)
user_info.updated_at = datetime.datetime.now()
db.session.add(user_info)
agent_log = AgentLogRecord()
agent_log.phone = user_info.phone
agent_log.ip = cur_ip
agent_log.last_login = user_info.last_login
agent_log.login_type = LOGIN_TYPE['token_login']
agent_log.created_at = datetime.datetime.now()
agent_log.updated_at = datetime.datetime.now()
db.session.add(agent_log)
db.session.commit()
data['token'] = new_token
data['user_name'] = user_info.user_name
data['phone'] = user_info.phone
data['level'] = user_info.level
data['spot_info'] = AgentService.get_spot_info(user_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
else:
if login_type == 1:
# 验证码登录
# 判断验证码是否正确
sms = SMSService()
res = sms.verificate(phone, code)
if res == -1:
return jsonify(VERIFICATION_CODE_INVALID_ERROR)
elif res == -2:
return jsonify(VERIFICATION_CODE_ERROR)
agent_info = AgentAccount.query.filter_by(phone=phone, status=ACCOUNT_STATUS['on_use']).first()
if not agent_info:
return jsonify(USER_NOT_EXIST)
salt = AgentService.gene_salt()
new_token = "%s#%s" % (AgentService.gene_agent_code(agent_info, salt), agent_info.id)
agent_token = new_token
agent_info.access_token = agent_token
agent_info.salt = salt
agent_info.last_login = datetime.datetime.now()
agent_info.expire_time = datetime.datetime.now() + datetime.timedelta(days=7)
agent_info.updated_at = datetime.datetime.now()
db.session.add(agent_info)
agent_log = AgentLogRecord()
agent_log.phone = agent_info.phone
agent_log.ip = cur_ip
agent_log.last_login = agent_info.last_login
agent_log.login_type = LOGIN_TYPE['code_login']
agent_log.created_at = datetime.datetime.now()
agent_log.updated_at = datetime.datetime.now()
db.session.add(agent_log)
db.session.commit()
data['token'] = new_token
data['user_name'] = agent_info.user_name
data['phone'] = agent_info.phone
data['level'] = agent_info.level
data['spot_info'] = AgentService.get_spot_info(agent_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
else:
# 密码登录
# 判断密码是否正确
agent_info = AgentAccount.query.filter_by(phone=phone, status=ACCOUNT_STATUS['on_use']).first()
if not agent_info:
return jsonify(USER_NOT_EXIST)
if not agent_info.password:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='login error').to_dict())
if agent_info.password != AgentService.gene_pwd(code, agent_info.salt_pwd):
return jsonify(BASE_RESPONSE(error_code=-1, error_message='手机号或密码错误').to_dict())
salt = AgentService.gene_salt()
new_token = "%s#%s" % (AgentService.gene_agent_code(agent_info, salt), agent_info.id)
agent_token = new_token
agent_info.access_token = agent_token
agent_info.salt = salt
agent_info.last_login = datetime.datetime.now()
agent_info.expire_time = datetime.datetime.now() + datetime.timedelta(days=7)
agent_info.updated_at = datetime.datetime.now()
db.session.add(agent_info)
agent_log = AgentLogRecord()
agent_log.phone = agent_info.phone
agent_log.ip = cur_ip
agent_log.last_login = agent_info.last_login
agent_log.login_type = LOGIN_TYPE['password']
agent_log.created_at = datetime.datetime.now()
agent_log.updated_at = datetime.datetime.now()
db.session.add(agent_log)
db.session.commit()
data['token'] = new_token
data['user_name'] = agent_info.user_name
data['phone'] = agent_info.phone
data['level'] = agent_info.level
data['spot_info'] = AgentService.get_spot_info(agent_info)
return jsonify(BASE_RESPONSE(data=data).to_dict())
# -*- coding: utf-8 -*-
from flask import Blueprint, jsonify, request, g
from Libs.ErrorTips import BASE_RESPONSE, OPERATE_TYPE_ERROR, OPERATE_LEVEL_ERROR, OPERATE_ERROR
from Libs.Helper import Helper
from Service.AgentService import AgentService
from Service.IndexService import IndexService
route_index = Blueprint('index', __name__)
@route_index.route('/index', methods=['GET', 'POST'])
def index():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
data_type = json_data['type'] if 'type' in json_data else 1 # 1今日,2本周,3本月,4历史
if int(data_type) not in [1, 2, 3, 4]:
return jsonify(OPERATE_TYPE_ERROR)
cur_user = g.user
if int(data_type) == 2:
# 本周数据
start_time_week, end_time_week = Helper.getWeekDate()
start_time_lastweek, end_time_lastweek = Helper.getLastWeekDate()
week_income, week_rent = IndexService.get_total_production(spot_id, start_time_week, end_time_week)
lastweek_income, lastweek_rent = IndexService.get_total_production(spot_id, start_time_lastweek,
end_time_lastweek)
refund_money_week, refund_rent_week = IndexService.get_refund_rent(spot_id, start_time_week, end_time_week)
invalid_money_week, invalid_rent_week = IndexService.get_invalid_production_info(spot_id, start_time_week,
end_time_week)
invalid_money_lastweek, invalid_rent_lastweek = IndexService.get_invalid_production_info(spot_id,
start_time_lastweek,
end_time_lastweek)
if cur_user.level == 1:
admin_week = {}
admin_week['week_income'] = week_income
admin_week['week_rent'] = week_rent
admin_week['lastweek_income'] = lastweek_income
admin_week['lastweek_rent'] = lastweek_rent
admin_week['refund_money_week'] = refund_money_week
admin_week['refund_rent_week'] = refund_rent_week
admin_week['week_invalid_rent'] = invalid_rent_week
admin_week['week_invalid_money'] = invalid_money_lastweek
if lastweek_income == 0:
admin_week['week_income_compare'] = 0
else:
admin_week['week_income_compare'] = round((week_income - lastweek_income) / lastweek_income, 2)
if invalid_rent_lastweek == 0:
admin_week['week_invalid_compare'] = 0
else:
admin_week['week_invalid_compare'] = round(
(invalid_rent_week - invalid_rent_lastweek) / invalid_rent_lastweek, 2)
admin_week['spot_info'] = AgentService.get_spot_info(cur_user)
return jsonify(BASE_RESPONSE(data=admin_week).to_dict())
elif cur_user.level == 2:
return jsonify(OPERATE_LEVEL_ERROR)
else:
return jsonify(OPERATE_ERROR)
elif int(data_type) == 3:
# 本月数据
start_time_month, end_time_month = Helper.getMonthDate()
start_time_lastmonth, end_time_lastmonth = Helper.getLastMonthDate()
month_income, month_rent = IndexService.get_total_production(spot_id, start_time_month, end_time_month)
last_month_income, last_month_rent = IndexService.get_total_production(spot_id, start_time_lastmonth,
end_time_lastmonth)
refund_money_month, refund_rent_month = IndexService.get_refund_rent(spot_id, start_time_month, end_time_month)
invalid_money_month, invalid_rent_month = IndexService.get_invalid_production_info(spot_id, start_time_month,
end_time_month)
invalid_money_lastmonth, invalid_rent_lastmonth = IndexService.get_invalid_production_info(spot_id,
start_time_lastmonth,
end_time_lastmonth)
if cur_user.level == 1:
admin_month = {}
admin_month['month_income'] = month_income
admin_month['month_rent'] = month_rent
admin_month['last_month_income'] = last_month_income
admin_month['last_month_rent'] = last_month_rent
admin_month['refund_money_month'] = refund_money_month
admin_month['refund_rent_month'] = refund_rent_month
admin_month['month_invalid_rent'] = invalid_rent_month
admin_month['month_invalid_money'] = invalid_money_month
if last_month_income == 0:
admin_month['month_income_compare'] = 0
else:
admin_month['month_income_compare'] = round((month_income - last_month_income) / last_month_income, 2)
if invalid_rent_lastmonth == 0:
admin_month['month_invalid_compare'] = 0
else:
admin_month['month_invalid_compare'] = round(
(invalid_rent_month - invalid_rent_lastmonth) / invalid_rent_lastmonth, 2)
admin_month['spot_info'] = AgentService.get_spot_info(cur_user)
return jsonify(BASE_RESPONSE(data=admin_month).to_dict())
elif cur_user.level == 2:
return jsonify(OPERATE_LEVEL_ERROR)
else:
return jsonify(OPERATE_ERROR)
elif int(data_type) == 4:
# 历史数据
history_income = IndexService.get_history_income_production(spot_id)
history_rent = IndexService.get_history_production(spot_id)
history_refund_money, history_refund_rent = IndexService.get_history_refund_rent(spot_id)
invalid_money_history, invalid_rent_history = IndexService.get_invalid_production_info_all(spot_id)
if cur_user.level == 1:
admin_history = {}
admin_history['history_income'] = history_income
admin_history['history_rent'] = history_rent
admin_history['history_refund_money'] = history_refund_money
admin_history['history_refund_rent'] = history_refund_rent
admin_history['history_invalid_rent'] = invalid_rent_history
admin_history['history_invalid_money'] = invalid_money_history
admin_history['spot_info'] = AgentService.get_spot_info(cur_user)
return jsonify(BASE_RESPONSE(data=admin_history).to_dict())
elif cur_user.level == 2:
agent_history = {}
start_time_week, end_time_week = Helper.getWeekDate()
start_time_lastweek, end_time_lastweek = Helper.getLastWeekDate()
start_time_month, end_time_month = Helper.getMonthDate()
start_time_lastmonth, end_time_lastmonth = Helper.getLastMonthDate()
week_income, week_rent = IndexService.get_total_production(spot_id, start_time_week, end_time_week)
lastweek_income, lastweek_rent = IndexService.get_total_production(spot_id, start_time_lastweek,
end_time_lastweek)
month_income, month_rent = IndexService.get_total_production(spot_id, start_time_month, end_time_month)
lastmonth_income, lastmonth_rent = IndexService.get_total_production(spot_id, start_time_lastmonth,
end_time_lastmonth)
agent_history['week_income'] = week_income
agent_history['week_rent'] = week_rent
agent_history['lastweek_income'] = lastweek_income
agent_history['lastweek_rent'] = lastweek_rent
agent_history['history_income'] = history_income
agent_history['history_rent'] = history_rent
agent_history['month_income'] = month_income
agent_history['month_rent'] = month_rent
agent_history['lastmonth_income'] = lastmonth_income
agent_history['lastmonth_rent'] = lastmonth_rent
agent_history['spot_info'] = AgentService.get_spot_info(cur_user)
return jsonify(BASE_RESPONSE(data=agent_history).to_dict())
else:
return jsonify(OPERATE_ERROR)
else:
# 今日数据
start_time_today, end_time_today = Helper.getTodayDate()
start_time_yesterday, end_time_yesterday = Helper.getYesterdayDate()
today_income, today_rent = IndexService.get_total_production(spot_id, start_time_today, end_time_today)
yesterday_income, yesterday_rent = IndexService.get_total_production(spot_id, start_time_yesterday,
end_time_yesterday)
rent_finish = IndexService.get_total_power(spot_id, start_time_today, end_time_today)
rent_not_return = IndexService.get_not_return_production(spot_id, start_time_today, end_time_today)
today_discount = IndexService.get_discount_money(spot_id, start_time_today, end_time_today)
if cur_user.level == 1:
# 超级管理员
admin_today = {}
admin_today['today_income'] = today_income
admin_today['today_rent'] = today_rent
admin_today['yesterday_income'] = yesterday_income
admin_today['yesterday_rent'] = yesterday_rent
admin_today['rent_finish'] = rent_finish
admin_today['rent_not_return'] = rent_not_return
rent_invalid_money, rent_invalid_rent = IndexService.get_invalid_production_info(spot_id, start_time_today,
end_time_today)
admin_today['today_invalid_rent'] = rent_invalid_rent
admin_today['today_invalid_money'] = rent_invalid_money
admin_today['discount'] = today_discount
refund_money_today, refund_rent_today = IndexService.get_refund_rent(spot_id, start_time_today,
end_time_today)
refund_money_yesterday, refund_rent_yesterday = IndexService.get_refund_rent(spot_id,
start_time_yesterday,
end_time_yesterday)
admin_today['refund_rent'] = refund_rent_today
admin_today['refund_money'] = refund_money_today
if refund_money_yesterday == 0:
admin_today['refund_compare'] = round((refund_money_today - refund_money_yesterday) * 100, 2)
else:
admin_today['refund_compare'] = round(
(refund_money_today - refund_money_yesterday) / refund_money_yesterday, 2)
admin_today['spot_info'] = AgentService.get_spot_info(cur_user)
return jsonify(BASE_RESPONSE(data=admin_today).to_dict())
elif cur_user.level == 2:
# 代理商
agent_today = {}
agent_today['today_income'] = today_income
agent_today['today_rent'] = today_rent
agent_today['yesterday_income'] = yesterday_income
agent_today['yesterday_rent'] = yesterday_rent
agent_today['rent_finish'] = rent_finish
agent_today['rent_not_return'] = rent_not_return
agent_today['discount'] = today_discount
agent_today['spot_info'] = AgentService.get_spot_info(cur_user)
return jsonify(BASE_RESPONSE(data=agent_today).to_dict())
else:
return jsonify(OPERATE_ERROR)
@route_index.route('/machine', methods=['GET', 'POST'])
def machine_info():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
data = IndexService.get_machine_info(spot_id)
return jsonify(BASE_RESPONSE(data=data).to_dict())
# -*- coding: utf-8 -*-
from flask import Blueprint, request, jsonify, g
from Libs.ErrorTips import BASE_RESPONSE
from Libs.Helper.Helper import getFormatDate
from Model.Base import db
from Model.Customer.CustomerModel import Customer
from Model.Production.ProductionModel import Production
from Model.Rent.RentModel import Rent
from Model.invoice.InvoiceModel import Invoice
from Model.invoice.InvoiceRecoreModel import InvoiceRecord
from Service.InvoiceService import InvoiceService
route_invoice = Blueprint('invoice', __name__)
@route_invoice.route('/list')
def invoice_list():
if g.user.id != 4:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='permission denied').to_dict())
invoice_info = InvoiceRecord.query.filter(InvoiceRecord.status == 1, InvoiceRecord.parent_id > 0).all()
data = []
for info in invoice_info:
customer_info = Customer.query.filter_by(id=info.customer_id).first()
phone = customer_info.phone if customer_info else None
tmp = {
'invoice_id': info.id,
'data': getFormatDate(info.created_at),
'total': info.pay_money,
'status': info.status,
'phone': phone
}
data.append(tmp)
return jsonify(BASE_RESPONSE(data=data).to_dict())
@route_invoice.route('/verify', methods=['GET', 'POST'])
def invoice_compare():
if g.user.id != 4:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='permission denied').to_dict())
json_data = request.get_json()
invoice_id = json_data['invoice_id'] if 'invoice_id' in json_data else 0
if int(invoice_id) < 1:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='invoice id error').to_dict())
new_invoice_info = InvoiceRecord.query.filter_by(id=invoice_id).first()
if not new_invoice_info:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='error').to_dict())
if new_invoice_info.parent_id == 0:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='该发票没有重开过').to_dict())
old_invoice_info = InvoiceRecord.query.filter_by(id=new_invoice_info.parent_id).first()
if not old_invoice_info:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='error').to_dict())
customer_info = Customer.query.filter_by(id=new_invoice_info.customer_id).first()
phone = customer_info.phone if customer_info else None
new_rent_list = new_invoice_info.rent_list.split(",")
new_info = {
"company_name": new_invoice_info.company_name,
"payment_id": new_invoice_info.payment_id,
"e_account": new_invoice_info.e_account,
"remark": new_invoice_info.remark,
"address": new_invoice_info.address,
"account": new_invoice_info.account,
"rent_count": len(new_rent_list),
"apply_time": getFormatDate(new_invoice_info.created_at),
"phone": phone
}
old_rent_list = old_invoice_info.rent_list.split(",")
old_info = {
"company_name": old_invoice_info.company_name,
"payment_id": old_invoice_info.payment_id,
"e_account": old_invoice_info.e_account,
"remark": old_invoice_info.remark,
"address": old_invoice_info.address,
"account": old_invoice_info.account,
"rent_count": len(old_rent_list),
"apply_time": getFormatDate(old_invoice_info.created_at),
"phone": phone
}
return jsonify(BASE_RESPONSE(data={'new_info': new_info, 'old_info': old_info}).to_dict())
@route_invoice.route('/submit', methods=['GET', 'POST'])
def invoice_submit():
if g.user.id != 4:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='permission denied').to_dict())
json_data = request.get_json()
invoice_id = json_data['invoice_id'] if 'invoice_id' in json_data else None
invoice_type = json_data['type'] if 'type' in json_data else None # 1:同意 2:驳回 3:拒绝
reason = json_data['reason'] if 'reason' in json_data else None # 理由
if not invoice_id or not type:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='params error').to_dict())
if int(invoice_id) < 1:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='invoice id error').to_dict())
current_invoice = InvoiceRecord.query.filter_by(id=invoice_id).first()
if not current_invoice:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='no such invoice').to_dict())
parent_id = current_invoice.parent_id
if parent_id == 0:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='该发票未重开过').to_dict())
invoice_detail = db.session.query(Invoice, InvoiceRecord).outerjoin(InvoiceRecord,
Invoice.id == InvoiceRecord.invoice_id).filter(
InvoiceRecord.id == parent_id).first()
if int(invoice_type) == 1:
# 审核成功
invoice_info = InvoiceService()
# 红冲
red_result = invoice_info.red_rush(invoice_detail.Invoice.fp_dm, invoice_detail.Invoice.fp_hm)
gmf_mc = current_invoice.company_name
gmf_nsrsbh = current_invoice.payment_id
gmf_dzyx = current_invoice.e_account
address = current_invoice.address
account = current_invoice.account
remark = current_invoice.remark
rent_list = current_invoice.rent_list
# 重开发票
repeat_result, new_id = invoice_info.dict_content(gmf_mc, gmf_nsrsbh, gmf_dzyx, address, account, remark,
rent_list)
if new_id != 0:
new_info = Invoice.query.filter_by(id=new_id).first()
new_info.is_red = 2
db.session.add(new_info)
current_invoice.status = 2
current_invoice.invoice_id = new_id
db.session.add(current_invoice)
db.session.commit()
data = {
'red_result': red_result,
'repeat_result': repeat_result
}
return jsonify(BASE_RESPONSE(data=data).to_dict())
elif int(invoice_type) == 2:
# 驳回
current_invoice.status = 3
current_invoice.reason = reason
db.session.add(current_invoice)
db.session.commit()
return jsonify(BASE_RESPONSE().to_dict())
else:
# 拒绝
current_invoice.status = 4
current_invoice.reason = reason
db.session.add(current_invoice)
db.session.commit()
return jsonify(BASE_RESPONSE().to_dict())
@route_invoice.route('/rent_list', methods=['GET', 'POST'])
def invoice_rent():
if g.user.id != 4:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='permission denied').to_dict())
json_data = request.get_json()
invoice_id = json_data['invoice_id'] if 'invoice_id' in json_data else 0
if int(invoice_id) < 1:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='invoice id error').to_dict())
invoice_info = InvoiceRecord.query.filter_by(id=invoice_id).first()
if not invoice_info:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='no invoice info').to_dict())
data = []
rent_all = invoice_info.rent_list
rent_all_list = rent_all.split(",")
for info in rent_all_list:
cur_info = db.session.query(Rent, Production).join(Production, Production.rent_id == Rent.id).filter(
Rent.rent_no == info).first()
tmp = {}
tmp["rent_no"] = cur_info.Rent.rent_no
tmp["hatch_no"] = cur_info.Production.rent_hatch_no
tmp["total"] = 0 if cur_info.Production.total is None else cur_info.Production.total
if cur_info.Production.is_return == 1:
if tmp["total"] <= 0:
if cur_info.Production.return_hatch_no == 127:
tmp["status"] = 3
else:
tmp["status"] = 2
else:
tmp["status"] = 1
else:
tmp["status"] = 0
data.append(tmp)
return jsonify(BASE_RESPONSE(data=data).to_dict())
# -*- coding: utf-8 -*-
import datetime
import json
import requests
from flask import Blueprint, jsonify, request
from sqlalchemy import or_
from sqlalchemy.exc import SQLAlchemyError
from Config.base_config import ACTION_PWD
from Libs.ErrorTips import BASE_RESPONSE, REFUND_NOT_RENT_INFO, REFUND_BACK_TIME_ERROR, REFUND_NOT_PRODUCTION_INFO, \
REFUND_MONEY_IS_ZERO, ACTION_CODE_ERROR, PARAMETER_ERROR
from Libs.Helper import Helper
from Libs.Logger import logger
from Model.Base import db
from Model.Customer.CustomerModel import Customer
from Model.Machine.MachineModel import Machine
from Model.Power.PowerModel import Power
from Model.Production.ProductionModel import Production
from Model.Rent.RentModel import Rent
from Model.Rent.RentRefundModel import RentRefund
from Service.IndexService import IndexService
from Service.RentService import RentService
from Service.WeChatService import WeChatService
route_rent = Blueprint('rent', __name__)
@route_rent.route('/test')
def test():
return jsonify({'code': 200, 'msg': 'success'})
@route_rent.route('/list', methods=['GET', 'POST'])
def rent_list():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
data_type = json_data['data_type'] if 'data_type' in json_data else 0 # 0:今日 1:昨日 2:近7天 3 所有
page = json_data['page'] if 'page' in json_data else 0
limit = json_data['limit'] if 'limit' in json_data else 10
if data_type not in [0, 1, 2, 3]:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='type error').to_dict())
if data_type == 0:
start_time, end_time = Helper.getTodayDate()
info = RentService.get_rent_production_info(spot_id, start_time, end_time)
total_income, total_rent = IndexService.get_total_production(spot_id, start_time, end_time)
return jsonify({'error_code': 200, 'error_message': 'Success', 'data': info,
'detail': {'total_income': total_income, 'total_rent': total_rent}})
elif data_type == 1:
start_time, end_time = Helper.getYesterdayDate()
info = RentService.get_rent_production_all(spot_id, start_time, end_time, page, limit)
total_income, total_rent = IndexService.get_total_production(spot_id, start_time, end_time)
return jsonify({'error_code': 200, 'error_message': 'Success', 'data': info,
'detail': {'total_income': total_income, 'total_rent': total_rent}})
elif data_type == 2:
start_time, end_time = Helper.getSevenDate()
info = RentService.get_rent_production_all(spot_id, start_time, end_time, page, limit)
total_income, total_rent = IndexService.get_total_production(spot_id, start_time, end_time)
return jsonify({'error_code': 200, 'error_message': 'Success', 'data': info,
'detail': {'total_income': total_income, 'total_rent': total_rent}})
else:
start_time, end_time = Helper.getMonthDate()
info = RentService.get_not_return_production(spot_id, start_time, end_time)
return jsonify(BASE_RESPONSE(data=info).to_dict())
@route_rent.route('/detail', methods=['GET', 'POST'])
def rent_detail():
json_data = request.get_json()
rent_no = json_data['rent_no'] if 'rent_no' in json_data else ''
hatch_no = json_data['hatch_no'] if 'hatch_no' in json_data else ''
# data = RentService.get_production_detail(rent_no, hatch_no)
data = RentService.get_production_detail_new(rent_no, hatch_no)
return jsonify(BASE_RESPONSE(data=data).to_dict())
@route_rent.route('/refund_old', methods=['GET', 'POST'])
def rent_refund_old():
json_data = request.get_json()
device_id = json_data['device_id'] if 'device_id' in json_data else ''
power_no = json_data['power_no'] if 'power_no' in json_data else ''
rent_no = json_data['rent_no'] if 'rent_no' in json_data else ''
back_time = json_data['back_time'] if 'back_time' in json_data else ''
code = json_data['code'] if 'code' in json_data else ''
data = {
'device_id': device_id,
'power_no': power_no,
'rent_no': rent_no,
'back_time': back_time,
'code': code
}
headers = {'Content-Type': 'application/xml'}
url = 'https://guide.ssw-htzn.com/tour/rent/do_return'
result = requests.post(url, json=data, headers=headers)
if result:
response = json.loads(result.text)
return jsonify(response)
return jsonify(BASE_RESPONSE(error_code=-1, error_message='Fail').to_dict())
@route_rent.route('/refund', methods=['GET', 'POST'])
def rent_refund():
json_data = request.get_json()
refund_type = json_data['type'] if 'type' in json_data else 0
rent_no = json_data['rent_no'] if 'rent_no' in json_data else ''
hatch_no = json_data['hatch_no'] if 'hatch_no' in json_data else 0
comment = json_data['comment'] if 'comment' in json_data else ''
production_info = db.session.query(Rent, Machine, Production).outerjoin(Machine,
Machine.id == Rent.machine_id).join(
Production, Production.rent_id == Rent.id).filter(Rent.rent_no == rent_no,
Production.rent_hatch_no == hatch_no).first()
if not production_info:
return jsonify(REFUND_NOT_RENT_INFO)
device_id = production_info.Machine.he_cloud_device_id
power_no = production_info.Production.power_no
rent_time = production_info.Rent.pay_time
if refund_type == '1':
# 正常归还
# back_time = rent_time + datetime.timedelta(hours=1)
now = datetime.datetime.now()
back_time = Helper.getFormatDate(now)
elif refund_type == '2':
# 全额归还
back_time = rent_time + datetime.timedelta(seconds=30)
elif refund_type == '3':
# 手动选择时间
back_time = json_data['back_time'] if 'back_time' in json_data else ''
else:
back_time = ''
if not back_time:
return jsonify(REFUND_BACK_TIME_ERROR)
# power_no = power_no[4:]
logger.info(power_no)
logger.info(device_id)
logger.info(rent_no)
logger.info(back_time)
power = Power.query.filter_by(power_no=power_no).first()
if power:
db.session.delete(power)
info = db.session.query(Production, Rent).join(Rent, Rent.id == Production.rent_id).filter(
Production.power_no == power_no, Production.is_refund == 0, Rent.rent_no == rent_no).first()
if not info:
logger.info('no production')
return jsonify(REFUND_NOT_PRODUCTION_INFO)
production = info.Production
rent = info.Rent
fee = RentService.check_fee(rent.pay_time.strftime('%Y-%m-%d %H:%M:%S'), str(back_time), rent.one_day_price,
rent.free_time)
total = fee['total'] if fee['total'] < rent.deposit else rent.deposit
refund_money = rent.deposit - total
if refund_money <= 0:
logger.info('refund money is 0')
return jsonify(REFUND_MONEY_IS_ZERO)
refund_no = RentService.create_refund_no()
data = {
"out_refund_no": refund_no,
"out_trade_no": rent.rent_no,
"total_fee": rent.deposit * rent.number,
"refund_fee": refund_money
}
result = WeChatService().refund(data)
if result:
try:
rent.total = rent.total + total
rent.real_total = rent.real_total + total
rent.is_over = 1
rent.over_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
rent.back_money = rent.back_money + refund_money
production.is_out = 1
production.is_return = 1
production.return_machine_id = production_info.Machine.id
production.return_time = back_time
production.total = total
production.is_refund = 1
production.refund_no = refund_no
if refund_type == '1':
production.return_hatch_no = production_info.Production.rent_hatch_no
else:
production.return_hatch_no = 127
# log
if refund_type == '2':
rent_refund = RentRefund()
rent_refund.refund_no = refund_no
rent_refund.production_id = production.id
rent_refund.fee = rent.one_day_price
rent_refund.comment = comment
rent_refund.created_at = datetime.datetime.now()
rent_refund.updated_at = datetime.datetime.now()
db.session.add(rent_refund)
db.session.add(production)
db.session.add(rent)
db.session.commit()
except SQLAlchemyError as e:
db.session.rollback()
raise e
return jsonify(BASE_RESPONSE().to_dict())
else:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='refund failed').to_dict())
@route_rent.route('/query_refund', methods=['GET', 'POST'])
def rent_query_refund():
json_data = request.get_json()
refund_no = json_data['refund_no'] if 'refund_no' in json_data else ''
refund_data = {
"out_refund_no": refund_no
}
result = WeChatService().query_refund_info(refund_data)
if not result:
return jsonify(BASE_RESPONSE().to_dict())
data = {}
if result['return_code'] == 'FAIL':
data['error_code'] = result['return_code']
data['error_message'] = '系统错误,请稍后再查询'
return jsonify(data)
if result['result_code'] == 'FAIL':
data['error_code'] = result['err_code']
data['error_message'] = result['err_code_des'] if 'err_code_des' in result.keys() else '退款单号异常, 请重新退款或者联系技术'
return jsonify(data)
if result['refund_status_0'] == 'SUCCESS':
data['refund_status'] = '退款成功'
data['refund_success_time'] = result['refund_success_time_0']
elif result['refund_status_0'] == 'REFUNDCLOSE':
data['refund_status'] = '退款关闭'
elif result['refund_status_0'] == 'PROCESSING':
data['refund_status'] = '退款中'
elif result['refund_status_0'] == 'CHANGE':
data['refund_status'] = '退款异常,请联系技术'
else:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='failed').to_dict())
data['refund_recv_accout'] = result['refund_recv_accout_0']
return jsonify(BASE_RESPONSE(data=data).to_dict())
@route_rent.route('/search_rent', methods=['GET', 'POST'])
def rent_search():
json_data = request.get_json()
key_word = json_data['word'] if 'word' in json_data else ''
page = json_data['page'] if 'page' in json_data else 1
limit = json_data['limit'] if 'limit' in json_data else 10
if not key_word:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='no key word').to_dict())
info = RentService.get_search_info_(key_word, int(page), int(limit))
return jsonify(BASE_RESPONSE(data=info).to_dict())
@route_rent.route('/rent_money_refund', methods=['GET', 'POST'])
def rent_money_refund():
json_data = request.get_json()
action_pwd = json_data['action_pwd'] if 'action_pwd' in json_data else ''
if action_pwd != ACTION_PWD:
return jsonify(ACTION_CODE_ERROR)
rent_no = json_data['rent_no'] if 'rent_no' in json_data else ''
hatch_no = json_data['hatch_no'] if 'hatch_no' in json_data else ''
comment = json_data['comment'] if 'comment' in json_data else ''
if not rent_no or not hatch_no or not comment:
return jsonify(PARAMETER_ERROR)
rent_info = db.session.query(Production, Rent).join(Rent, Rent.id == Production.rent_id).filter(
Production.rent_hatch_no == hatch_no, Rent.rent_no == rent_no).first()
if not rent_info:
return jsonify(REFUND_NOT_PRODUCTION_INFO)
real_total_consume = rent_info.Rent.deposit * rent_info.Rent.number - rent_info.Rent.back_money
real_single_refund = real_total_consume if real_total_consume < rent_info.Production.total else rent_info.Production.total
rent_refund_no = RentService.create_refund_no()
rent_info.Rent.back_money = rent_info.Rent.deposit * rent_info.Rent.number \
if rent_info.Rent.back_money + real_single_refund > rent_info.Rent.deposit * rent_info.Rent.number \
else rent_info.Rent.back_money + real_single_refund
rent_total = rent_info.Rent.total - rent_info.Production.total
rent_real_total = rent_info.Rent.real_total - real_single_refund
rent_info.Rent.total = rent_total if rent_total > 0 else 0
rent_info.Rent.real_total = rent_real_total if rent_real_total > 0 else 0
data = {
"out_refund_no": rent_refund_no,
"out_trade_no": rent_info.Rent.rent_no,
"total_fee": rent_info.Rent.deposit * rent_info.Rent.number,
"refund_fee": real_single_refund
}
result = WeChatService().refund(data)
if result:
try:
rent_refund = RentRefund()
rent_refund.refund_no = rent_refund_no
rent_refund.production_id = rent_info.Production.id
rent_refund.fee = real_single_refund
rent_refund.comment = comment
rent_refund.created_at = datetime.datetime.now()
rent_refund.updated_at = datetime.datetime.now()
rent_info.Production.total = 0
db.session.add(rent_refund)
db.session.add(rent_info.Rent)
db.session.add(rent_info.Production)
db.session.commit()
except SQLAlchemyError as e:
db.session.rollback()
raise e
return jsonify(BASE_RESPONSE().to_dict())
else:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='refund failed').to_dict())
# -*- coding: utf-8 -*-
import base64
import hmac
import random
import time
from flask import Blueprint, jsonify, request, g
from Libs.ErrorTips import BASE_RESPONSE
from Libs.Logger import logger
from Service.RepairService import RepairService
route_repair = Blueprint('repair', __name__)
@route_repair.route('/repair', methods=['GET', 'POST'])
def repairCreate():
json_data = request.get_json()
system_user_id = g.user.id
# system_user_id = json_data['system_user_id'] if 'system_user_id' in json_data else 0
remark = json_data['remark'] if 'remark' in json_data else ''
tel = json_data['tel'] if 'tel' in json_data else ''
pics = json_data['pics'] if 'pics' in json_data else []
spot_id = json_data['spot_id'] if 'spot_id' in json_data else ''
machine_id = json_data['machine_id'] if 'machine_id' in json_data else ''
logger.info('####### spot id #######')
logger.info(spot_id)
RepairService.create(system_user_id, remark, tel, pics, spot_id, machine_id)
return jsonify(BASE_RESPONSE().to_dict())
@route_repair.route('/tencentUploadAuthorization', methods=['POST'])
def tencentUploadAuthorization():
json_data = request.get_json()
app_id = '1255927177'
bucket = 'dev'
secret_id = 'AKIDQp9OXawOAqWAjCAr9LRRL9vcEj8QMkke'
secret_key = 'wnXDmFbqy1yoXhmldQ8kEf1GOPLBufMy'
postfix = json_data['postfix'] if 'postfix' in json_data else 'png'
filename = RepairService.guid() + '.' + postfix
pathname = '/' + app_id + '/' + bucket + '/img/' + filename
now = int(time.time())
randoma = random.randint(1, 9999999999)
expired = int(time.time()) + 300
plainText = 'a=' + app_id + '&b=' + bucket + '&k=' + secret_id + '&e=' + str(expired) + '&t=' + str(
now) + '&r=' + str(randoma) + '&f=' + pathname
bin = hmac.new(secret_key.encode('utf-8'), plainText.encode('utf-8'), 'SHA1').digest()
new_bin = bin + plainText.encode()
signature = base64.encodebytes(new_bin).decode()
signature = signature.replace("\n", "")
data = {'auth': signature, 'filename': pathname}
return jsonify(BASE_RESPONSE(data=data).to_dict())
# -*- coding: utf-8 -*-
import datetime
from flask import Blueprint, jsonify, request, g
from Libs.ErrorTips import BASE_RESPONSE
from Libs.Helper import Helper
from Model.Customer.CustomerModel import Customer
from Service.ReportService import ReportService
route_report = Blueprint('report', __name__)
@route_report.route('/chart', methods=['GET', 'POST'])
def user_chart():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
type = json_data['type'] if 'type' in json_data else 1
if type not in [1, 2, 3]:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='type error').to_dict())
yesterday = datetime.datetime.now() - datetime.timedelta(days=1)
zero_yesterday = yesterday - datetime.timedelta(hours=yesterday.hour, minutes=yesterday.minute,
seconds=yesterday.second,
microseconds=yesterday.microsecond)
last_yesterday = zero_yesterday + datetime.timedelta(hours=23, minutes=59, seconds=59)
cur_user = g.user
if cur_user.level == 1:
if type == 2:
seven_start = zero_yesterday - datetime.timedelta(days=6)
data = ReportService.get_history_rent_number_admin(spot_id, seven_start, last_yesterday)
elif type == 3:
thirty_start_date = zero_yesterday - datetime.timedelta(days=29)
data = ReportService.get_history_rent_number_admin(spot_id, thirty_start_date, last_yesterday)
else:
data = ReportService.get_today_rent_number_admin(spot_id)
return jsonify(BASE_RESPONSE(data=data).to_dict())
elif cur_user.level == 2:
if type == 2:
seven_start = zero_yesterday - datetime.timedelta(days=6)
data = ReportService.get_history_rent_number_agent(spot_id, seven_start, last_yesterday)
elif type == 3:
thirty_start_date = zero_yesterday - datetime.timedelta(days=29)
data = ReportService.get_history_rent_number_agent(spot_id, thirty_start_date, last_yesterday)
else:
data = ReportService.get_today_rent_number_agent(spot_id)
return jsonify(BASE_RESPONSE(data=data).to_dict())
else:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='Failed').to_dict())
@route_report.route('/gender')
def user_gender():
male = 0
female = 0
unknown = 0
gender_info = Customer.query.with_entities(Customer.gender).all()
for info in gender_info:
if info.gender == 1:
male += 1
elif info.gender == 2:
female += 1
else:
unknown += 1
return jsonify({'code': 200, 'msg': 'success', 'data': {'male': male, 'female': female, 'unknown': unknown}})
@route_report.route('/rent_number', methods=['GET', 'POST'])
def user_rent_number():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
number_info = ReportService.get_customer_rent_number(spot_id)
return jsonify(BASE_RESPONSE(data=number_info).to_dict())
@route_report.route('/rent_time', methods=['GET', 'POST'])
def user_rent_time():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
rent_time_info = ReportService.get_customer_rent_time(spot_id)
return jsonify(BASE_RESPONSE(data=rent_time_info).to_dict())
@route_report.route('/income_chart', methods=['GET', 'POST'])
def user_income_chart():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
data_type = json_data['type'] if 'type' in json_data else 1 # 1:七天,2:一个月,3:六个月
if int(data_type) not in [1, 2, 3]:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='type error').to_dict())
if int(data_type) == 2:
start_time, end_time = Helper.get_recent_someday_date(29)
data = ReportService.get_spot_day_income(spot_id, start_time, end_time, 30)
return jsonify(BASE_RESPONSE(data=data).to_dict())
elif int(data_type) == 3:
start_time, end_time = Helper.get_recent_six_month()
data = ReportService.get_spot_month_income(spot_id, start_time, end_time)
return jsonify(BASE_RESPONSE(data=data).to_dict())
else:
start_time, end_time = Helper.get_recent_someday_date(6)
data = ReportService.get_spot_day_income(spot_id, start_time, end_time, 7)
return jsonify(BASE_RESPONSE(data=data).to_dict())
@route_report.route('/over_record', methods=['GET', 'POST'])
def rent_over_record():
json_data = request.get_json()
spot_id = json_data['spot_id'] if 'spot_id' in json_data else 0
data_type = json_data['type'] if 'type' in json_data else 1 # 1:日,2:月
date = json_data['date'] if 'date' in json_data else ''
page = json_data['page'] if 'page' in json_data else 0
limit = json_data['limit'] if 'limit' in json_data else 10
if int(data_type) not in [1, 2]:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='type error').to_dict())
total, data = ReportService.get_spot_rent_record(spot_id, int(data_type), date, page, limit)
return jsonify({'error_code': 200, 'error_message': 'Success', 'total': total, 'data': data})
# -*- coding: utf-8 -*-
from flask import Blueprint, jsonify, g, request
from Libs.ErrorTips import BASE_RESPONSE
from Service.SpotService import SpotService
route_spot = Blueprint('spot', __name__)
@route_spot.route('/spot_info')
def all_spot_info():
info = SpotService.get_spot_info()
return jsonify(BASE_RESPONSE(data=info).to_dict())
@route_spot.route('/spot_machine_list', methods=["POST"])
def get_spot_machine_list():
json_data = request.get_json()
spot_id = json_data.get("spot_id")
info = SpotService.get_spot_machine_list(spot_id)
return jsonify(BASE_RESPONSE(data=info).to_dict())
# -*- coding: utf-8 -*-
import time
from flask import Blueprint, jsonify, request
from Libs.ErrorTips import MACHINE_NOT_EXIST_ERROR, MACHINE_HATCH_NOT_ILLEGAL, MACHINE_NOT_ONLINE, BASE_RESPONSE
from Libs.Onenet.Message.Message import CommandMessage
from Libs.Onenet.OneNetApi import OneNetApi
from Model.Base import db
from Model.Machine.MachineModel import Machine
from Model.Power.PowerModel import Power
from Service.ToolService import ToolService
route_tool = Blueprint('tool', __name__)
@route_tool.route('/power_info', methods=['GET', 'POST'])
def get_power_info():
json_data = request.get_json()
mac_no = json_data['mac_no'] if 'mac_no' in json_data else None
if not mac_no:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='illegal mac no').to_dict())
machine_info = Machine.query.filter_by(mac_no=mac_no).first()
if not machine_info:
return jsonify(MACHINE_NOT_EXIST_ERROR)
data = ToolService.get_power_info_by_machine(machine_info.id)
return jsonify(BASE_RESPONSE(data=data).to_dict())
@route_tool.route('/takeout', methods=['GET', 'POST'])
def take_out():
json_data = request.get_json()
mac_no = json_data['mac_no'] if 'mac_no' in json_data else None
hatch_no = json_data['hatch_no'] if 'hatch_no' in json_data else None
if not mac_no or not hatch_no:
return jsonify(MACHINE_HATCH_NOT_ILLEGAL)
if hatch_no > 60 or hatch_no < 1:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='mac_no or hatch_no error').to_dict())
machine_info = Machine.query.filter_by(mac_no=mac_no).first()
if not machine_info:
return jsonify(MACHINE_NOT_EXIST_ERROR)
if machine_info.life != 1:
return jsonify(MACHINE_NOT_ONLINE)
command_message = CommandMessage(machine_info.he_cloud_device_id, chr(0x46), str(hatch_no - 1))
one_api = OneNetApi()
result = one_api.send_data_to_edp(command_message.get_device_id(), 1, 0, command_message.pack())
if "errno" in result.keys() and result['errno'] == 0:
if result['error'] == 'succ':
return jsonify(BASE_RESPONSE().to_dict())
else:
if "error_message" in result.keys():
return jsonify(BASE_RESPONSE(error_message=result['error_message']).to_dict())
else:
return jsonify(BASE_RESPONSE(error_code=-1, error_message='Fail').to_dict())
@route_tool.route('/takeout_multiple', methods=['GET', 'POST'])
def take_out_multiple():
json_data = request.get_json()
mac_no = json_data['mac_no'] if 'mac_no' in json_data else None
hatch_no_list = json_data['hatch_no'] if 'hatch_no' in json_data else []
if not mac_no or not hatch_no_list:
return jsonify(MACHINE_HATCH_NOT_ILLEGAL)
machine_info = Machine.query.filter_by(mac_no=mac_no).first()
if not machine_info:
return jsonify(MACHINE_NOT_EXIST_ERROR)
if machine_info.life != 1:
return jsonify(MACHINE_NOT_ONLINE)
data = {}
for i in hatch_no_list:
command_message = CommandMessage(machine_info.he_cloud_device_id, chr(0x46), str(i - 1))
one_api = OneNetApi()
result = one_api.send_data_to_edp(command_message.get_device_id(), 1, 0, command_message.pack())
if 'errno' in result.keys() and result['errno'] == 0:
if result['error'] == 'succ':
data[i] = 'success'
Power.query.filter_by(hatch_no=i, machine_id=machine_info.id).update({'status': 8, 'has_power': 0})
db.session.commit()
else:
data[i] = 'fail'
else:
if 'error_message' in result.keys():
data[i] = result['error_message']
else:
data[i] = 'fail'
time.sleep(3)
return jsonify(BASE_RESPONSE(data=data).to_dict())
# -*- coding: utf-8 -*-
\ No newline at end of file
# -*- coding: utf-8 -*-
class BASE_RESPONSE(object):
def __init__(self, error_code=200, error_message='Success', data=None):
self.error_code = error_code
self.error_message = error_message
self.data = data
def to_dict(self):
return {'error_code': self.error_code, 'error_message': self.error_message, 'data': self.data}
TOKEN_NOT_VALID_ERROR = {
"error_code": 1001,
"error_message": "无效的token"
}
TOKEN_NOT_PROVIDER_ERROR = {
"error_code": 1002,
"error_message": "token未提供"
}
TOKEN_EXPIRE_ERROR = {
"error_code": 1003,
"error_message": "token超时"
}
PHONE_NOT_NULL_ERROR = {
"error_code": 1004,
"error_message": "手机号为空"
}
PHONE_NOT_VALID_ERROR = {
"error_code": 1005,
"error_message": "无效的手机号"
}
PHONE_NOT_PERMISSION = {
"error_code": 1006,
"error_message": "无权登录"
}
LOGIN_ERROR = {
"error_code": 1007,
"error_message": "验证码为空"
}
VERIFICATION_CODE_INVALID_ERROR = {
"error_code": 1008,
"error_message": "验证码已失效"
}
VERIFICATION_CODE_ERROR = {
"error_code": 1009,
"error_message": "验证码错误"
}
USER_NOT_EXIST = {
"error_code": 1010,
"error_message": "用户不存在"
}
PARAMETER_ERROR = {
"error_code": 1011,
"error_message": "参数有误"
}
MACHINE_HATCH_NOT_ILLEGAL = {
"error_code": 1101,
"error_message": "机柜或仓口号错误"
}
MACHINE_NOT_EXIST_ERROR = {
"error_code": 1102,
"error_message": "机柜不存在"
}
MACHINE_NOT_ONLINE = {
"error_code": 1103,
"error_message": "机柜不在线"
}
ACCOUNT_ALREADY_EXISTS_ERROR = {
"error_code": 1201,
"error_message": "该账号已存在"
}
ACCOUNT_NOT_EXISTS_ERROR = {
"error_code": 1202,
"error_message": "账号不存在"
}
ACCOUNT_ALREADY_DELETE_ERROR = {
"error_code": 1203,
"error_message": "账号已被删除"
}
ACCOUNT_AGENT_SPOT_NULL_ERROR = {
"error_code": 1204,
"error_message": "代理商景点列表为空"
}
REFUND_NOT_RENT_INFO = {
"error_code": 1301,
"error_message": "没有该订单信息"
}
REFUND_BACK_TIME_ERROR = {
"error_code": 1302,
"error_message": "归还时间异常"
}
REFUND_NOT_PRODUCTION_INFO = {
"error_code": 1303,
"error_message": "没有该讲解器信息"
}
REFUND_MONEY_IS_ZERO = {
"error_code": 1304,
"error_message": "退款金额为零"
}
OPERATE_TYPE_ERROR = {
"error_code": 1401,
"error_message": "type错误"
}
OPERATE_LEVEL_ERROR = {
"error_code": 1402,
"error_message": "权限错误"
}
OPERATE_ERROR = {
"error_code": 1403,
"error_message": "操作有误"
}
ACTION_CODE_ERROR = {
"error_code": 1501,
"error_message": "退款操作码错误"
}
# -*- coding: utf-8 -*-
import calendar
import datetime
import re
import time
def getFormatDate(date=None, format="%Y-%m-%d %H:%M:%S"):
'''
获取格式化时间
:param date: 时间
:param format: 格式
:return:
'''
if date is None:
date = datetime.datetime.now()
return date.strftime(format)
def getTodayDate():
'''
获取今天零点和24点
:return:
'''
now = datetime.datetime.now()
zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
microseconds=now.microsecond)
last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
return getFormatDate(zero_today), getFormatDate(last_today)
def getSevenDate():
'''
获取近七天零点和24点
:return:
'''
now = datetime.datetime.now()
zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
microseconds=now.microsecond)
last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
seven_start = zero_today - datetime.timedelta(days=6)
return getFormatDate(seven_start), getFormatDate(last_today)
def get_recent_someday_date(days):
now = datetime.datetime.now() - datetime.timedelta(days=1)
zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
microseconds=now.microsecond)
last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
seven_start = zero_today - datetime.timedelta(days=days)
return seven_start.strftime('%Y-%m-%d'), last_today.strftime('%Y-%m-%d')
def get_recent_six_month():
now = datetime.datetime.now()
first = now.replace(day=1)
last_month = first - datetime.timedelta(days=1)
second = last_month.replace(day=1)
last_second_month = second - datetime.timedelta(days=1)
third = last_second_month.replace(day=1)
last_third_month = third - datetime.timedelta(days=1)
four = last_third_month.replace(day=1)
last_four_month = four - datetime.timedelta(days=1)
five = last_four_month.replace(day=1)
last_five_month = five - datetime.timedelta(days=1)
six = last_five_month.replace(day=1)
last_six_month = six - datetime.timedelta(days=1)
return last_six_month.strftime('%Y%m'), last_month.strftime('%Y%m')
def getYesterdayDate():
'''
获取昨天零点和24点
:return:
'''
now = datetime.datetime.now() - datetime.timedelta(days=1)
zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
microseconds=now.microsecond)
last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
return getFormatDate(zero_today), getFormatDate(last_today)
def getWeekDate():
'''
获取本周一和周日
:return:
'''
now = datetime.datetime.now()
zero_week = now - datetime.timedelta(days=now.weekday(), hours=now.hour, minutes=now.minute, seconds=now.second,
microseconds=now.microsecond)
last_week = now + datetime.timedelta(days=6 - now.weekday(), hours=23 - now.hour, minutes=59 - now.minute,
seconds=59 - now.second)
return getFormatDate(zero_week), getFormatDate(last_week)
def getLastWeekDate():
'''
获取上周一和周日
:return:
'''
now = datetime.datetime.now()
zero_last_week = now - datetime.timedelta(days=now.weekday() + 7, hours=now.hour, minutes=now.minute,
seconds=now.second, microseconds=now.microsecond)
last_last_week = now - datetime.timedelta(days=now.weekday() + 1) \
+ datetime.timedelta(hours=23 - now.hour, minutes=59 - now.minute, seconds=59 - now.second)
return getFormatDate(zero_last_week), getFormatDate(last_last_week)
def getMonthDate():
'''
获取本月第一天和最后一天
:return:
'''
now = datetime.datetime.now()
zero_month = datetime.datetime(now.year, now.month, 1)
cur_month = now.month
cur_year = now.year
if now.month == 12:
cur_month = 0
cur_year += 1
last_month = datetime.datetime(cur_year, cur_month + 1, 1) - datetime.timedelta(days=1) + datetime.timedelta(
hours=23, minutes=59, seconds=59)
return getFormatDate(zero_month), getFormatDate(last_month)
def getLastMonthDate():
'''
获取上月第一天和最后一天
:return:
'''
now = datetime.datetime.now()
last_last_month = datetime.datetime(now.year, now.month, 1) - datetime.timedelta(days=1) + datetime.timedelta(
hours=23, minutes=59, seconds=59)
zero_last_month = datetime.datetime(last_last_month.year, last_last_month.month, 1)
return getFormatDate(zero_last_month), getFormatDate(last_last_month)
def checkPhone(phone):
phone_pat = re.compile('^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d|19\d)\d{8}$')
res = re.search(phone_pat, phone)
return res
def checkTime(start_time, end_time):
if start_time is None or end_time is None:
return 0
start_time_array = time.strptime(str(start_time), "%Y-%m-%d %H:%M:%S")
end_time_array = time.strptime(str(end_time), "%Y-%m-%d %H:%M:%S")
start_time_stamp = time.mktime(start_time_array)
end_time_stamp = time.mktime(end_time_array)
use_time = end_time_stamp - start_time_stamp
return round(use_time / 60, 2)
def get_this_month_day(date):
if date:
date_list = date.split('-')
if len(date_list) == 2:
new_date = calendar.monthrange(int(date_list[0]), int(date_list[1]))
return '-' + str(new_date[1]) + ' 23:59:59'
# -*- coding: utf-8 -*-
import logging
import os
from logging.handlers import TimedRotatingFileHandler
class Log(object):
def __init__(self, name, level=logging.DEBUG):
self.name = name
self.level = level
self.path = os.getcwd() + "/logs/"
self.formatter = logging.Formatter("%(asctime)s - %(filename)s -[line:%(lineno)d] - %(levelname)s: %(message)s",
"%Y-%m-%d %H:%M:%S")
def getLogger(self):
logger = logging.getLogger(self.name)
logger.setLevel(self.level)
# logger.addHandler(self.get_file_handler())
logger.addHandler(self.get_console_handler())
return logger
def get_file_handler(self):
file_name = "{0}{1}.log".format(self.path, self.name)
file_handler = TimedRotatingFileHandler(
filename=file_name,
when="D",
interval=1,
backupCount=7
)
file_handler.suffix = "%Y-%m-%d"
file_handler.setLevel(self.level)
file_handler.setFormatter(self.formatter)
return file_handler
def get_console_handler(self):
console_handler = logging.StreamHandler()
console_handler.setLevel(self.level)
console_handler.setFormatter(self.formatter)
return console_handler
logger = Log(name='main').getLogger()
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
class Message(metaclass=ABCMeta):
def __init__(self, device_id):
self.device_id = device_id
def get_device_id(self):
return self.device_id
def set_device_id(self, device_id):
self.device_id = device_id
@abstractmethod
def pack(self):
pass
@abstractmethod
def unpack(self, value):
pass
class CommandMessage(Message):
def __init__(self, device_id, command, *param):
super().__init__(device_id)
self.command = command
self.param = param
def get_command(self):
return self.command
def set_command(self, command):
self.command = command
def pack(self):
params = (str(i) for i in self.param)
msg = "{" + self.command + ''.join(params) + "}"
return msg
def unpack(self, value):
print('unpack')
# -*- coding: utf-8 -*-
from Libs.Onenet.Message.Message import CommandMessage
from Libs.Onenet.OneNetApi import OneNetApi
class OneNet(object):
@staticmethod
def open(machine, position):
command_message = CommandMessage(machine.he_cloud_device_id, chr(0x46), str(position - 1))
one_api = OneNetApi()
result = one_api.send_data_to_edp(command_message.get_device_id(), 1, 0, command_message.pack())
if not result or result.get("error", None) is not None:
return False
return True
# -*- coding: utf-8 -*-
import json
import time
import urllib.parse
import requests
from Config.common_config import ONENET_CONFIG as config
class OneNetApi(object):
_key = None
_base_url = 'http://api.heclouds.com'
_raw_response = ''
_http_code = 200
_error_no = 0
_error = ''
_ALLOW_METHODS = ['GET', 'PUT', 'POST', 'DELETE']
def __init__(self, key=None, base_url=None):
self._key = key
if base_url:
self._base_url = base_url
def get_raw_response(self):
return self._raw_response
def get_error(self):
return self._error
def get_error_no(self):
return self._error_no
def get_http_code(self):
return self._http_code
def get_cur_api_key(self):
return config["api_key"]
def device(self, id):
if not id:
return False
api = '/devices/{}'.format(id)
return self._call(api)
def device_list(self, page=1, page_size=30, key_words=None, tag=None, is_online=None, is_private=None,
device_ids=None):
params = {"page": 1, "page_size": 30}
if isinstance(page, int):
params["page"] = page if page else 1
if isinstance(page_size, int):
params["page_size"] = page_size if page_size else 30
if key_words:
params["key_words"] = key_words
if tag:
params["tag"] = tag
if is_private:
params["is_private"] = is_private
if device_ids:
params["device_ids"] = device_ids
if is_online:
params["is_online"] = "true"
params_str = urllib.parse.urlencode(params)
api = '/devices?' + params_str
return self._call(api)
def device_add(self, device):
api = '/devices'
return self._call(api, method="POST", data=device)
def device_edit(self, id, device):
if not id:
return False
api = '/devices/{}'.format(id)
return self._call(api, "PUT", device)
def device_delete(self, id):
if not id:
return False
api = "/devices/{id}".format(id=id)
return self._call(api, 'DELETE')
def datastream(self, device_id, datastream_id):
"""
数据流相关
:param device_id: 设备id
:param datastream_id:数据流id
:return: False表示失败, json数据表示返回价格
"""
if not device_id or not datastream_id:
return False
datastream_id = str(datastream_id).replace(" ", "%20")
api = "/devices/{0}/datastreams/{1}".format(device_id, datastream_id)
return self._call(api)
def datastream_of_dev(self, device_id):
"""
获取某个设备下面的数据流
:param device_id: 设备id
:return:
"""
if not device_id:
return False
api = '/devices/{}/datastreams'.format(device_id)
return self._call(api)
def datastream_add(self, device_id, datastream):
"""
新增数据流
:param device_id:设备id
:param datastream: 数据流
:return:
"""
if not device_id or not datastream:
return False
api = '/devices/{}/datastreams'.format(device_id)
return self._call(api, "POST", datastream)
def datastream_edit(self, device_id, datastream_id, datastream):
if not device_id or datastream_id or datastream:
return False
api = '/devices/{0}/datastreams/{1}'.format(device_id, datastream_id)
return self._call(api, "PUT", datastream)
def datastream_delete(self, device_id, datasteam_id):
if not device_id or not datasteam_id:
return False
api = '/devices/{}/datasteams/{}'.format(device_id, datasteam_id)
return self._call(api, "DELETE")
def datapoint_add(self, device_id, datastream_id, datas):
"""
添加数据点
:param device_id:
:param datastream_id:
:param datas: {timestamp:data}
:return:
"""
if not datas:
return True
if not device_id or not datastream_id:
return False
datastream_data = []
for k, v in datas.items():
k = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(k))
datastream_data.append({
"at": k,
"value": v
})
api_data = {
"datastreams": {
"id": datastream_id,
"datapoints": datastream_data
}
}
api = "/devices/{device_id}/datapoints".format(device_id=device_id)
return self._call(api, "POST", api_data)
def datapoint_multi_add(self, device_id, datas):
"""
多个datastream一次添加
:param device_id:
:param datas: {'datastream_id':{'timestamp':data}}
:return:
"""
if not datas:
return True
if not device_id:
return False
api_data = {
"datastreams": []
}
for datastream_id, value in datas.items():
datastream_data = []
for k, v in value.items():
k = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(k))
datastream_data.append({
"at": k,
"value": v
})
if not datastream_data:
continue
api_data["datastreams"].append({
"id": datastream_id,
"datapoints": datastream_data
})
api = "/devices/{device_id}/datapoints".format(device_id=device_id)
return self._call(api, "POST", api_data)
def datapoint_get(self, device_id, datastream_id, start_time=None, end_time=None, limit=None, cursor=None):
"""
2015-04-13 OneNet更新后,将不再支持以下参数:
sort_time 可选,指定时按时间倒序排,最新时间在前面
page 指定页码, 可选
per_page 指定每页输出数据点个数,可选, 默认300,最多1000
当前datastream更像是数据流的操作。废弃之前 datapoint_list, datapoint_multi_list 方法
:param datastream_id:
:param start_time:
:param end_time:
:param limit:
:param cursor:
:return:
"""
if not device_id or datastream_id:
return False
return self.datapoint_multi_get(device_id, start_time, end_time, limit, cursor, datastream_id)
def datapoint_multi_get(self, device_id, start_time=None, end_time=None, limit=None, cursor=None,
datastream_ids=None):
# TODO 暂时用不到,等待开发
if not device_id:
return False
params = {}
if datastream_ids:
if isinstance(datastream_ids, list):
datastream_ids = ",".join(datastream_ids)
params["datastream_id"] = datastream_ids
pass
def datapoint_delete(self, device_id, datastream_id, start_time=None, end_time=None):
# TODO 暂时用不到,等待开发
pass
def datapoint_multi_delete(self, device_id, start_time=None, end_time=None):
# TODO 暂时用不到,等待开发
pass
def trigger(self, trigger_id):
# TODO 暂时用不到,等待开发
pass
def trigger_list(self, page=None, per_page=None, title=None):
# TODO 暂时用不到,等待开发
pass
def trigger_add(self, trigger):
# TODO 暂时用不到,等待开发
pass
def trigger_edit(self, trigger_id, trigger):
# TODO 暂时用不到,等待开发
pass
def trigger_delete(self, trigger_id):
# TODO 暂时用不到,等待开发
pass
def api_key(self, dev_id=None, key=None, page=None, per_page=None):
# TODO 暂时用不到,等待开发
pass
def api_key_add(self, dev_id, title):
# TODO 暂时用不到,等待开发
pass
def api_key_edit(self, key, title, resource=None):
# TODO 暂时用不到,等待开发
pass
def api_key_delete(self, api_key):
# TODO 暂时用不到,等待开发
pass
def request_log(self, device_id, start_time):
# TODO 暂时用不到,等待开发
pass
def send_data_to_edp(self, device_id, qos, timeout, sms):
if not device_id:
return False
api = "/cmds?device_id={device_id}&qos={qos}&timeout={timeout}".format(device_id=device_id, qos=qos,
timeout=timeout)
return self._call(api, "POST", sms)
def send_data_to_mqtt(self, topic, sms):
# TODO 暂时用不到,等待开发
pass
def get_dev_status(self, cmd_uuid):
# TODO 暂时用不到,等待开发
pass
def get_dev_status_resp(self, cmd_uuid):
# TODO 暂时用不到,等待开发
pass
def _startendtime_to_startduration(self, start_time, end_time):
# TODO 暂时用不到,等待开发
pass
def _call(self, url, method="GET", data=None, heasers=None):
result = self._rawcall(url, method, data, heasers)
if not result:
return False
return result
def _rawcall(self, url, method, data=None, heasers=None):
url = self._paddingUrl(url)
self._error_no = 0
self._error = None
if not url:
self._http_code = 500
return False
if method not in self._ALLOW_METHODS:
self._http_code = 500
return False
if heasers:
heasers = heasers
kwargs = {"headers": {"api-key": self.get_cur_api_key()}}
if data:
if isinstance(data, list) or isinstance(data, dict):
data = json.dumps(data).encode('utf-8')
kwargs["data"] = data
if heasers:
kwargs["headers"].update(heasers)
result = requests.request(method, url, **kwargs)
print(result.text)
if result:
self._http_code = result.status_code
result = json.loads(result.text)
return result
else:
return {}
def _paddingUrl(self, url):
if not url:
return url
if url[0] != '/':
url = '/' + url
return config["url"] + url
def _beforeCall(self, ch, url, method, data):
pass
def _afterCall(self, ch, url, method, data, ret):
pass
def _afterDecode(self, url, method, data, ori_ret, ret):
pass
-----BEGIN CERTIFICATE-----
MIIEbDCCA9WgAwIBAgIEAWJK2zANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xNzA4MDcwOTAwNDZa
Fw0yNzA4MDUwOTAwNDZaMIGbMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdk
b25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UE
CxMFTU1QYXkxMDAuBgNVBAMUJ+iLj+W3numaj+i6q+eOqeS/oeaBr+aKgOacr+ac
iemZkOWFrOWPuDERMA8GA1UEBBMINDEyOTEyMTcwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDeUEFC0H3NiPALgWZQGtAEFoyiAMEcGKWKxDAXA+7RTzkH
Y6rRqWa4UtmLn+y2Dq3Bqj0JV9/hpxH4XDGmyVEPoeX1vrvjY+hZa5vsHo5iAowC
+/5tfbSK0MCIqLVu32RUL/2XNKzu1uI9qJCyG5S5xviwY+LUsIiQVSYS68xxPmQi
UvB/Si7nPVu8flQp/CErGj67+UnfRstzdlXmIedVZI2B/zDY36GWz99OcC1vKAoH
1Qyr0djSPKUjBW728SgKgt7koS1DV4tQdd+Z3d0JUMaf1xC3HQgYxrIsOAo/mRki
fCvRG19WB6UgQn57pAPQ1aRmc8uHoc4K0t5PG3z3AgMBAAGjggFGMIIBQjAJBgNV
HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh0iQ0VTLUNBIEdlbmVyYXRlIENlcnRpZmlj
YXRlIjAdBgNVHQ4EFgQUkwjPtBG/QHSUDjRnzQs7jkYgkHwwgb8GA1UdIwSBtzCB
tIAUPgUm9iJitBVbiM1kfrDUYqflhnShgZCkgY0wgYoxCzAJBgNVBAYTAkNOMRIw
EAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdU
ZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAdBgkq
hkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnSCCQC7VJcrvADoVzAOBgNVHQ8BAf8E
BAMCBsAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEA
NkWBjd8qNtg5LT8u+lns5kmoqMgJmPqWsLkeAdDzGQgk0umVIivnbvjBK9gyQDo8
M3uQjHDOeoL9kpYQoZCzcC/0NqMluXjmvfXiarc1lv2RYu4nNoUVp4ix/15dFhML
pS65pTZ3LXXDigY76nFOu6XztJNvylnDZ/c7nejsC3g=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDeUEFC0H3NiPAL
gWZQGtAEFoyiAMEcGKWKxDAXA+7RTzkHY6rRqWa4UtmLn+y2Dq3Bqj0JV9/hpxH4
XDGmyVEPoeX1vrvjY+hZa5vsHo5iAowC+/5tfbSK0MCIqLVu32RUL/2XNKzu1uI9
qJCyG5S5xviwY+LUsIiQVSYS68xxPmQiUvB/Si7nPVu8flQp/CErGj67+UnfRstz
dlXmIedVZI2B/zDY36GWz99OcC1vKAoH1Qyr0djSPKUjBW728SgKgt7koS1DV4tQ
dd+Z3d0JUMaf1xC3HQgYxrIsOAo/mRkifCvRG19WB6UgQn57pAPQ1aRmc8uHoc4K
0t5PG3z3AgMBAAECggEAIepAan8AEjEH3dl50FKm1VjTT4up6i1gY9EWPQyejFP3
sUblMmMThp8tDP3y0LtgiqD7+sbrIrOoLCl0catYsHfUay8T3tbJBYtDGDx5ID6f
OX1UDUQWHO9H0BFczHNMDQPdPgoNL8qcbSegG2vVvpm6Kr6yRhxAWTSEQHK0l7nS
F30WM0uTtu4iaJi71MCvZZSHiRkr1hJettfeECJYZoCxxKpI/+DXV2bi1xVbyBTl
k4/n6sBV7lSS5ELsm4RGkV9YIMuHmjeV0qGn4pnvt79tCK72KAP5a06OorrVHUqH
IKymJqi8MTPceI4h2D2Q3XN0YUUjAsko2bg54kQBgQKBgQD4dck0IizWQdu2fb3W
n/42I7XEA9YtgXuiQRAnSgzTi6Yk98vcVyDDUi4xfw8JzxvPSpIlItJVEEiQSJOt
9nK6VXW5ZAGiG6C2RKrtZ4bWEYmp57C0mu3Q3X7NBez/mRkvkc2p64ZN4o9p4pBL
NKow0EFH+0LaTVHkgef39Qh91wKBgQDlD1f3p8jtClIYMYKrLjW7wUmd2+o+VpFT
Dkfx39Kx9GzS0UdpwUAXdrWX8a9q33raMj0hih5GSc0hYOA+TVZ7feZxwDwvfsra
uY/9Z7ShoYKs35Tz0i6quqQtbOz47bDo63uvivf8C/juXR+tdJFt8Dw7he9v7IT5
sduzVXfV4QKBgQCGJFmf+v+IIgB0k4jF8pV2N2twS737zZepb0VAYRtxr0jhVqPK
74Nx0NG9yWKeIiJalWE4CYfTgzoaJAUPfCpO7crkb9jt48qt/X7nM+i5dLiFceCW
cbsJ9Dv8h0GAcfEGHMsT/WQCctqJCVhsMh/cwOMt8LsUT4ByRayu061k+wKBgQC0
Pz22uUZoGS3+sb8kWwmXhIMcgHg0s8RJujws/jb7J98Wie6LLrHzhMtjFKE4FUHE
P7JRGTG3l82ejXAINq1uIeVb76yspzaTpV/ERX4jjkeZJ5s7vlJQsOwOft9/BvOm
Zd9/hHid0wIA+DC8OrVR8LBFGqEOzuzY2/eJiCDzoQKBgQDmPl4D02GIeORgO46R
/SVVMdK4/wz9OhwaWX2NNkHi6d5YZjR+e0w7XmmmT1n8C+Dcf0i3EdSCH2ci9kYU
dQ5A0wHPVYX1tw6yeqQYXYyfVHwcLCZO4sTJXUwD2OZ4AncjhI3PG1YnhJUov0Y8
dVXi8bkgyP/Wo47YevasN7t2qQ==
-----END PRIVATE KEY-----
Bag Attributes
friendlyName: ޏo/ Pl
localKeyID: 54 69 6D 65 20 31 35 37 39 30 35 33 34 35 35 35 37 37
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHP9QLh1+lz1zm8
BtfzJpbESBlZhhrSRzgCDVLDJs1nVawe5jSK7xK93Q89oarPy/pJEA33ChezSfWD
UAiY/0Md5e+A1LgP/TPWdPFkSaI2GyNifz4XqffwlHW9tM8gS9/4gjWKXcxaQ2UZ
fPtnRK0SNVIq+zQ6RQ/q7nb3QYR5AgMBAAECgYBlGnYp/zJr3SjtOamawMxzTpi1
eObZVXL7ubd7adMSvoSWVxNdTSNzsbyrWT3sO7OpcVMV3ZkQOX8QxOVtpAsNi0eH
sKZd8l+I41d0RIMIbiWhicXC64vZy4VO0hrCCiIJ+6k0e0xX80++b/tuXiuCuOST
Fo1zgBV2Epcx7WYPjQJBAP7ao0KNPKVcvF4fx8LP3FLFtrsLsCpZF38WbzK3IVIA
YpZovoaxFuP8UFgMKXiyxQWgFwFK34PBI/D1kfxZqIcCQQDi0+OyfxYRRHCAFe59
BcPjeQXQ7K/GZfyesUdGPNVl6l5nzbfrYy+osJ0TpKPRd2cU4s8BYJtd/3dz9FX2
76r/AkBxzI86GHcMH+y82tQIWWi4TTDbNMzlHAMx7IKa0ss+Io3jO8JXwpvGEdSO
fF/IVYtEh8e9/ADyhDvYTM9zL1XhAkA935jL9vi5Cxc5CUJ93hW6NigM/pNQJj/L
tgYANdXsMAtCe45A6lR0yoB+fDmniM+YlenrsUOQV4BpI+xTKLtXAkA1EnstEXVP
M2DaEbHy4K7wjtcZxSdvOMrw/GMf+Zwp/6mnhFrx7wYVFmM0rD0z2dUzQaAJu9E8
hVKcbRGrlRfY
-----END PRIVATE KEY-----
Bag Attributes
friendlyName: ޏo/ Pl
localKeyID: 54 69 6D 65 20 31 35 37 39 30 35 33 34 35 35 35 37 37
subject=/C=CN/ST=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81/L=\xE6\xB7\xB1\xE5\x9C\xB3\xE5\xB8\x82/O=\xE8\x8B\x8F\xE5\xB7\x9E\xE9\x9A\x8F\xE8\xBA\xAB\xE7\x8E\xA9\xE4\xBF\xA1\xE6\x81\xAF\xE6\x8A\x80\xE6\x9C\xAF\xE6\x9C\x89\xE9\x99\x90\xE5\x85\xAC\xE5\x8F\xB8/OU=913205943138134162/CN=\xE8\x8B\x8F\xE5\xB7\x9E\xE9\x9A\x8F\xE8\xBA\xAB\xE7\x8E\xA9\xE4\xBF\xA1\xE6\x81\xAF\xE6\x8A\x80\xE6\x9C\xAF\xE6\x9C\x89\xE9\x99\x90\xE5\x85\xAC\xE5\x8F\xB8
issuer=/C=CN/ST=Guangdong/L=Shenzhen/O=fapiao.com/OU=fapiao.com/CN=FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIIDKzCCAhOgAwIBAgILAav439MuoTwyGG8wDQYJKoZIhvcNAQELBQAwczELMAkG
A1UEBhMCQ04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4x
EzARBgNVBAoTCmZhcGlhby5jb20xEzARBgNVBAsTCmZhcGlhby5jb20xEzARBgNV
BAMTCkZBUElBTy5DT00wIBcNMjAwMTE1MDE1NzM1WhgPMjA1MDAxMDcwMTU3MzVa
MIG2MQswCQYDVQQGEwJDTjESMBAGA1UECAwJ5bm/5Lic55yBMRIwEAYDVQQHDAnm
t7HlnLPluIIxMDAuBgNVBAoMJ+iLj+W3numaj+i6q+eOqeS/oeaBr+aKgOacr+ac
iemZkOWFrOWPuDEbMBkGA1UECxMSOTEzMjA1OTQzMTM4MTM0MTYyMTAwLgYDVQQD
DCfoi4/lt57pmo/ouqvnjqnkv6Hmga/mioDmnK/mnInpmZDlhazlj7gwgZ8wDQYJ
KoZIhvcNAQEBBQADgY0AMIGJAoGBAOHP9QLh1+lz1zm8BtfzJpbESBlZhhrSRzgC
DVLDJs1nVawe5jSK7xK93Q89oarPy/pJEA33ChezSfWDUAiY/0Md5e+A1LgP/TPW
dPFkSaI2GyNifz4XqffwlHW9tM8gS9/4gjWKXcxaQ2UZfPtnRK0SNVIq+zQ6RQ/q
7nb3QYR5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD0akYERYKvOtwZywEQa0SW6
6q9zRYzuxD9GlW1jqDYMnnorJeseasMDrzOv2OG1zR4foIen80gMS1d1KV1PzGVo
HQI84/xrdAxRuvolbHlcUOQD9wxXZe6985hygWI4cCIKTzSGIFNkH+wPQbtzJFSV
+k0526JitlhWNCG3pCAYPNiB+Hv3DzTDJsHJ/Q0g5wS2s0jSvKqNZQrwzQJfaj7X
pUq+48EieATuq9yze22zC6EdTScScJV4BHagQ3Nt+kXs4IiVomOYtdQzhZPLBnfb
Rpb5x1pgCG5AKGkiwUs4OW//RrSgskT2KOJl+N9xVYCx+eeM1pblF/h10Jwir6E=
-----END CERTIFICATE-----
Bag Attributes
friendlyName: CN=FAPIAO.COM,OU=fapiao.com,O=fapiao.com,L=Shenzhen,ST=Guangdong,C=CN
subject=/C=CN/ST=Guangdong/L=Shenzhen/O=fapiao.com/OU=fapiao.com/CN=FAPIAO.COM
issuer=/C=CN/ST=Guangdong/L=Shenzhen/O=fapiao.com/OU=fapiao.com/CN=FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIID0zCCArugAwIBAgIBATANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJDTjES
MBAGA1UECBMJR3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjETMBEGA1UEChMK
ZmFwaWFvLmNvbTETMBEGA1UECxMKZmFwaWFvLmNvbTETMBEGA1UEAxMKRkFQSUFP
LkNPTTAeFw0xNzAzMTcwMDAwMDBaFw00NzAzMTcwMDAwMDBaMHMxCzAJBgNVBAYT
AkNOMRIwEAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRMwEQYD
VQQKEwpmYXBpYW8uY29tMRMwEQYDVQQLEwpmYXBpYW8uY29tMRMwEQYDVQQDEwpG
QVBJQU8uQ09NMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzYNOZvkd
6gHrJ1HmiymABAYZv301G6gl3oRTXCjHuSymAtLiBIH2JNkc3RPbLGVhrfBDl+DO
W/cLZw1uamSmu+eaPkm2BN0jOR8Tsl157jNqNCaW7KFtuTrRJMknpdJ8BRIyF5V6
g9US+KyodJA0oyF5pZPSWhyPE13EWR1d7cMxNReM0XBL9A5Pg+IS8X2LmE1Ao+uL
ALEz7Rz7RMpVhpZbR/r6ffWFrvSrPrmJg2aA+KjUHWEOx96mTFCRRUY8JkqaV4Pp
9SVdee/u00gqdK9DFPsMvFWt9s9olSUoGujTFbrVxcHBdBgGSnoBLdohmHM49F6d
WGwWJLZgrqj2JwIDAQABo3IwcDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSE
Fk9/I8TFerc3y4O/q1OWCdTBOTALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQD
AgAHMB4GCWCGSAGG+EIBDQQRFg94Y2EgY2VydGlmaWNhdGUwDQYJKoZIhvcNAQEL
BQADggEBAGvzauj7RHJSFe3IlzNHunLJKKsTi6vOhVSR0J1RtmVRI1Pu1qcUkhpN
OiLhVbR/yhbEP1YfepqubP0E3rx70RIzYhhUxsHobmC/tu2/iKkX3IbFV0h2JI3Y
TjtdsxE64TJUbiLpq+gaIQTA0uZaQQ+Zpnh19rFbxLEzw8a9TSQS845eXX5LHUH3
ndpc6gMI4K1r36sZvd0MKbX2mOGPOD5tjnAsZDEndcxoL9z/A4ylh7mYuuYtR1GR
fC7a7hMSX9iPy1pMyc6mTq6WzLuJM81+UYjzNxXZEHmXkoziw2wI1n8SWveTN6Pi
oBFqXBY8Xqaz5nSPve3PLd6xYro7bBQ=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF5TCCBM2gAwIBAgIQHYtZAdpWwLET8sFQNsSUzDANBgkqhkiG9w0BAQsFADBE
MQswCQYDVQQGEwJDTjEaMBgGA1UECgwRV29TaWduIENBIExpbWl0ZWQxGTAXBgNV
BAMMEFdvU2lnbiBPViBTU0wgQ0EwHhcNMTcwODA4MDc1NTA2WhcNMjAwODA2MDc1
NTA2WjCBkzELMAkGA1UEBhMCQ04xRTBDBgNVBAoMPOeZvuacm+eUteWtkOWPkeel
qOaVsOaNruacjeWKoeaciemZkOWFrOWPuOa3seWcs+i/kOiQpeS4reW/gzESMBAG
A1UEBwwJ5rex5Zyz5biCMRIwEAYDVQQIDAnlub/kuJznnIExFTATBgNVBAMMDCou
ZmFwaWFvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMe68gUh
2LHtow0SIGBhBbZlFXclyhSdr+gkPPAW4WeEBtiXwFcTBykZV3hbwqvXeC/npmnd
cuTMlovjdcheIE377ivzqvgJTBwQVhFpI3/gFvrPbdF2Pm8TQTjkoirQjMjeHRyh
rxo1gRRoVR8MI3q/C6CgYG2tqgVMC/lgluX36OT+Pzzotbqnurf2IrzWVDiwTFXQ
dQelAH2WV8m3nw5A/hu9/WnIDorK0Q3VSEx53Md1iYy1oHj13h5/cvmRXSl3P7oS
mrADHp63XRiQiG+vgIrcGOkw5aSo3Xu7eGt1+maOj2NGHfTZRy0UnROrpt+E9m8+
rZvgkmfNgMi0r4cCAwEAAaOCAoEwggJ9MAwGA1UdEwEB/wQCMAAwPAYDVR0fBDUw
MzAxoC+gLYYraHR0cDovL3dvc2lnbi5jcmwuY2VydHVtLnBsL3dvc2lnbi1vdmNh
LmNybDB3BggrBgEFBQcBAQRrMGkwLgYIKwYBBQUHMAGGImh0dHA6Ly93b3NpZ24t
b3ZjYS5vY3NwLWNlcnR1bS5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly9yZXBvc2l0
b3J5LmNlcnR1bS5wbC93b3NpZ24tb3ZjYS5jZXIwHwYDVR0jBBgwFoAUoRNU3FZz
LCeCysiE7+6/AP1fq1YwHQYDVR0OBBYEFN+JmFD32Qxm6NjMJst5qqtwv3NvMA4G
A1UdDwEB/wQEAwIFoDCCASAGA1UdIASCARcwggETMAgGBmeBDAECAjCCAQUGDCqE
aAGG9ncCBQEMAjCB9DCB8QYIKwYBBQUHAgIwgeQwHxYYQXNzZWNvIERhdGEgU3lz
dGVtcyBTLkEuMAMCAQEagcBVc2FnZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN0
cmljdGx5IHN1YmplY3RlZCB0byB0aGUgQ0VSVFVNIENlcnRpZmljYXRpb24gUHJh
Y3RpY2UgU3RhdGVtZW50IChDUFMpIGluY29ycG9yYXRlZCBieSByZWZlcmVuY2Ug
aGVyZWluIGFuZCBpbiB0aGUgcmVwb3NpdG9yeSBhdCBodHRwczovL3d3dy5jZXJ0
dW0ucGwvcmVwb3NpdG9yeS4wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
MCMGA1UdEQQcMBqCDCouZmFwaWFvLmNvbYIKZmFwaWFvLmNvbTANBgkqhkiG9w0B
AQsFAAOCAQEAVbW/dkDpLso5ysVgzj6Tpaida0LXvRcfWzoFIi6WHMU4hGNNcdPh
K9bRHys8ue6WjuC170pFhKeSmrF/ph4xIGd66a/zM4IrJwFKn1xnbHEZNJBCtEfJ
x19zQUd9EkHZDqpj+pWZFVf7Cwzw7IPuCSZShZr7FZLX8Muddpv+gP158yDzw0tH
RClcsSgNjQntjxWvAt8O91Xgr3+YK0h2v0t51Lj7GOsz7Wb4jAB+5dD2lBpXjCrU
EEIqSsdypwLY8cvVbB93Nvg1LDTFrS27Gzu4Nr+7/RvtvsVmppy9bhxzbwOgO4TL
D3E3nXiSFBBYlfk1jEp9ywrRi7Fj2Vm2Wg==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCXsNL6cWpwZ2rEtUNKCF2ogaMJSqdeHoeMQq4YwP+FpEcrWupl
nkOGundwMZaXDG522PjQeR4AVXPUQ8jy8y5GwbUVi6Mmx2p3r1V0OfJ3G1gLdTcI
mAGfunYM3QJIEy6rdznb1pU5sm0UHOQPliJODhlVLPxfAxVkwEdM6DMp/QIDAQAB
AoGAadyskL2gI8v4tkkuKbeG7XdzeaORBF1YCanraDkg2nqYdIhhdwOpapgtjK3+
w3GYkfbARnWQW3lHecbIsczG6N5m8k8wXkX/p485nQB00kBjS46y4rxsdW6sDjTp
L/0xvlWNUZNlpSvMEzxPxM2lMlq/lFSpittFaX7KntfOxF0CQQD28Y2sM+xOPRqz
/FWtwmzlUWS87RQWhXBWDR4MS5gD4iNr8ljBQwvKZiMjKTnsy5lekbmnEfXXFFpq
W8zyd4fDAkEAnUD7mxD2ix9OM0NsWTtH3mu8wZPqELSlI+NVYm9c6TM+7njvTS+E
pkrAXfnaYhpW/RAROFbDtTw0S/1j/mkrPwJATbcNYAFjP+gpDDXAfROwE6c+7doq
tT+/b8VnDHWJ3McBYMp/Nis0fbkRG9KwoR4eIU35QGP9m3eTUN+dKz2E4wJBAJCt
A48DyT/v2ltxkZJ65sEsb+nM8xDRkgl1ks3QVTO70Q9HtipWKH1x0o/jWlbdkuCa
Uq15re7k59xt0Px0t7MCQQCa+aOmU8A9O2sdhnMN+AWlFxNIPvgW2zp1d3qvl7mE
qvUu6m/3pl9ZvGSE23EvQMx8zBcMQSJB8OHtIIjX1i1j
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCXsNL6cWpwZ2rEtUNKCF2ogaMJSqdeHoeMQq4YwP+FpEcrWupl
nkOGundwMZaXDG522PjQeR4AVXPUQ8jy8y5GwbUVi6Mmx2p3r1V0OfJ3G1gLdTcI
mAGfunYM3QJIEy6rdznb1pU5sm0UHOQPliJODhlVLPxfAxVkwEdM6DMp/QIDAQAB
AoGAadyskL2gI8v4tkkuKbeG7XdzeaORBF1YCanraDkg2nqYdIhhdwOpapgtjK3+
w3GYkfbARnWQW3lHecbIsczG6N5m8k8wXkX/p485nQB00kBjS46y4rxsdW6sDjTp
L/0xvlWNUZNlpSvMEzxPxM2lMlq/lFSpittFaX7KntfOxF0CQQD28Y2sM+xOPRqz
/FWtwmzlUWS87RQWhXBWDR4MS5gD4iNr8ljBQwvKZiMjKTnsy5lekbmnEfXXFFpq
W8zyd4fDAkEAnUD7mxD2ix9OM0NsWTtH3mu8wZPqELSlI+NVYm9c6TM+7njvTS+E
pkrAXfnaYhpW/RAROFbDtTw0S/1j/mkrPwJATbcNYAFjP+gpDDXAfROwE6c+7doq
tT+/b8VnDHWJ3McBYMp/Nis0fbkRG9KwoR4eIU35QGP9m3eTUN+dKz2E4wJBAJCt
A48DyT/v2ltxkZJ65sEsb+nM8xDRkgl1ks3QVTO70Q9HtipWKH1x0o/jWlbdkuCa
Uq15re7k59xt0Px0t7MCQQCa+aOmU8A9O2sdhnMN+AWlFxNIPvgW2zp1d3qvl7mE
qvUu6m/3pl9ZvGSE23EvQMx8zBcMQSJB8OHtIIjX1i1j
-----END RSA PRIVATE KEY-----
Bag Attributes
localKeyID: 91 7A D8 5B 8B 8D 00 24 4F AE DE 99 5C 59 AF A0 E5 32 A6 58
subject=/C=CN/ST=SC/L=CD/O=BenZeph/OU=ISI/CN=\xE6\xB5\x8B\xE8\xAF\x95\xE8\xAF\x81\xE4\xB9\xA6
issuer=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIIC2TCCAcGgAwIBAgIENNsNsjANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UEBxMIU0hFTlpIRU4xGDAWBgNV
BAoTD3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMPdGVzdC5mYXBpYW8uY29tMRgw
FgYDVQQDEw9URVNULkZBUElBTy5DT00wHhcNMTcwMzIxMDcyMjQxWhcNMjcwMzE5
MDcyMjQxWjBeMQswCQYDVQQGEwJDTjELMAkGA1UECBMCU0MxCzAJBgNVBAcTAkNE
MRAwDgYDVQQKEwdCZW5aZXBoMQwwCgYDVQQLEwNJU0kxFTATBgNVBAMMDOa1i+iv
leivgeS5pjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAl7DS+nFqcGdqxLVD
SghdqIGjCUqnXh6HjEKuGMD/haRHK1rqZZ5Dhrp3cDGWlwxudtj40HkeAFVz1EPI
8vMuRsG1FYujJsdqd69VdDnydxtYC3U3CJgBn7p2DN0CSBMuq3c529aVObJtFBzk
D5YiTg4ZVSz8XwMVZMBHTOgzKf0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhUT1
TQQ9Ur+oqKhm25RGyu9IpKi3ZXIoHSUEsVISMEcbr3jvGxcD1ICUE7VytWJGpxFL
kbVbvftaIlUgnqqAjl4f6CRjTNg3Jlx+edS04AzRINWnIqNyABCa4+J3w850DFu4
Jl0ho+ic7Y7mluuvPKeKnWSJIR9letDaaq++hXBT8Pq+VQ4O2hD+XnOvsWYmQGlf
MwLILG9QKpJXVnvbYy1MZY/56mKTWGyMCS/B9OTfx9G2o7PghBoAgbkzcv6GK/l+
WG4qCN4jdTQgaGirSXpMbPBb3OyKSiCZtN1mruja5SbG0Nft8n5/Zx/APHxsYkve
NBMsCYpEjCGr6IaPUw==
-----END CERTIFICATE-----
Bag Attributes
localKeyID: 91 7A D8 5B 8B 8D 00 24 4F AE DE 99 5C 59 AF A0 E5 32 A6 58
Key Attributes: <No Attributes>
-----BEGIN CERTIFICATE-----
MIIF5TCCBM2gAwIBAgIQHYtZAdpWwLET8sFQNsSUzDANBgkqhkiG9w0BAQsFADBE
MQswCQYDVQQGEwJDTjEaMBgGA1UECgwRV29TaWduIENBIExpbWl0ZWQxGTAXBgNV
BAMMEFdvU2lnbiBPViBTU0wgQ0EwHhcNMTcwODA4MDc1NTA2WhcNMjAwODA2MDc1
NTA2WjCBkzELMAkGA1UEBhMCQ04xRTBDBgNVBAoMPOeZvuacm+eUteWtkOWPkeel
qOaVsOaNruacjeWKoeaciemZkOWFrOWPuOa3seWcs+i/kOiQpeS4reW/gzESMBAG
A1UEBwwJ5rex5Zyz5biCMRIwEAYDVQQIDAnlub/kuJznnIExFTATBgNVBAMMDCou
ZmFwaWFvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMe68gUh
2LHtow0SIGBhBbZlFXclyhSdr+gkPPAW4WeEBtiXwFcTBykZV3hbwqvXeC/npmnd
cuTMlovjdcheIE377ivzqvgJTBwQVhFpI3/gFvrPbdF2Pm8TQTjkoirQjMjeHRyh
rxo1gRRoVR8MI3q/C6CgYG2tqgVMC/lgluX36OT+Pzzotbqnurf2IrzWVDiwTFXQ
dQelAH2WV8m3nw5A/hu9/WnIDorK0Q3VSEx53Md1iYy1oHj13h5/cvmRXSl3P7oS
mrADHp63XRiQiG+vgIrcGOkw5aSo3Xu7eGt1+maOj2NGHfTZRy0UnROrpt+E9m8+
rZvgkmfNgMi0r4cCAwEAAaOCAoEwggJ9MAwGA1UdEwEB/wQCMAAwPAYDVR0fBDUw
MzAxoC+gLYYraHR0cDovL3dvc2lnbi5jcmwuY2VydHVtLnBsL3dvc2lnbi1vdmNh
LmNybDB3BggrBgEFBQcBAQRrMGkwLgYIKwYBBQUHMAGGImh0dHA6Ly93b3NpZ24t
b3ZjYS5vY3NwLWNlcnR1bS5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly9yZXBvc2l0
b3J5LmNlcnR1bS5wbC93b3NpZ24tb3ZjYS5jZXIwHwYDVR0jBBgwFoAUoRNU3FZz
LCeCysiE7+6/AP1fq1YwHQYDVR0OBBYEFN+JmFD32Qxm6NjMJst5qqtwv3NvMA4G
A1UdDwEB/wQEAwIFoDCCASAGA1UdIASCARcwggETMAgGBmeBDAECAjCCAQUGDCqE
aAGG9ncCBQEMAjCB9DCB8QYIKwYBBQUHAgIwgeQwHxYYQXNzZWNvIERhdGEgU3lz
dGVtcyBTLkEuMAMCAQEagcBVc2FnZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN0
cmljdGx5IHN1YmplY3RlZCB0byB0aGUgQ0VSVFVNIENlcnRpZmljYXRpb24gUHJh
Y3RpY2UgU3RhdGVtZW50IChDUFMpIGluY29ycG9yYXRlZCBieSByZWZlcmVuY2Ug
aGVyZWluIGFuZCBpbiB0aGUgcmVwb3NpdG9yeSBhdCBodHRwczovL3d3dy5jZXJ0
dW0ucGwvcmVwb3NpdG9yeS4wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
MCMGA1UdEQQcMBqCDCouZmFwaWFvLmNvbYIKZmFwaWFvLmNvbTANBgkqhkiG9w0B
AQsFAAOCAQEAVbW/dkDpLso5ysVgzj6Tpaida0LXvRcfWzoFIi6WHMU4hGNNcdPh
K9bRHys8ue6WjuC170pFhKeSmrF/ph4xIGd66a/zM4IrJwFKn1xnbHEZNJBCtEfJ
x19zQUd9EkHZDqpj+pWZFVf7Cwzw7IPuCSZShZr7FZLX8Muddpv+gP158yDzw0tH
RClcsSgNjQntjxWvAt8O91Xgr3+YK0h2v0t51Lj7GOsz7Wb4jAB+5dD2lBpXjCrU
EEIqSsdypwLY8cvVbB93Nvg1LDTFrS27Gzu4Nr+7/RvtvsVmppy9bhxzbwOgO4TL
D3E3nXiSFBBYlfk1jEp9ywrRi7Fj2Vm2Wg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF5TCCBM2gAwIBAgIQHYtZAdpWwLET8sFQNsSUzDANBgkqhkiG9w0BAQsFADBE
MQswCQYDVQQGEwJDTjEaMBgGA1UECgwRV29TaWduIENBIExpbWl0ZWQxGTAXBgNV
BAMMEFdvU2lnbiBPViBTU0wgQ0EwHhcNMTcwODA4MDc1NTA2WhcNMjAwODA2MDc1
NTA2WjCBkzELMAkGA1UEBhMCQ04xRTBDBgNVBAoMPOeZvuacm+eUteWtkOWPkeel
qOaVsOaNruacjeWKoeaciemZkOWFrOWPuOa3seWcs+i/kOiQpeS4reW/gzESMBAG
A1UEBwwJ5rex5Zyz5biCMRIwEAYDVQQIDAnlub/kuJznnIExFTATBgNVBAMMDCou
ZmFwaWFvLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMe68gUh
2LHtow0SIGBhBbZlFXclyhSdr+gkPPAW4WeEBtiXwFcTBykZV3hbwqvXeC/npmnd
cuTMlovjdcheIE377ivzqvgJTBwQVhFpI3/gFvrPbdF2Pm8TQTjkoirQjMjeHRyh
rxo1gRRoVR8MI3q/C6CgYG2tqgVMC/lgluX36OT+Pzzotbqnurf2IrzWVDiwTFXQ
dQelAH2WV8m3nw5A/hu9/WnIDorK0Q3VSEx53Md1iYy1oHj13h5/cvmRXSl3P7oS
mrADHp63XRiQiG+vgIrcGOkw5aSo3Xu7eGt1+maOj2NGHfTZRy0UnROrpt+E9m8+
rZvgkmfNgMi0r4cCAwEAAaOCAoEwggJ9MAwGA1UdEwEB/wQCMAAwPAYDVR0fBDUw
MzAxoC+gLYYraHR0cDovL3dvc2lnbi5jcmwuY2VydHVtLnBsL3dvc2lnbi1vdmNh
LmNybDB3BggrBgEFBQcBAQRrMGkwLgYIKwYBBQUHMAGGImh0dHA6Ly93b3NpZ24t
b3ZjYS5vY3NwLWNlcnR1bS5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly9yZXBvc2l0
b3J5LmNlcnR1bS5wbC93b3NpZ24tb3ZjYS5jZXIwHwYDVR0jBBgwFoAUoRNU3FZz
LCeCysiE7+6/AP1fq1YwHQYDVR0OBBYEFN+JmFD32Qxm6NjMJst5qqtwv3NvMA4G
A1UdDwEB/wQEAwIFoDCCASAGA1UdIASCARcwggETMAgGBmeBDAECAjCCAQUGDCqE
aAGG9ncCBQEMAjCB9DCB8QYIKwYBBQUHAgIwgeQwHxYYQXNzZWNvIERhdGEgU3lz
dGVtcyBTLkEuMAMCAQEagcBVc2FnZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN0
cmljdGx5IHN1YmplY3RlZCB0byB0aGUgQ0VSVFVNIENlcnRpZmljYXRpb24gUHJh
Y3RpY2UgU3RhdGVtZW50IChDUFMpIGluY29ycG9yYXRlZCBieSByZWZlcmVuY2Ug
aGVyZWluIGFuZCBpbiB0aGUgcmVwb3NpdG9yeSBhdCBodHRwczovL3d3dy5jZXJ0
dW0ucGwvcmVwb3NpdG9yeS4wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
MCMGA1UdEQQcMBqCDCouZmFwaWFvLmNvbYIKZmFwaWFvLmNvbTANBgkqhkiG9w0B
AQsFAAOCAQEAVbW/dkDpLso5ysVgzj6Tpaida0LXvRcfWzoFIi6WHMU4hGNNcdPh
K9bRHys8ue6WjuC170pFhKeSmrF/ph4xIGd66a/zM4IrJwFKn1xnbHEZNJBCtEfJ
x19zQUd9EkHZDqpj+pWZFVf7Cwzw7IPuCSZShZr7FZLX8Muddpv+gP158yDzw0tH
RClcsSgNjQntjxWvAt8O91Xgr3+YK0h2v0t51Lj7GOsz7Wb4jAB+5dD2lBpXjCrU
EEIqSsdypwLY8cvVbB93Nvg1LDTFrS27Gzu4Nr+7/RvtvsVmppy9bhxzbwOgO4TL
D3E3nXiSFBBYlfk1jEp9ywrRi7Fj2Vm2Wg==
-----END CERTIFICATE-----
Bag Attributes
friendlyName: testK
localKeyID: 54 69 6D 65 20 31 34 39 30 30 38 30 39 36 32 31 31 30
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJew0vpxanBnasS1
Q0oIXaiBowlKp14eh4xCrhjA/4WkRyta6mWeQ4a6d3AxlpcMbnbY+NB5HgBVc9RD
yPLzLkbBtRWLoybHanevVXQ58ncbWAt1NwiYAZ+6dgzdAkgTLqt3OdvWlTmybRQc
5A+WIk4OGVUs/F8DFWTAR0zoMyn9AgMBAAECgYBp3KyQvaAjy/i2SS4pt4btd3N5
o5EEXVgJqetoOSDaeph0iGF3A6lqmC2Mrf7DcZiR9sBGdZBbeUd5xsixzMbo3mby
TzBeRf+njzmdAHTSQGNLjrLivGx1bqwONOkv/TG+VY1Rk2WlK8wTPE/EzaUyWr+U
VKmK20Vpfsqe187EXQJBAPbxjawz7E49GrP8Va3CbOVRZLztFBaFcFYNHgxLmAPi
I2vyWMFDC8pmIyMpOezLmV6RuacR9dcUWmpbzPJ3h8MCQQCdQPubEPaLH04zQ2xZ
O0fea7zBk+oQtKUj41Vib1zpMz7ueO9NL4SmSsBd+dpiGlb9EBE4VsO1PDRL/WP+
aSs/AkBNtw1gAWM/6CkMNcB9E7ATpz7t2iq1P79vxWcMdYncxwFgyn82KzR9uREb
0rChHh4hTflAY/2bd5NQ350rPYTjAkEAkK0DjwPJP+/aW3GRknrmwSxv6czzENGS
CXWSzdBVM7vRD0e2KlYofXHSj+NaVt2S4JpSrXmt7uTn3G3Q/HS3swJBAJr5o6ZT
wD07ax2Gcw34BaUXE0g++BbbOnV3eq+XuYSq9S7qb/emX1m8ZITbcS9AzHzMFwxB
IkHw4e0giNfWLWM=
-----END PRIVATE KEY-----
Bag Attributes
friendlyName: testK
localKeyID: 54 69 6D 65 20 31 34 39 30 30 38 30 39 36 32 31 31 30
subject=/C=CN/ST=SC/L=CD/O=BenZeph/OU=ISI/CN=\xE6\xB5\x8B\xE8\xAF\x95\xE8\xAF\x81\xE4\xB9\xA6
issuer=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIIC2TCCAcGgAwIBAgIENNsNsjANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UEBxMIU0hFTlpIRU4xGDAWBgNV
BAoTD3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMPdGVzdC5mYXBpYW8uY29tMRgw
FgYDVQQDEw9URVNULkZBUElBTy5DT00wHhcNMTcwMzIxMDcyMjQxWhcNMjcwMzE5
MDcyMjQxWjBeMQswCQYDVQQGEwJDTjELMAkGA1UECBMCU0MxCzAJBgNVBAcTAkNE
MRAwDgYDVQQKEwdCZW5aZXBoMQwwCgYDVQQLEwNJU0kxFTATBgNVBAMMDOa1i+iv
leivgeS5pjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAl7DS+nFqcGdqxLVD
SghdqIGjCUqnXh6HjEKuGMD/haRHK1rqZZ5Dhrp3cDGWlwxudtj40HkeAFVz1EPI
8vMuRsG1FYujJsdqd69VdDnydxtYC3U3CJgBn7p2DN0CSBMuq3c529aVObJtFBzk
D5YiTg4ZVSz8XwMVZMBHTOgzKf0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhUT1
TQQ9Ur+oqKhm25RGyu9IpKi3ZXIoHSUEsVISMEcbr3jvGxcD1ICUE7VytWJGpxFL
kbVbvftaIlUgnqqAjl4f6CRjTNg3Jlx+edS04AzRINWnIqNyABCa4+J3w850DFu4
Jl0ho+ic7Y7mluuvPKeKnWSJIR9letDaaq++hXBT8Pq+VQ4O2hD+XnOvsWYmQGlf
MwLILG9QKpJXVnvbYy1MZY/56mKTWGyMCS/B9OTfx9G2o7PghBoAgbkzcv6GK/l+
WG4qCN4jdTQgaGirSXpMbPBb3OyKSiCZtN1mruja5SbG0Nft8n5/Zx/APHxsYkve
NBMsCYpEjCGr6IaPUw==
-----END CERTIFICATE-----
Bag Attributes
friendlyName: CN=TEST.FAPIAO.COM,OU=test.fapiao.com,O=test.fapiao.com,L=SHENZHEN,ST=GUANGDONG,C=CN
subject=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
issuer=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIID8zCCAtugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCQ04x
EjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UEBxMIU0hFTlpIRU4xGDAWBgNVBAoT
D3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMPdGVzdC5mYXBpYW8uY29tMRgwFgYD
VQQDEw9URVNULkZBUElBTy5DT00wHhcNMTcwMzIwMDAwMDAwWhcNNDcwMzIwMDAw
MDAwWjCBgjELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UE
BxMIU0hFTlpIRU4xGDAWBgNVBAoTD3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMP
dGVzdC5mYXBpYW8uY29tMRgwFgYDVQQDEw9URVNULkZBUElBTy5DT00wggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUGbclvZWREPvoFEDIZNibmuVJuKPl
CMyvVmtZURr45fVRXykUcs5gSLYaZNWmWhYxhA5aR+DuCuscHZAOYjAWrDNHHBPc
AplzvwAWAjRnObFG8yWp1TFObEFgEzYBnDI7Wm2rUwyr9/IZqtmh9CAto/tt6oez
+AfEI2yHjRrNu0CCWKxDIe+HabP8ElWOSoDseBMCeFIS/eIrnRGlo/nMjVWrwJSn
4XAwDXiyOhWzEQXYc+smOVVP67FYdyMKkVleRrokZbQecVPH22aDqmg5jCrAAqzM
JJ0N3OX7JvRiUg+7xxGxWz8Wu8yS+N53jPCXDYs/+5GVgq7ncASbKEtVAgMBAAGj
cjBwMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFDxbw3+e5JQ6248psoo2uIQC
7u/lMAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgEN
BBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAVhyUyOP9DjD8
EI2HIGbWWW32bauEHYC0ngYBHULpJRmo0l69AaYjPaKygmvTy+OIjZcseX1ojfJz
GnqRjDn8Hyd3qiSi9nKeiKxDfEjhsGDCT7hMK2z+7Pym7Je2yq5gSd2GjZJQfepE
M6ViNuwy+j/Qw2c7txJaxxeJCJrsieuB8PZ7+G3qW2b1z2YckjxYZtUrMaBfo8c+
3XYxRpGqu6JrI8uzieTrIjuarlnnR8Sqfgjj7YrNzyGQ6Xah8oUU2gOPtO6KA/bU
1UmMisjUnBqcOcHMnVbCIZcPEumB/hRrcyjOqWxmK+KQs0NF22y2B3yZ1PwQ+bpB
2a0+KO+wAw==
-----END CERTIFICATE-----
Bag Attributes
friendlyName: testK
localKeyID: 54 69 6D 65 20 31 34 39 30 30 38 30 39 36 32 31 31 30
Key Attributes: <No Attributes>
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIF+258htus7gCAggA
MBQGCCqGSIb3DQMHBAivgydcDBctvgSCAoAw+pej9FhjiALD3psPHU1ctufqeSTf
3wETFnNJmSCslDUHX/+9jNWT+yX/7nTSGwiBdeRC+Hd2fTtdVCdJbq87kfd9sbVH
zJ7xO4F69a04NuCcaiCVkMJHigMOdwN+xzBgFyKCWZX4xHkC44ikZczANtuw78Gi
OfQv/7S9vPdH1um3DJasEXUy79XsAbAYe8fmXIzyZv+GwCXCFv6ZVnaeBgADuXDg
RXLjAXCbievYPw7kg/JLS2pJUHEhfYCEtTDTDO8TUle4gHMEHuMK/7/Tw9M3a03D
LVRqu08HoE60xIJECqLhZEuxZkem3COo29ITW7FrdTHj+1+ncuk4tYg8ZCuoj78r
5Zha7Fzc5S0OM/Wx0VYh7tmInv3JfyAp6Q1wDEMW1whX9ki7klozTcMx7CuQ9cW2
XO5Z/1ZBa+2FDbrqUFMZczUlex7D2+CKIvnKICxZ16+lYOx1GkPCeBBLs3LjxFVF
bBzxJQtbJJFD80oKwpH7/yAfMLOuDRktgcLU7in9ZZ0F4U66Ud8BMLbZJ0DAmd7U
G3lKuPh+x0HFoXsKgsnB/5JEwIW5nlS65PKc1mTTUDHn5QagjEiF7248wqWCn97b
fs8FJ4BqbUVohoFm54cunJ62qtCSXYLTOlDKUVQsVyS5GdspTBVC+TPb+YLWi56r
hwoC577Bs+e0kJiSi586C2CZClOxc+U2f9r2gPJpKBnGZfEQB/a7z4Z1ZTRfbQpA
zIuw0RtIZI7RIaQiHyQLlPF0UZzPWJN6GSW9HpMF8ZhujgnHq3CQxIzT0DrR0MFl
xMHpno0k9mU14vn3asPTTuZEPGLKtkD/T4bTtOc/L7EsyvxI5+d8iJAH
-----END ENCRYPTED PRIVATE KEY-----
Bag Attributes
friendlyName: testK
localKeyID: 54 69 6D 65 20 31 34 39 30 30 38 30 39 36 32 31 31 30
subject=/C=CN/ST=SC/L=CD/O=BenZeph/OU=ISI/CN=\xE6\xB5\x8B\xE8\xAF\x95\xE8\xAF\x81\xE4\xB9\xA6
issuer=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIIC2TCCAcGgAwIBAgIENNsNsjANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UEBxMIU0hFTlpIRU4xGDAWBgNV
BAoTD3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMPdGVzdC5mYXBpYW8uY29tMRgw
FgYDVQQDEw9URVNULkZBUElBTy5DT00wHhcNMTcwMzIxMDcyMjQxWhcNMjcwMzE5
MDcyMjQxWjBeMQswCQYDVQQGEwJDTjELMAkGA1UECBMCU0MxCzAJBgNVBAcTAkNE
MRAwDgYDVQQKEwdCZW5aZXBoMQwwCgYDVQQLEwNJU0kxFTATBgNVBAMMDOa1i+iv
leivgeS5pjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAl7DS+nFqcGdqxLVD
SghdqIGjCUqnXh6HjEKuGMD/haRHK1rqZZ5Dhrp3cDGWlwxudtj40HkeAFVz1EPI
8vMuRsG1FYujJsdqd69VdDnydxtYC3U3CJgBn7p2DN0CSBMuq3c529aVObJtFBzk
D5YiTg4ZVSz8XwMVZMBHTOgzKf0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhUT1
TQQ9Ur+oqKhm25RGyu9IpKi3ZXIoHSUEsVISMEcbr3jvGxcD1ICUE7VytWJGpxFL
kbVbvftaIlUgnqqAjl4f6CRjTNg3Jlx+edS04AzRINWnIqNyABCa4+J3w850DFu4
Jl0ho+ic7Y7mluuvPKeKnWSJIR9letDaaq++hXBT8Pq+VQ4O2hD+XnOvsWYmQGlf
MwLILG9QKpJXVnvbYy1MZY/56mKTWGyMCS/B9OTfx9G2o7PghBoAgbkzcv6GK/l+
WG4qCN4jdTQgaGirSXpMbPBb3OyKSiCZtN1mruja5SbG0Nft8n5/Zx/APHxsYkve
NBMsCYpEjCGr6IaPUw==
-----END CERTIFICATE-----
Bag Attributes
friendlyName: CN=TEST.FAPIAO.COM,OU=test.fapiao.com,O=test.fapiao.com,L=SHENZHEN,ST=GUANGDONG,C=CN
subject=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
issuer=/C=CN/ST=GUANGDONG/L=SHENZHEN/O=test.fapiao.com/OU=test.fapiao.com/CN=TEST.FAPIAO.COM
-----BEGIN CERTIFICATE-----
MIID8zCCAtugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCQ04x
EjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UEBxMIU0hFTlpIRU4xGDAWBgNVBAoT
D3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMPdGVzdC5mYXBpYW8uY29tMRgwFgYD
VQQDEw9URVNULkZBUElBTy5DT00wHhcNMTcwMzIwMDAwMDAwWhcNNDcwMzIwMDAw
MDAwWjCBgjELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUdVQU5HRE9ORzERMA8GA1UE
BxMIU0hFTlpIRU4xGDAWBgNVBAoTD3Rlc3QuZmFwaWFvLmNvbTEYMBYGA1UECxMP
dGVzdC5mYXBpYW8uY29tMRgwFgYDVQQDEw9URVNULkZBUElBTy5DT00wggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUGbclvZWREPvoFEDIZNibmuVJuKPl
CMyvVmtZURr45fVRXykUcs5gSLYaZNWmWhYxhA5aR+DuCuscHZAOYjAWrDNHHBPc
AplzvwAWAjRnObFG8yWp1TFObEFgEzYBnDI7Wm2rUwyr9/IZqtmh9CAto/tt6oez
+AfEI2yHjRrNu0CCWKxDIe+HabP8ElWOSoDseBMCeFIS/eIrnRGlo/nMjVWrwJSn
4XAwDXiyOhWzEQXYc+smOVVP67FYdyMKkVleRrokZbQecVPH22aDqmg5jCrAAqzM
JJ0N3OX7JvRiUg+7xxGxWz8Wu8yS+N53jPCXDYs/+5GVgq7ncASbKEtVAgMBAAGj
cjBwMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFDxbw3+e5JQ6248psoo2uIQC
7u/lMAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgEN
BBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAVhyUyOP9DjD8
EI2HIGbWWW32bauEHYC0ngYBHULpJRmo0l69AaYjPaKygmvTy+OIjZcseX1ojfJz
GnqRjDn8Hyd3qiSi9nKeiKxDfEjhsGDCT7hMK2z+7Pym7Je2yq5gSd2GjZJQfepE
M6ViNuwy+j/Qw2c7txJaxxeJCJrsieuB8PZ7+G3qW2b1z2YckjxYZtUrMaBfo8c+
3XYxRpGqu6JrI8uzieTrIjuarlnnR8Sqfgjj7YrNzyGQ6Xah8oUU2gOPtO6KA/bU
1UmMisjUnBqcOcHMnVbCIZcPEumB/hRrcyjOqWxmK+KQs0NF22y2B3yZ1PwQ+bpB
2a0+KO+wAw==
-----END CERTIFICATE-----
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, FetchedValue, DateTime
from Config.common_config import AGENT_STATUS
from Model.Base import BaseModel
class AgentAccount(BaseModel):
__tablename__ = 'agent_account'
id = Column(Integer, primary_key=True)
agent_no = Column(String(25, 'utf8mb4_unicode_ci'), nullable=False)
user_name = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False)
phone = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, server_default=FetchedValue())
level = Column(Integer, nullable=False, server_default=FetchedValue(), comment='1:超级管理员, 2:代理商')
status = Column(Integer, nullable=False, server_default=FetchedValue(), comment='1:正常 2:删除')
access_token = Column(String(255, 'utf8mb4_unicode_ci'))
salt = Column(String(255, 'utf8mb4_unicode_ci'))
password = Column(String(255, 'utf8mb4_unicode_ci'))
salt_pwd = Column(String(255, 'utf8mb4_unicode_ci'))
comment = Column(String(255, 'utf8mb4_unicode_ci'))
last_login = Column(DateTime)
expire_time = Column(DateTime)
@property
def level_desc(self):
return AGENT_STATUS[str(self.level)]
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, FetchedValue, String, DateTime
from Model.Base import BaseModel
class AgentLogRecord(BaseModel):
__tablename__ = 'agent_log_record'
id = Column(Integer, primary_key=True)
phone = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, server_default=FetchedValue())
ip = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, server_default=FetchedValue())
last_login = Column(DateTime, nullable=False, server_default=FetchedValue())
login_type = Column(Integer, nullable=False, server_default=FetchedValue(), comment='1:验证码登录 2:token 3:发送验证码')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, FetchedValue
from Model.Base import BaseModel
class AgentSpot(BaseModel):
__tablename__ = 'agent_spot'
id = Column(Integer, primary_key=True)
agent_no = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, server_default=FetchedValue())
spot_no = Column(Integer, nullable=False, server_default=FetchedValue())
status = Column(Integer, nullable=False, server_default=FetchedValue())
# -*- coding: utf-8 -*-
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import func, Column
db = SQLAlchemy()
class BaseModel(db.Model):
__abstract__ = True
created_at = Column(db.TIMESTAMP, nullable=False, server_default=func.now())
updated_at = Column(db.TIMESTAMP, nullable=False, server_default=func.now(), onupdate=func.now())
\ No newline at end of file
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, Index, DateTime, FetchedValue, Date
from Model.Base import BaseModel
class CouponOrder(BaseModel):
__tablename__ = 'coupon_order'
__table_args__ = (
Index('wx_guide_id_customer_id', 'wx_guide_id', 'customer_id'),
)
id = Column(Integer, primary_key=True)
spot_id = Column(Integer, comment='景点id')
business_id = Column(Integer, comment='商户id')
coupon_type_id = Column(Integer, nullable=False, comment='优惠券id')
wx_guide_id = Column(Integer, comment='对应导游的id')
customer_id = Column(Integer, comment='用户的id')
status = Column(Integer, nullable=False, server_default=FetchedValue(), comment='领取状态,1代表领取,2代表使用过,3过期')
add_time = Column(DateTime, nullable=False, server_default=FetchedValue(), comment='用户领取时间')
expire_time = Column(Date, nullable=False, comment='优惠的过期时间')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, DateTime, String
from Model.Base import BaseModel
class WxGuide(BaseModel):
__tablename__ = 'wx_guide'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, comment='领取的导游id')
qrcode = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, unique=True, comment='优惠二维码')
spot_id = Column(Integer, nullable=False, comment='景点id')
coupon_type_id = Column(Integer, nullable=False, comment='优惠券类型')
business_id = Column(Integer, nullable=False, comment='商户id')
expire_time = Column(Integer, nullable=False, comment='活动截止时间')
bonus = Column(Integer, comment='提成')
number = Column(Integer, comment='优惠群个数')
old = Column(Integer, nullable=False, comment='区分老旧数据')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, DateTime, FetchedValue
from Model.Base import BaseModel
class Customer(BaseModel):
__tablename__ = 'customers'
id = Column(Integer, primary_key=True)
mini_program_open_id = Column(String(191, 'utf8mb4_unicode_ci'), comment='微信支付宝小程序openID')
openid = Column(String(191, 'utf8mb4_unicode_ci'), comment='微信支付宝公众平台openID')
unionid = Column(String(191, 'utf8mb4_unicode_ci'), comment='微信支付宝unionid')
platform = Column(Integer, nullable=False, server_default=FetchedValue(), comment='平台 1微信 2支付宝')
phone = Column(String(191, 'utf8mb4_unicode_ci'), comment='手机号')
deposit = Column(Integer, nullable=False, server_default=FetchedValue(), comment='押金')
language = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='语种')
nick_name = Column(String(191, 'utf8mb4_unicode_ci'), comment='昵称')
gender = Column(Integer, nullable=False, server_default=FetchedValue(), comment='性别')
avatar_url = Column(String(191, 'utf8mb4_unicode_ci'), comment='头像')
status = Column(Integer, nullable=False, comment='状态 0停用 1正常')
last_login_at = Column(DateTime, comment='上次登录时间')
# -*- coding: utf-8 -*-
from sqlalchemy import Index, Column, Integer, Date
from sqlalchemy.ext.declarative import declarative_base
from Model.Base import db
Base = declarative_base()
metadata = Base.metadata
class Dayincome(db.Model):
__tablename__ = 'dayincome'
__table_args__ = (
Index('spot_id_day', 'spot_id', 'day'),
)
id = Column(Integer, primary_key=True)
spot_id = Column(Integer, nullable=False, comment='景区id')
business_id = Column(Integer, nullable=False, comment='商户id')
total = Column(Integer, nullable=False, comment='总金额')
guide_total = Column(Integer, nullable=False, comment='同游共听')
day = Column(Date, nullable=False, comment='总金额')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, FetchedValue, String
from sqlalchemy.sql.sqltypes import NullType
from Model.Base import BaseModel
class Machine(BaseModel):
__tablename__ = 'machine'
id = Column(Integer, primary_key=True)
mac_no = Column(String(16, 'utf8mb4_unicode_ci'), nullable=False, comment='机柜编号')
he_cloud_device_id = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='机柜号对应的波所的编号')
one_day_price = Column(Integer, nullable=False, comment='日租金')
deposit = Column(Integer, nullable=False, server_default=FetchedValue(), comment='押金')
free_time = Column(Integer, nullable=False, server_default=FetchedValue(), comment='免费时间')
position = Column(NullType, comment='机柜位置坐标')
address = Column(String(191, 'utf8mb4_unicode_ci'), comment='机柜位置')
spot_id = Column(Integer, nullable=False)
business_id = Column(Integer, nullable=False)
wx_mini_program = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='微信租借二维码地址')
ali_mini_program = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='支付宝租借二维码地址')
version = Column(String(191, 'utf8mb4_unicode_ci'), comment='版本号')
iccid = Column(String(191, 'utf8mb4_unicode_ci'), comment='iccid')
life = Column(Integer, nullable=False, server_default=FetchedValue(), comment='机柜在线状态默认0不在线1在线')
type = Column(Integer, nullable=False, comment='机柜类型')
hatch_number = Column(Integer, nullable=False, server_default=FetchedValue(), comment='机柜的仓口数量')
take_out_tool = Column(Integer, nullable=False, comment='0:没有弹出功能 , 1:有')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, FetchedValue
from Model.Base import BaseModel
class Power(BaseModel):
__tablename__ = 'power'
id = Column(Integer, primary_key=True)
power_no = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='充电宝编号')
power_type = Column(String(10, 'utf8mb4_unicode_ci'), comment='讲解器类型')
season = Column(Integer, server_default=FetchedValue(), comment='季节0暂无1春2夏3秋4冬')
has_power = Column(Integer, nullable=False, server_default=FetchedValue(), comment='充电宝电量')
status = Column(Integer, nullable=False, server_default=FetchedValue(), comment='充电宝状态1在仓库2在机柜可用3在机柜占用4出货成功')
is_miss = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否丢失 0未丢 1丢失')
machine_id = Column(Integer, comment='机柜id')
hatch_no = Column(Integer, comment='机柜仓口号')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, DateTime, FetchedValue
from Model.Base import BaseModel
class Production(BaseModel):
__tablename__ = 'production'
id = Column(Integer, primary_key=True)
rent_id = Column(Integer, nullable=False, comment='租借id')
is_out = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否取出')
power_id = Column(Integer, nullable=False, comment='讲解器id')
power_no = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='讲解器编号')
rent_machine_id = Column(Integer, nullable=False, comment='租的机柜id')
rent_hatch_no = Column(Integer, nullable=False, comment='租的仓口')
is_return = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否归还')
return_machine_id = Column(Integer, comment='还的机柜id')
return_hatch_no = Column(Integer, comment='还的仓口')
return_time = Column(DateTime, comment='还的时间')
is_refund = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否退款')
refund_no = Column(String(191, 'utf8mb4_unicode_ci'), comment='退款单号')
refund_time = Column(DateTime, comment='退款时间')
total = Column(Integer, comment='消费金额')
spot_id = Column(Integer, nullable=False, comment='景点id')
business_id = Column(Integer, nullable=False, comment='商家id')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, DateTime, FetchedValue
from Model.Base import BaseModel
class Rent(BaseModel):
__tablename__ = 'rent'
id = Column(Integer, primary_key=True)
rent_no = Column(String(19, 'utf8mb4_unicode_ci'), nullable=False, comment='租借单号')
number = Column(Integer, nullable=False, comment='租借数量')
deposit = Column(Integer, nullable=False, comment='单个押金')
one_day_price = Column(Integer, nullable=False, comment='日单价')
free_time = Column(Integer, nullable=False, comment='免费时间')
machine_id = Column(Integer, nullable=False, comment='机柜id')
power_type = Column(String(10, 'utf8mb4_unicode_ci'), comment='讲解器类型')
customer_id = Column(Integer, nullable=False, comment='用户id')
total = Column(Integer, nullable=False, server_default=FetchedValue(), comment='应收金额')
real_total = Column(Integer, nullable=False, server_default=FetchedValue(), comment='实收金额')
back_money = Column(Integer, nullable=False, server_default=FetchedValue(), comment='退款金额')
is_pay = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否支付')
rent_type = Column(Integer, nullable=False, server_default=FetchedValue(), comment='租借类型1现场租借2预约')
add_time = Column(DateTime, nullable=False, server_default=FetchedValue(), comment='下单时间')
pay_time = Column(DateTime, comment='支付时间')
is_take = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否取货')
take_time = Column(DateTime, comment='开始发货时间')
is_over = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否完结')
is_cancel = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否取消交易')
refund_no = Column(String(191, 'utf8mb4_unicode_ci'), comment='退款单号')
spot_id = Column(Integer, nullable=False, comment='景点id')
business_id = Column(Integer, nullable=False, comment='商家id')
expire_handle = Column(Integer, nullable=False, server_default=FetchedValue(), comment='是否做过期处理')
prepay_id = Column(String(191, 'utf8mb4_unicode_ci'), comment='微信支付prepay_id')
over_time = Column(DateTime, comment='订单完结时间')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, FetchedValue, Text
from Model.Base import BaseModel
class RentRefund(BaseModel):
__tablename__ = 'rent_refund'
id = Column(Integer, primary_key=True)
refund_no = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False)
production_id = Column(Integer, server_default=FetchedValue(), nullable=False)
fee = Column(Integer, server_default=FetchedValue(), nullable=False)
comment = Column(Text(collation='utf8mb4_unicode_ci'), nullable=False)
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, ForeignKey, String
from sqlalchemy.orm import relationship
from Model.Base import BaseModel
class RepairImage(BaseModel):
__tablename__ = 'repair_images'
id = Column(Integer, primary_key=True)
repairs_id = Column(ForeignKey('repairs.id', ondelete='CASCADE'), index=True)
url = Column(String(200))
repairs = relationship('Repair', primaryjoin='RepairImage.repairs_id == Repair.id', backref='repair_images')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, ForeignKey, Text, String, FetchedValue
from sqlalchemy.orm import relationship
from Model.Base import BaseModel
class Repair(BaseModel):
__tablename__ = 'repairs'
id = Column(Integer, primary_key=True)
spot_id = Column(ForeignKey('spot.id', ondelete='CASCADE'), nullable=False, index=True, comment='景区编号')
machine_id = Column(ForeignKey('machine.id', ondelete='CASCADE'), nullable=False, index=True, comment='机柜编号')
system_users_id = Column(Integer, comment='商家账号id')
remark = Column(Text, comment='问题描述')
tel = Column(String(50), comment='联系方式')
status = Column(Integer, server_default=FetchedValue(), comment='状态')
machine = relationship('Machine', primaryjoin='Repair.machine_id == Machine.id', backref='repairs')
spot = relationship('Spot', primaryjoin='Repair.spot_id == Spot.id', backref='repairs')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, FetchedValue, DateTime
from sqlalchemy.ext.declarative import declarative_base
from Model.Base import db
Base = declarative_base()
metadata = Base.metadata
class Settlement(db.Model):
__tablename__ = 'settlement'
id = Column(Integer, primary_key=True)
spot_id = Column(Integer, nullable=False)
business_id = Column(Integer, nullable=False)
month = Column(Integer, nullable=False)
total = Column(Integer, nullable=False)
guide_total = Column(Integer, nullable=False)
status = Column(Integer, nullable=False, server_default=FetchedValue())
bill_id = Column(Integer)
created_at = Column(DateTime)
updated_at = Column(DateTime)
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, FetchedValue
from Model.Base import BaseModel
class Spot(BaseModel):
__tablename__ = 'spot'
id = Column(Integer, primary_key=True)
spotname = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='景点名')
business_id = Column(Integer, nullable=False, comment='关联id')
main_title = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='主标题')
vic_title = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='副标题')
detail_img = Column(String(191, 'utf8mb4_unicode_ci'), comment='展示界面的图片')
wx_logo = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='微信头像')
go_url = Column(String(191, 'utf8mb4_unicode_ci'), comment='定制化界面')
listen_img = Column(String(191, 'utf8mb4_unicode_ci'), comment='手机游二维码')
page_id = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='微信id')
code = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='唯一值')
time = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='开始时间')
overtime = Column(String(191, 'utf8mb4_unicode_ci'), nullable=False, comment='结束时间')
open_week = Column(String(255), server_default=FetchedValue(), comment='营业时间')
address = Column(String(255), nullable=False, server_default=FetchedValue())
return_img = Column(String(255, 'utf8mb4_unicode_ci'), comment='归还图片')
spotname_english = Column(String(191, 'utf8mb4_unicode_ci'), comment='景点英文名')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, String, FetchedValue
from Model.Base import BaseModel
class Invoice(BaseModel):
__tablename__ = 'invoice'
id = Column(Integer, primary_key=True)
fpqqlsh = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='发票请求流水号')
fp_dm = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='发票代码')
fp_hm = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='发票号码')
kprq = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='开票日期')
jym = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='校验码')
pdf_url = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='PDF下载地址')
sp_url = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='售票地址')
is_red = Column(Integer, nullable=False, server_default=FetchedValue(), comment='0:未红冲 1:已红冲 2:红冲发票')
status = Column(Integer, nullable=False, server_default=FetchedValue(), comment='1:正常 2:删除')
# -*- coding: utf-8 -*-
from sqlalchemy import Column, String, Integer
from Model.Base import BaseModel
class InvoiceRecord(BaseModel):
__tablename__ = 'invoice_record'
id = Column(Integer, primary_key=True)
invoice_id = Column(Integer, nullable=False, comment='对应发票id')
customer_id = Column(Integer, nullable=False, comment='用户id')
company_name = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='发票抬头')
payment_id = Column(String(255, 'utf8mb4_unicode_ci'), comment='税号')
pay_money = Column(Integer, nullable=False, comment='合计金额')
e_account = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='电子邮箱')
remark = Column(String(255, 'utf8mb4_unicode_ci'), comment='备注')
address = Column(String(255, 'utf8mb4_unicode_ci'), comment='地址电话')
account = Column(String(255, 'utf8mb4_unicode_ci'), comment='开户行账号')
parent_id = Column(Integer, nullable=False, comment='父节点')
rent_list = Column(String(255, 'utf8mb4_unicode_ci'), nullable=False, comment='订单id列表')
status = Column(Integer, nullable=False, comment='0:正常开发票1:等待审核2:审核成功3:驳回4:拒绝')
reason = Column(String(255, 'utf8mb4_unicode_ci'), comment='审核理由')
#tour_business
# -*- coding: utf-8 -*-
from flask_redis import FlaskRedis
redis = FlaskRedis(config_prefix='TENCENT_REDIS')
# -*- coding: utf-8 -*-
import base64
import datetime
import hashlib
import random
import string
from Config.common_config import ACCOUNT_STATUS
from Model.Agent.AgentAccountModel import AgentAccount
from Model.Agent.AgentSpotModel import AgentSpot
from Model.Base import db
from Model.Spot.SpotModel import Spot
from Service.SpotService import SpotService
class AgentService():
@staticmethod
def gene_salt(length=16):
key_list = [random.choice((string.ascii_letters + string.digits)) for i in range(length)]
return ("".join(key_list))
@staticmethod
def gene_agent_code(agent_info, salt):
m = hashlib.md5()
str = "%s-%s-%s-%s" % (agent_info.id, agent_info.user_name, agent_info.phone, salt)
m.update(str.encode("utf-8"))
return m.hexdigest()
@staticmethod
def gene_pwd(pwd, salt):
m = hashlib.md5()
str = "%s-%s" % (base64.encodebytes(pwd.encode("utf-8")), salt)
m.update(str.encode("utf-8"))
return m.hexdigest()
@staticmethod
def check_agent_token(token):
token = base64.b64decode(token).decode("utf-8")
try:
agent_info = AgentAccount.query.filter_by(access_token=token).first()
except Exception as e:
return 1
if not agent_info:
return 1
s = token.split("#")
if len(s) != 2:
return 1
if AgentService.gene_agent_code(agent_info, agent_info.salt) != s[0]:
return 1
if agent_info.expire_time < datetime.datetime.now():
return 2
return agent_info
@staticmethod
def create_agent_no():
'''
生成用户编号
:return:
'''
ran_int = str(random.randint(1, 999999)).zfill(6)
return 'ssw' + ran_int
@staticmethod
def get_spot_info(agent_info):
spot_info = []
if agent_info.level == 2 or agent_info.level == 3:
infos = db.session.query(AgentAccount, AgentSpot, Spot).join(AgentSpot,
AgentAccount.id == AgentSpot.agent_no).join(
Spot, Spot.id == AgentSpot.spot_no).filter(AgentAccount.id == agent_info.id,
AgentAccount.status == ACCOUNT_STATUS['on_use'],
AgentSpot.status == ACCOUNT_STATUS['on_use']).all()
for info in infos:
cur_info = {}
cur_info['id'] = info.Spot.id
cur_info['spotname'] = info.Spot.spotname
cur_info['letter'] = SpotService.get_pinyin(info.Spot.spotname)
spot_info.append(cur_info)
else:
infos = Spot.query.with_entities(Spot.id, Spot.spotname).all()
for info in infos:
cur_info = {}
cur_info['id'] = info.id
cur_info['spotname'] = info.spotname
cur_info['letter'] = SpotService.get_pinyin(info.spotname)
spot_info.append(cur_info)
return spot_info
# -*- coding: utf-8 -*-
from Model.Base import db
from Model.Coupon.CouponOrderModel import CouponOrder
from Model.Coupon.WxGuideModel import WxGuide
from Model.Machine.MachineModel import Machine
from Model.Power.PowerModel import Power
from Model.Production.ProductionModel import Production
from Model.Rent.RentModel import Rent
class IndexService():
@staticmethod
def get_total_production(spot_id, start_time, end_time):
'''
获取该景区当前时间段内收益和租借充电宝的数量
:param spot_id:
:param start_time:
:param end_time:
:return:
'''
income_info = db.session.query(Production.total).filter(Production.spot_id == spot_id, Production.total > 0,
Production.created_at >= start_time,
Production.created_at <= end_time).all()
total = 0
for info in income_info:
total += info.total
return round(total / 100, 2), len(income_info)
@staticmethod
def get_total_power(spot_id, start_time, end_time):
'''
获取该景区当前时间段内租借充电宝的总量
:param spot_id:
:param start_time:
:param end_time:
:return:
'''
where = {
Rent.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
count = db.session.query(Production, Rent).join(Rent, Rent.id == Production.rent_id).filter(*where).count()
return count
@staticmethod
def get_total_production_num(spot_id, start_time, end_time):
where = {
Production.is_out == 1,
Production.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
count = Production.query.filter(*where).count()
return count
@staticmethod
def get_total_production_finished(spot_id, start_time, end_time):
'''
获取已完成的充电宝数量
:param spot_id:
:param start_time:
:param end_time:
:return:
'''
where = {
Production.is_out == 1,
Production.is_return == 1,
Production.total > 0,
Production.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
return Production.query.filter(*where).count()
@staticmethod
def get_not_return_production(spot_id, start_time, end_time):
'''
获取未归还的充电宝数量
:param spot_id:
:param start_time:
:param end_time:
:return:
'''
where = {
Production.is_return == 0,
Production.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
count = Production.query.filter(*where).count()
return count
@staticmethod
def get_invalid_production(spot_id, start_time, end_time):
'''
获取无效的充电宝数量
:param spot_id:
:param start_time:
:param end_time:
:return:
'''
where = {
Production.is_out == 1,
Production.is_return == 1,
Production.total <= 0,
Production.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
return Production.query.filter(*where).count()
@staticmethod
def get_invalid_production_info(spot_id, start_time, end_time):
'''
获取无效的充电宝信息
:param spot_id:
:param start_time:
:param end_time:
:return:
'''
where = {
Production.is_return == 1,
Production.spot_id == spot_id,
Production.total == 0,
Production.created_at >= start_time,
Production.created_at <= end_time
}
total = 0
infos = db.session.query(Rent.one_day_price).join(Production, Production.rent_id == Rent.id).filter(
*where).all()
for info in infos:
total += info.one_day_price
return round(total / 100, 2), len(infos)
@staticmethod
def get_invalid_production_info_all(spot_id):
'''
获取当前景区所有的无效充电宝信息
:param spot_id:
:return:
'''
where = {
Production.is_return == 1,
Production.spot_id == spot_id,
Production.total == 0
}
total = 0
infos = db.session.query(Rent.one_day_price).join(Production, Production.rent_id == Rent.id).filter(
*where).all()
for info in infos:
total += info.one_day_price
return round(total / 100, 2), len(infos)
@staticmethod
def get_refund_rent(spot_id, start_time, end_time):
info = db.session.query(Production, Rent).join(Rent, Rent.id == Production.rent_id).filter(
Production.spot_id == spot_id, Production.is_refund == 1, Production.return_hatch_no == 127,
Production.refund_time >= start_time, Production.refund_time <= end_time).all()
total_income = 0
for i in info:
total_income += i.Production.total
return round(total_income / 100, 2), len(info)
@staticmethod
def get_history_refund_rent(spot_id):
info = db.session.query(Production, Rent).join(Rent, Rent.id == Production.rent_id).filter(
Production.spot_id == spot_id, Production.is_refund == 1, Production.return_hatch_no == 127).all()
total_income = 0
for i in info:
total_income += i.Production.total
return round(total_income / 100, 2), len(info)
@staticmethod
def get_history_income_production(spot_id):
'''
获取历史收益通过production
:param spot_id:
:return:
'''
# total = db.session.query(func.sum(Production.total)).filter(Production.spot_id == spot_id).scalar()
# logger.info(total)
# return round(total / 100, 2)
total = 0
income_info = db.session.query(Production.total).filter(Production.spot_id == spot_id,
Production.total > 0).all()
for info in income_info:
total += info.total
return round(total / 100, 2)
@staticmethod
def get_history_production(spot_id):
'''
获取历史租借充电宝数量
:param spot_id:
:return:
'''
where = {
Production.is_out == 1,
Production.is_return == 1,
Production.total > 0,
Production.spot_id == spot_id
}
total = Production.query.filter(*where).count()
return total
@staticmethod
def get_available_power_number(machine_id):
power_info = Power.query.filter(Power.has_power > 75, Power.status == 2, Power.machine_id == machine_id).count()
return power_info
@staticmethod
def get_machine_total_power(machine_id):
total = 55
power_info = Power.query.filter_by(machine_id=machine_id).all()
for power in power_info:
if power.power_no.startswith("00000000"):
total -= 1
return total
@staticmethod
def get_machine_info(spot_id):
machine_info = Machine.query.filter(Machine.spot_id == spot_id).all()
machine = []
for info in machine_info:
cur_machine = {}
cur_machine['mac_no'] = info.mac_no
cur_machine['life'] = info.life
cur_machine['hatch_number'] = IndexService.get_machine_total_power(info.id)
cur_machine['take_out_tool'] = info.take_out_tool
cur_machine['available_number'] = IndexService.get_available_power_number(info.id)
machine.append(cur_machine)
return machine
@staticmethod
def get_discount_money(spot_id, start_time, end_time):
discount_info = db.session.query(CouponOrder, WxGuide).join(WxGuide,
WxGuide.id == CouponOrder.wx_guide_id).filter(
CouponOrder.spot_id == spot_id, CouponOrder.updated_at >= start_time,
CouponOrder.updated_at <= end_time).all()
total = 0
for info in discount_info:
total += info.WxGuide.bonus
return round(total / 100, 2)
# -*- coding: utf-8 -*-
import base64
import datetime
import hashlib
import json
import random
import requests
from Crypto.Cipher import AES
from Config.common_config import INVOICE_CONFIG
from Model.Base import db
from Model.Rent.RentModel import Rent
from Model.invoice.InvoiceModel import Invoice
class InvoiceService:
def __init__(self):
self.url = INVOICE_CONFIG["url"]
self.app_id = INVOICE_CONFIG["app_id"]
self.key = INVOICE_CONFIG["app_key"]
self.xsf_nsrsbh = INVOICE_CONFIG["xsf_nsrsbh"]
@classmethod
def encrypt(cls, raw, key):
block_size = 16 # Bytes
raw = raw + (block_size - len(raw) % block_size) * chr(block_size - len(raw) % block_size)
cipher = AES.new(str.encode(key), AES.MODE_ECB)
return base64.b64encode(cipher.encrypt(str.encode(raw))).decode(encoding='utf-8')
@classmethod
def create_fpqqlsh(cls):
data_str = datetime.datetime.now().strftime('%Y%m%d')
int_str = str(random.randint(1, 9999)).zfill(7)
return 'SZSSW' + data_str + int_str
def dict_content(self, gmf_mc, gmf_nsrsbh, gmf_dzyx, gmf_dzdh, gmf_yhzh, remark, rent_list):
new_list = rent_list.split(',')
common_fpkj_xmxx = []
jshj = 0
hjje_total = 0
hjsh = 0
for ls in new_list:
rent_info = Rent.query.filter_by(rent_no=ls).first()
real_total = round(rent_info.real_total / 100, 2)
xmdj = str(round(real_total / 1.06, 11))
xmje = str(round(real_total / 1.06, 2))
se = str(round((real_total - round(real_total / 1.06, 2)), 2))
jshj += real_total
hjje_total += round(real_total / 1.06, 2)
hjsh += round(real_total - round(real_total / 1.06, 2), 2)
# "SPBM": "304020300000000000001"
tmp = {
"FPHXZ": "0",
"SPBM": INVOICE_CONFIG["spbm"],
"ZXBM": "",
"YHZCBS": "",
"LSLBS": "",
"ZZSTSGL": "",
"XMMC": "信息技术服务",
"GGXH": "",
"DW": "",
"XMSL": "1",
"XMDJ": xmdj,
"XMJE": xmje,
"SL": "0.06",
"SE": se,
"BY1": "",
"BY2": "",
"BY3": "",
"BY4": "",
"BY5": "",
}
common_fpkj_xmxx.append(tmp)
dict_content = {"REQUEST_COMMON_FPKJ": {"FPQQLSH": self.create_fpqqlsh(),
"BMB_BBH": "",
"ZSFS": "0",
"KPLX": "0",
"XSF_NSRSBH": self.xsf_nsrsbh,
"XSF_MC": INVOICE_CONFIG["xsf_mc"],
"XSF_DZDH": INVOICE_CONFIG["dizhi_dianhua"],
"XSF_YHZH": INVOICE_CONFIG["yinhang_zhanghao"],
"GMF_NSRSBH": gmf_nsrsbh,
"GMF_MC": gmf_mc,
"GMF_DZDH": gmf_dzdh,
"GMF_YHZH": gmf_yhzh,
"GMF_SJH": "18068402080",
"GMF_DZYX": gmf_dzyx,
"FPT_ZH": "",
"WX_OPENID": "",
"KPR": INVOICE_CONFIG["kaipiaoren"],
"SKR": INVOICE_CONFIG["shoukuanren"],
"FHR": INVOICE_CONFIG["fuheren"],
"YFP_DM": "",
"YFP_HM": "",
"JSHJ": jshj,
"HJJE": hjje_total,
"HJSE": hjsh,
"KCE": "",
"BZ": remark,
"HYLX": "0",
"BY1": "",
"BY2": "",
"BY3": "",
"BY4": "",
"BY5": "",
"BY6": "",
"BY7": "",
"BY8": "",
"BY9": "",
"BY10": "",
"WX_ORDER_ID": "",
"WX_APP_ID": "",
"ZFB_UID": "",
"TSPZ": "00",
"QJ_ORDER_ID": "",
"WX_GROUP_ID": "",
"COMMON_FPKJ_XMXXS": {"COMMON_FPKJ_XMXX": common_fpkj_xmxx}}}
json_content = json.dumps(dict_content)
# BASE64加密并转成字符串
content = base64.b64encode(json_content.encode('utf-8')).decode(encoding='utf-8')
# 对content进行md5
contentMd5 = hashlib.md5(content.encode("utf-8")).hexdigest()
# 对md5进行aes加密
contentKey = self.encrypt(contentMd5, self.key)
post_data = {
"interface": {
"globalInfo": {
"appId": self.app_id,
"interfaceId": "",
"interfaceCode": "DFXJ1001",
"requestCode": "DS",
"requestTime": "2017-02-14 08:13:15",
"responseCode": "DZFPQZ",
"dataExchangeId": "DZFPQZDFXJ10012017-02-14128641426"
},
"returnStateInfo": {
"returnCode": "",
"returnMessage": ""
},
"Data": {
"dataDescription": {
"zipCode": "0"
},
"content": content,
"contentKey": contentKey
}}
}
post_data = json.dumps(post_data)
cert_path = INVOICE_CONFIG["cert_path"]
res = requests.post(self.url, data=post_data, cert=cert_path)
if not res.text:
return {"error_code": -1, "error_message": "申请失败,请重新申请!"}, 0
res = json.loads(res.text)
if res['interface']['returnStateInfo']['returnCode'] != "0000":
return res['interface']['returnStateInfo'], 0
raw = res["interface"]["Data"]["content"]
raw = str(base64.b64decode(raw), encoding="utf-8")
new_invoice = Invoice()
if raw:
raw = json.loads(raw)
new_invoice.fpqqlsh = raw['FPQQLSH']
new_invoice.fp_dm = raw['FP_DM']
new_invoice.fp_hm = raw['FP_HM']
new_invoice.kprq = raw['KPRQ']
new_invoice.jym = raw['JYM']
new_invoice.pdf_url = raw['PDF_URL']
new_invoice.sp_url = raw['SP_URL']
new_invoice.status = 1
new_invoice.is_red = 0
new_invoice.created_at = datetime.datetime.now()
new_invoice.updated_at = datetime.datetime.now()
db.session.add(new_invoice)
db.session.commit()
return raw, new_invoice.id
def red_rush(self, yfp_dm, yfp_hm):
dict_content = {
"REQUEST_COMMON_FPKSHC": {
"FPQQLSH": self.create_fpqqlsh(),
"XSF_NSRSBH": INVOICE_CONFIG["xsf_nsrsbh"],
"XSF_MC": INVOICE_CONFIG["xsf_mc"],
"YFP_DM": yfp_dm,
"YFP_HM": yfp_hm
}
}
json_content = json.dumps(dict_content)
# BASE64加密并转成字符串
content = base64.b64encode(json_content.encode('utf-8')).decode(encoding='utf-8')
# 对content进行md5
contentMd5 = hashlib.md5(content.encode("utf-8")).hexdigest()
# 对md5进行aes加密
contentKey = self.encrypt(contentMd5, self.key)
post_data = {
"interface": {
"globalInfo": {
"appId": self.app_id,
"interfaceId": "",
"interfaceCode": "DFXJ1008",
"requestCode": "DS",
"requestTime": "2017-02-14 08:13:15",
"responseCode": "DZFPQZ",
"dataExchangeId": "DZFPQZDFXJ10012017-02-14128641426"
},
"returnStateInfo": {
"returnCode": "",
"returnMessage": ""
},
"Data": {
"dataDescription": {
"zipCode": "0"
},
"content": content,
"contentKey": contentKey
}}
}
post_data = json.dumps(post_data)
cert_path = INVOICE_CONFIG["cert_path"]
res = requests.post(self.url, data=post_data, cert=cert_path)
if not res.text:
return {"error_code": -1, "error_message": "申请失败,请重新申请!"}, 0
res = json.loads(res.text)
if res['interface']['returnStateInfo']['returnCode'] != "0000":
return res['interface']['returnStateInfo']
raw = res["interface"]["Data"]["content"]
raw = str(base64.b64decode(raw), encoding="utf-8")
new_invoice = Invoice()
if raw:
raw = json.loads(raw)
new_invoice.fpqqlsh = raw['FPQQLSH']
new_invoice.fp_dm = raw['FP_DM']
new_invoice.fp_hm = raw['FP_HM']
new_invoice.kprq = raw['KPRQ']
new_invoice.jym = raw['JYM']
new_invoice.pdf_url = raw['PDF_URL']
new_invoice.sp_url = raw['SP_URL']
new_invoice.status = 1
new_invoice.is_red = 1
new_invoice.created_at = datetime.datetime.now()
new_invoice.updated_at = datetime.datetime.now()
db.session.add(new_invoice)
db.session.commit()
return raw
# -*- coding: utf-8 -*-
import datetime
import random
from sqlalchemy import or_
from Libs.Helper import Helper
from Model.Base import db
from Model.Customer.CustomerModel import Customer
from Model.Machine.MachineModel import Machine
from Model.Production.ProductionModel import Production
from Model.Rent.RentModel import Rent
from Model.Rent.RentRefundModel import RentRefund
from Model.Spot.SpotModel import Spot
class RentService():
@staticmethod
def get_rent_production_all(spot_id, start_time, end_time, page, limit):
where = {
Rent.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
rent_info = db.session.query(Rent, Production).join(Production, Production.rent_id == Rent.id).filter(
*where).order_by(Production.created_at.desc()).slice(page * limit, (page + 1) * limit).all()
data = []
for info in rent_info:
cur_info = {}
cur_info['rent_no'] = info.Rent.rent_no
cur_info['hatch_no'] = info.Production.rent_hatch_no
cur_info['total'] = 0 if info.Production.total is None else info.Production.total
if info.Production.is_return == 1:
if cur_info['total'] <= 0:
if info.Production.return_hatch_no == 127:
cur_info['status'] = 3
else:
cur_info['status'] = 2
else:
cur_info['status'] = 1
else:
cur_info['status'] = 0
data.append(cur_info)
return data
@staticmethod
def get_not_return_production(spot_id, start_time, end_time):
where = {
Rent.spot_id == spot_id,
Production.is_out == 1,
Production.is_return == 0,
Production.created_at >= start_time,
Production.created_at <= end_time
}
rent_info = db.session.query(Rent, Production).join(Production, Production.rent_id == Rent.id).filter(
*where).order_by(Production.created_at.desc()).all()
data = []
for info in rent_info:
tmp = {
'rent_no': info.Rent.rent_no,
'hatch_no': info.Production.rent_hatch_no,
'total': 0 if info.Production.total is None else info.Production.total,
'status': 0
}
data.append(tmp)
return data
@staticmethod
def get_rent_production_info(spot_id, start_time, end_time):
where = {
Rent.spot_id == spot_id,
Production.created_at >= start_time,
Production.created_at <= end_time
}
rent_info = db.session.query(Rent, Production).join(Production, Production.rent_id == Rent.id).filter(
*where).order_by(Production.created_at.desc()).all()
data = []
for info in rent_info:
cur_info = {}
cur_info['rent_no'] = info.Rent.rent_no
cur_info['hatch_no'] = info.Production.rent_hatch_no
cur_info['total'] = 0 if info.Production.total is None else info.Production.total
if info.Production.is_return == 1:
if cur_info['total'] <= 0:
if info.Production.return_hatch_no == 127:
cur_info['status'] = 3
else:
cur_info['status'] = 2
else:
cur_info['status'] = 1
else:
cur_info['status'] = 0
data.append(cur_info)
return data
@staticmethod
def get_production_detail_new(rent_no, hatch_no):
sql = '''
SELECT rent.deposit, rent.is_over, production.is_return, production.total, production.return_hatch_no,
production.rent_machine_id, rent.customer_id, rent.real_total, rent.rent_no, production.return_time,
rent.free_time, rent.one_day_price, rent.pay_time, rent.spot_id, production.is_refund, production.refund_no,
rent_refund.refund_no AS rent_refund_no FROM rent
LEFT JOIN production ON production.rent_id = rent.id
LEFT JOIN rent_refund ON rent_refund.production_id = production.id
WHERE rent.rent_no = "{rent_no}" AND production.rent_hatch_no = {hatch_no}
'''.format(rent_no=rent_no, hatch_no=hatch_no)
production_info = db.session.execute(sql)
total_info = []
for info in production_info:
cur_info = {}
cur_info['deposit'] = info.deposit
cur_info['is_return'] = info.is_over
if info.is_return == 1:
if info.total <= 0:
if info.return_hatch_no == 127:
cur_info['status'] = 3
else:
cur_info['status'] = 2
else:
cur_info['status'] = 1
else:
cur_info['status'] = 0
cur_info['mac_no'] = RentService.get_rent_machine(info.rent_machine_id)
cur_info['phone'] = RentService.get_customer_phone(info.customer_id)
cur_info['real_total'] = info.real_total
cur_info['rent_no'] = info.rent_no
cur_info['rent_over_time'] = None if not info.return_time else Helper.getFormatDate(info.return_time)
cur_info['rent_price'] = str(info.free_time) + '分钟内免费,日租金' + str(
round(info.one_day_price / 100, 2)) + '元/个'
cur_info['rent_start_time'] = Helper.getFormatDate(info.pay_time)
cur_info['spot_name'] = RentService.get_rent_spot_name(info.spot_id)
cur_info['is_refund'] = info.is_refund
cur_info['refund_no'] = info.refund_no
cur_info['rent_refund_no'] = info.rent_refund_no
total_info.append(cur_info)
return total_info
@staticmethod
def get_production_detail(rent_no, hatch_no):
production_info = db.session.query(Rent, Production).join(Production, Production.rent_id == Rent.id).filter(
Rent.rent_no == rent_no, Production.rent_hatch_no == hatch_no).all()
total_info = []
for info in production_info:
cur_info = {}
cur_info['deposit'] = info.Rent.deposit
cur_info['is_return'] = info.Rent.is_over
if info.Production.is_return == 1:
if info.Production.total <= 0:
cur_info['status'] = 2
elif info.Production.return_hatch_no == 127:
cur_info['status'] = 3
else:
cur_info['status'] = 1
else:
cur_info['status'] = 0
cur_info['mac_no'] = RentService.get_rent_machine(info.Production.rent_machine_id)
cur_info['phone'] = RentService.get_customer_phone(info.Rent.customer_id)
cur_info['real_total'] = info.Rent.real_total
cur_info['rent_no'] = info.Rent.rent_no
cur_info['rent_over_time'] = Helper.getFormatDate(info.Production.return_time)
cur_info['rent_price'] = str(info.Rent.free_time) + '分钟内免费,日租金' + str(
round(info.Rent.one_day_price / 100, 2)) + '元/个'
cur_info['rent_start_time'] = Helper.getFormatDate(info.Rent.pay_time)
cur_info['spot_name'] = RentService.get_rent_spot_name(info.Rent.spot_id)
cur_info['is_refund'] = info.Production.is_refund
cur_info['refund_no'] = info.Production.refund_no
total_info.append(cur_info)
return total_info
@staticmethod
def get_rent_machine(machine_id):
machine_info = Machine.query.filter(Machine.id == machine_id).first()
if machine_info:
return machine_info.mac_no
return 'unknown'
@staticmethod
def get_rent_spot_name(spot_id):
spot_info = Spot.query.filter(Spot.id == spot_id).first()
if spot_info:
return spot_info.spotname
return 'unknown'
@staticmethod
def get_customer_phone(customer_id):
customer_info = Customer.query.filter(Customer.id == customer_id).first()
if customer_info:
return customer_info.phone
return 'unknown'
@staticmethod
def get_search_info_(key_word, page, limit):
sql = '''
SELECT rent.rent_no, production.rent_hatch_no, production.total, production.is_return,
production.return_hatch_no, customers.phone, rent.pay_time FROM rent
LEFT JOIN production ON production.rent_id = rent.id
LEFT JOIN customers ON customers.id = rent.customer_id
where rent.id in
(select id from rent where rent_no LIKE "%{key_word}%" or customer_id in
(select id from customers where phone LIKE "%{key_word}%"))
ORDER BY rent.pay_time DESC LIMIT {page},{limit}
'''.format(key_word=key_word, page=(page - 1) * limit, limit=limit)
infos = db.session.execute(sql)
data = []
for info in infos:
cur_info = {}
cur_info['rent_no'] = info.rent_no
cur_info['hatch_no'] = info.rent_hatch_no
cur_info['total'] = info.total
cur_info['phone'] = info.phone
if info.is_return == 1:
if cur_info['total'] <= 0:
if info.return_hatch_no == 127:
cur_info['status'] = 3
else:
cur_info['status'] = 2
else:
cur_info['status'] = 1
else:
cur_info['status'] = 0
data.append(cur_info)
return data
@staticmethod
def get_search_info(key_word):
search_info = db.session.query(Rent.rent_no, Production.rent_hatch_no, Production.total, Production.is_return,
Production.return_hatch_no, Customer.phone).outerjoin(Production,
Production.rent_id == Rent.id).join(
Customer,
Customer.id == Rent.customer_id).filter(
or_(Rent.rent_no.like('%' + str(key_word) + '%'), Customer.phone.like('%' + str(key_word) + '%'))).all()
data = []
for info in search_info:
cur_info = {}
cur_info['rent_no'] = info.rent_no
cur_info['hatch_no'] = info.rent_hatch_no
cur_info['total'] = info.total
if info.is_return == 1:
if cur_info['total'] <= 0:
cur_info['status'] = 2
elif info.return_hatch_no == 127:
cur_info['status'] = 3
else:
cur_info['status'] = 1
else:
cur_info['status'] = 0
data.append(cur_info)
return data
@staticmethod
def check_fee(rent_time, back_time, one_day_price, free_time):
'''
计算租借费用
:param rent_time:
:param back_time:
:param one_day_price:
:param free_time:
:return:
'''
back_time_date = datetime.datetime.strptime(back_time, '%Y-%m-%d %H:%M:%S')
rent_time_date = datetime.datetime.strptime(rent_time, '%Y-%m-%d %H:%M:%S')
use_time = (back_time_date - rent_time_date).total_seconds()
total = 0
use_m = round(use_time / 60, 2)
if use_time > free_time * 60:
days = (datetime.datetime(back_time_date.year, back_time_date.month,
back_time_date.day) - datetime.datetime(rent_time_date.year, rent_time_date.month,
rent_time_date.day)).days
total = one_day_price * (days + 1)
return {'total': total, 'use_m': use_m}
@staticmethod
def create_refund_no():
'''
生成退款单号
:return:
'''
data_str = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
int_str = str(random.randint(1, 999)).zfill(6)
return 'RF' + data_str + int_str
# -*- coding: utf-8 -*-
import datetime
import hashlib
import random
import time
from sqlalchemy.exc import SQLAlchemyError
from Model.Base import db
from Model.Repairs.RepairImagesModel import RepairImage
from Model.Repairs.RepairModel import Repair
class RepairService():
@staticmethod
def create(system_users_id, remark, tel, pics, spot_id, machine_id):
repair = RepairService.createRepairStub(system_users_id, remark, tel, spot_id, machine_id)
if repair:
try:
db.session.add(repair)
db.session.commit()
except SQLAlchemyError as e:
raise e
if len(pics) > 0:
for item in pics:
repair_images = RepairService.createRepairImage(repair.id, item)
if repair_images:
try:
db.session.add(repair_images)
db.session.commit()
except SQLAlchemyError as e:
raise e
return repair
@staticmethod
def createRepairImage(repair_id, pic):
repairImage = RepairImage()
repairImage.repairs_id = repair_id
repairImage.url = pic
repairImage.created_at = datetime.datetime.now()
repairImage.updated_at = datetime.datetime.now()
return repairImage
@staticmethod
def createRepairStub(system_users_id, remark, tel, spot_id, machine_id):
repair = Repair()
repair.system_users_id = system_users_id
repair.remark = remark
repair.tel = tel
repair.status = 0
repair.spot_id = spot_id
repair.machine_id = machine_id
repair.created_at = datetime.datetime.now()
repair.updated_at = datetime.datetime.now()
return repair
@staticmethod
def guid():
timestamp = int(time.time())
ranstr = random.randint(9999, 9999999999)
return RepairService.MD5(str(timestamp) + str(ranstr)) + RepairService.MD5(str(ranstr))[0: 8]
@staticmethod
def MD5(info):
m = hashlib.md5()
m.update(info.encode("utf-8"))
return m.hexdigest()
# -*- coding: utf-8 -*-
import datetime
import time
from Libs.Helper import Helper
from Model.Base import db
from Model.Income.DayIncomeModel import Dayincome
from Model.Production.ProductionModel import Production
from Model.Rent.RentModel import Rent
from Model.Settlement.SettlementModel import Settlement
from Service.IndexService import IndexService
class ReportService():
@staticmethod
def get_history_rent_number_admin(spot_id, start_time, end_time):
sql = '''
SELECT a.hours, a.total_rent, IFNULL(b.valid_rent,0) AS valid_rent, IFNULL(c.invalid_rent,0) AS invalid_rent
FROM (SELECT DATE_FORMAT(production.created_at,"%Y-%m-%d") AS hours, COUNT(*) AS total_rent
FROM production
WHERE production.is_out = 1 AND production.spot_id = {spot_id} AND production.is_out = 1
AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" GROUP BY DATE_FORMAT(production.created_at,"%Y-%m-%d")) a
LEFT JOIN (SELECT DATE_FORMAT(production.created_at,"%Y-%m-%d") AS hours, COUNT(*) AS valid_rent FROM production
WHERE production.is_out = 1 AND production.is_return = 1 AND production.spot_id = {spot_id}
AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" AND production.total > 0
GROUP BY DATE_FORMAT(production.created_at,"%Y-%m-%d")) b ON a.hours = b.hours
LEFT JOIN (SELECT DATE_FORMAT(production.created_at,"%Y-%m-%d") AS hours, COUNT(*) AS invalid_rent FROM production
WHERE production.is_out = 1 AND production.is_return = 1 AND production.spot_id = {spot_id}
AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" AND production.total <= 0
GROUP BY DATE_FORMAT(production.created_at,"%Y-%m-%d")) c ON a.hours = c.hours
'''.format(spot_id=spot_id, start_time=start_time, end_time=end_time)
info = db.session.execute(sql)
total_data = {}
my_data = []
for i in info:
total_data[str(i.hours)] = {'total_rent': i.total_rent, 'valid_rent': i.valid_rent,
'invalid_rent': i.invalid_rent}
days = (end_time - start_time).days + 1
for i in range(days):
cur_info = {}
cur_date = datetime.date.today() - datetime.timedelta(days=(days - i))
cur_info['date'] = cur_date.strftime('%Y-%m-%d')
cur_info['total_rent'] = total_data[str(cur_date.strftime('%Y-%m-%d'))]['total_rent'] if str(
cur_date.strftime('%Y-%m-%d')) in total_data.keys() else 0
cur_info['valid_rent'] = total_data[str(cur_date.strftime('%Y-%m-%d'))]['valid_rent'] if str(
cur_date.strftime('%Y-%m-%d')) in total_data.keys() else 0
cur_info['invalid_rent'] = total_data[str(cur_date.strftime('%Y-%m-%d'))]['invalid_rent'] if str(
cur_date.strftime('%Y-%m-%d')) in total_data.keys() else 0
my_data.append(cur_info)
return my_data
@staticmethod
def get_history_rent_number_agent(spot_id, start_time, end_time):
sql = '''
SELECT DATE_FORMAT(production.created_at,"%Y-%m-%d") AS hours, COUNT(*) AS total_rent
FROM production
WHERE production.is_out = 1 AND production.spot_id = {spot_id} AND production.is_out = 1
AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" GROUP BY DATE_FORMAT(production.created_at,"%Y-%m-%d")
'''.format(spot_id=spot_id, start_time=start_time, end_time=end_time)
info = db.session.execute(sql)
total_data = {}
my_data = []
for i in info:
total_data[str(i.hours)] = {'total_rent': i.total_rent}
days = (end_time - start_time).days + 1
for i in range(days):
cur_info = {}
cur_date = datetime.date.today() - datetime.timedelta(days=(days - i))
cur_info['date'] = cur_date.strftime('%Y-%m-%d')
cur_info['total_rent'] = total_data[str(cur_date.strftime('%Y-%m-%d'))]['total_rent'] if str(
cur_date.strftime('%Y-%m-%d')) in total_data.keys() else 0
my_data.append(cur_info)
return my_data
@staticmethod
def get_today_rent_number_admin(spot_id):
start_time, end_time = Helper.getTodayDate()
sql = '''
SELECT a.hours, a.total_rent, IFNULL(b.valid_rent,0) AS valid_rent, IFNULL(c.invalid_rent, 0) AS invalid_rent FROM
(SELECT DATE_FORMAT(production.created_at,"%H") AS hours, COUNT(*) AS total_rent FROM production
WHERE production.spot_id = {spot_id} AND production.is_out = 1 AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" GROUP BY DATE_FORMAT(production.created_at,"%H")) a
LEFT JOIN (SELECT DATE_FORMAT(production.created_at,"%H") AS hours, COUNT(*) AS valid_rent FROM production
WHERE production.is_out = 1 AND production.is_return = 1 AND production.spot_id = {spot_id} AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" AND production.total > 0
GROUP BY DATE_FORMAT(production.created_at,"%H")) b ON a.hours = b.hours
LEFT JOIN (SELECT DATE_FORMAT(production.created_at,"%H") AS hours, COUNT(*) AS invalid_rent FROM production
WHERE production.is_out = 1 AND production.is_return = 1 AND production.spot_id = {spot_id} AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" AND production.total <= 0
GROUP BY DATE_FORMAT(production.created_at,"%H")) c ON a.hours = c.hours
'''.format(spot_id=spot_id, start_time=start_time, end_time=end_time)
info = db.session.execute(sql)
total_data = {}
my_data = []
for i in info:
total_data[int(i.hours)] = {'total_rent': i.total_rent, 'valid_rent': i.valid_rent,
'invalid_rent': i.invalid_rent}
for i in range(24):
cur_info = {}
cur_info['hour'] = i
cur_info['total_rent'] = total_data[i]['total_rent'] if i in total_data.keys() else 0
cur_info['valid_rent'] = total_data[i]['valid_rent'] if i in total_data.keys() else 0
cur_info['invalid_rent'] = total_data[i]['invalid_rent'] if i in total_data.keys() else 0
my_data.append(cur_info)
return my_data
@staticmethod
def get_today_rent_number_agent(spot_id):
start_time, end_time = Helper.getTodayDate()
sql = '''
SELECT DATE_FORMAT(production.created_at,"%H") AS hours, COUNT(*) AS total_rent FROM production
WHERE production.spot_id = {spot_id} AND production.is_out = 1 AND production.created_at >= "{start_time}"
AND production.created_at <= "{end_time}" GROUP BY DATE_FORMAT(production.created_at,"%H")
'''.format(spot_id=spot_id, start_time=start_time, end_time=end_time)
info = db.session.execute(sql)
total_data = {}
my_data = []
for i in info:
total_data[int(i.hours)] = {'total_rent': i.total_rent}
for i in range(24):
cur_info = {}
cur_info['hour'] = i
cur_info['total_rent'] = total_data[i]['total_rent'] if i in total_data.keys() else 0
my_data.append(cur_info)
return my_data
@staticmethod
def get_customer_rent_number(spot_id):
rent_number = Rent.query.with_entities(Rent.number).filter(Rent.spot_id == spot_id).all()
number_one = 0
number_two = 0
number_three = 0
for i in rent_number:
if i.number == 1:
number_one += 1
elif i.number == 2:
number_two += 1
elif i.number == 3:
number_three += 1
return {'one': number_one, 'two': number_two, 'three': number_three}
@staticmethod
def get_customer_rent_time(spot_id):
rent_info = db.session.query(Production, Rent).join(Rent, Rent.id == Production.rent_id).filter(
Production.spot_id == spot_id, Rent.spot_id == spot_id).all()
less_one = 0
larger_two = 0
one_two = 0
for info in rent_info:
if info.Production.return_time is None or info.Rent.pay_time is None:
continue
use_time = Helper.checkTime(info.Rent.pay_time, info.Production.return_time)
if use_time < 60:
less_one += 1
elif use_time > 120:
larger_two += 1
else:
one_two += 1
return {'less_one': less_one, 'larger_two': larger_two, 'one_two': one_two}
@staticmethod
def get_spot_day_income(spot_id, start_time, end_time, days):
where = {
Dayincome.spot_id == spot_id,
Dayincome.day >= start_time,
Dayincome.day <= end_time
}
day_income_info = Dayincome.query.filter(*where).all()
data = {}
for info in day_income_info:
data[info.day.strftime('%Y-%m-%d')] = info.total
new_data = []
for i in range(days):
tmp = {}
now = datetime.datetime.now() - datetime.timedelta(days=(days - i))
now = now.strftime('%Y-%m-%d')
tmp['day'] = now
if now in data:
tmp['total'] = round(data[now] / 100, 2)
else:
tmp['total'] = 0
new_data.append(tmp)
return new_data
@staticmethod
def get_spot_month_income(spot_id, start_time, end_time):
where = {
Settlement.spot_id == spot_id,
Settlement.month >= start_time,
Settlement.month <= end_time
}
month_income_info = Settlement.query.filter(*where).all()
data = []
for info in month_income_info:
tmp = {
'month': info.month,
'total': round(info.total / 100, 2)
}
data.append(tmp)
return data
@staticmethod
def get_spot_rent_record(spot_id, data_type, date, page, limit):
where = {
Rent.is_over == 1,
Rent.spot_id == spot_id,
}
income = 0
if data_type == 1:
where.add(Rent.created_at >= date + ' 00:00:00')
where.add(Rent.created_at <= date + ' 23:59:59')
income, total = IndexService.get_total_production(spot_id, date + ' 00:00:00', date + ' 23:59:59')
else:
last_date = Helper.get_this_month_day(date)
if last_date:
where.add(Rent.created_at >= date + '-01 00:00:00')
where.add(Rent.created_at <= date + last_date)
income, total = IndexService.get_total_production(spot_id, date + '-01 00:00:00', date + last_date)
rent_info = Rent.query.filter(*where).order_by(Rent.created_at.desc()).slice(page * limit,
(page + 1) * limit).all()
data = []
for info in rent_info:
cur_total = round(info.real_total / 100, 2)
tmp = {
'real_total': cur_total,
'over_time': Helper.getFormatDate(info.created_at)
}
data.append(tmp)
return income, data
# -*- coding: utf-8 -*-
import random
import string
from qcloudsms_py import SmsSingleSender
from qcloudsms_py.httpclient import HTTPError
from Config.common_config import SMS_CONFIG
from Libs.Logger import logger
from Redis_Cache import redis
class SMSService():
def __init__(self):
self.appid = SMS_CONFIG['app_id']
self.appKey = SMS_CONFIG['app_key']
try:
self.ssender = SmsSingleSender(self.appid, self.appKey)
except Exception as e:
print(e)
def create_code(self, length=4):
'''
生成验证码
:param length:
:return:
'''
verification = []
letters = string.digits
for i in range(length):
letter = letters[random.randint(0, 9)]
verification.append(letter)
return "".join(verification)
def make_code(self, phoneNumber):
'''
设置验证码300秒有效
:param phoneNumber:
:return:
'''
code = self.create_code(4)
redis.set('V_C' + str(phoneNumber), code, 300)
logger.info("code: " + code)
return code
def phoneSendCode(self, phoneNumber, tempId, sign='灰兔智能'):
'''
发送验证码
:param phoneNumber:
:param tempId:
:param sign:
:return:
'''
code = self.make_code(phoneNumber)
params = [code]
try:
result = self.ssender.send_with_param(86, phoneNumber, tempId, params, sign=sign, extend="", ext='')
return result
except HTTPError as e:
print(e)
except Exception as e:
print(e)
return
def phoneSendCodeWithContent(self, phoneNumber, tempId, Content, sign='灰兔智能'):
'''
发送验证码
:param phoneNumber:
:param tempId:
:param sign:
:return:
'''
try:
result = self.ssender.send_with_param(86, phoneNumber, tempId, Content, sign=sign, extend="", ext='')
return result
except HTTPError as e:
print(e)
except Exception as e:
print(e)
return
def verificate(self, phoneNumber, code):
'''
判断验证码,-1验证码过期 -2验证码错误 0匹配
:param phoneNumber:
:param code:
:return:
'''
logger.info("phone:" + phoneNumber + ", code:" + code)
ver = redis.get('V_C' + str(phoneNumber))
logger.info(ver)
if ver is None:
return -1
else:
if ver == str(code).encode('utf-8'):
return 0
else:
return -2
# -*- coding: utf-8 -*-
from xpinyin import Pinyin
from Config.common_config import ACCOUNT_STATUS
from Model.Agent.AgentAccountModel import AgentAccount
from Model.Agent.AgentSpotModel import AgentSpot
from Model.Base import db
from Model.Machine.MachineModel import Machine
from Model.Spot.SpotModel import Spot
class SpotService():
@staticmethod
def get_spot_info():
infos = []
spot_info = Spot.query.with_entities(Spot.spotname, Spot.id).all()
for info in spot_info:
cur_info = {}
cur_info['id'] = info.id
cur_info['letter'] = SpotService.get_pinyin(info.spotname)
cur_info['spotname'] = info.spotname
cur_info['agent_info'] = SpotService.get_agent_spot(info.id)
infos.append(cur_info)
return infos
@staticmethod
def get_agent_spot(spot_id):
agent_spot = db.session.query(AgentSpot, AgentAccount).join(AgentAccount,
AgentAccount.id == AgentSpot.agent_no).filter(
AgentSpot.spot_no == spot_id, AgentAccount.status == ACCOUNT_STATUS['on_use'],
AgentSpot.status == ACCOUNT_STATUS['on_use']).all()
total_info = []
for info in agent_spot:
cur_info = {}
cur_info['agent_name'] = info.AgentAccount.user_name
cur_info['phone'] = info.AgentAccount.phone
cur_info['comment'] = info.AgentAccount.comment
cur_info['spot_info'] = SpotService.get_spot_agent(info.AgentAccount.id)
total_info.append(cur_info)
return total_info
@staticmethod
def get_spot_agent(agent_id):
spot_agent = db.session.query(AgentAccount, AgentSpot, Spot).join(AgentSpot,
AgentAccount.id == AgentSpot.agent_no).join(
Spot, Spot.id == AgentSpot.spot_no).filter(AgentAccount.id == agent_id,
AgentAccount.status == ACCOUNT_STATUS['on_use'],
AgentSpot.status == ACCOUNT_STATUS['on_use']).all()
total_info = []
for info in spot_agent:
cur_info = {}
cur_info['spot_id'] = info.Spot.id
cur_info['spot_name'] = info.Spot.spotname
total_info.append(cur_info)
return total_info
@staticmethod
def get_pinyin(word):
s = Pinyin().get_initials(word)
return s[0:1].upper()
@classmethod
def get_spot_machine_list(cls, spot_id):
res = Machine.query.filter_by(spot_id=spot_id).all()
if res:
result = []
for i in res:
tmp = {
"id": i.id,
"mac_no": i.mac_no
}
result.append(tmp)
return result
else:
return []
# -*- coding: utf-8 -*-
from Model.Power.PowerModel import Power
class ToolService():
@staticmethod
def get_power_info_by_machine(machine_id):
power_data = []
power_infos = Power.query.filter_by(machine_id=machine_id).order_by(Power.hatch_no.asc()).all()
if not power_infos:
for i in range(55):
cur_power = {}
cur_power['hatch_no'] = i+1
cur_power['power'] = 0
cur_power['status'] = 0
power_data.append(cur_power)
else:
for power_info in power_infos:
cur_power = {}
cur_power['hatch_no'] = power_info.hatch_no
cur_power['power'] = power_info.has_power
if power_info.status == 7:
cur_power['status'] = 7
else:
cur_power['status'] = 1
power_data.append(cur_power)
return power_data
# -*- coding: utf-8 -*-
import hashlib
import uuid
import xml.etree.ElementTree as ET
import requests
from Config.common_config import MINA_APP
from Libs.Logger import logger
class WeChatService():
def __init__(self, app_id=None, app_key=None, mch_id=None, pay_key=None, pay_cert_path=None, pay_key_path=None):
self.app_id = MINA_APP["app_id"] if not app_id else app_id
self.app_key = MINA_APP["app_key"] if not app_key else app_key
self.mch_id = MINA_APP["mch_id"] if not mch_id else mch_id
self.pay_key = MINA_APP["pay_key"] if not pay_key else pay_key
self.pay_cert_path = MINA_APP["wx_pay_cert_path"] if not pay_cert_path else pay_cert_path
self.pay_key_path = MINA_APP["wx_pay_key_path"] if not pay_key_path else pay_key_path
self.default_data = {
"appid": self.app_id,
"mch_id": self.mch_id,
"nonce_str": self.get_nonce_str()
}
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.pay_key)
sign = hashlib.md5(stringSignTemp.encode("utf-8")).hexdigest()
return sign.upper()
def refund(self, refund_data=None):
'''
申请退款信息
:param refund_data:
:return:
'''
refund_data.update(self.default_data)
sign = self.create_sign(refund_data)
refund_data['sign'] = sign
xml_data = self.dict_to_xml(refund_data)
headers = {'Content-Type': 'application/xml'}
url = "https://api.mch.weixin.qq.com/secapi/pay/refund"
cert = (self.pay_cert_path, self.pay_key_path)
r = requests.post(url=url, data=xml_data.encode('utf-8'), headers=headers, cert=cert)
r.encoding = 'utf-8'
logger.info(r.text)
if r.status_code == 200:
_return_data = self.xml_to_dict(r.text)
if _return_data["return_code"] == "SUCCESS":
if _return_data["result_code"] == "SUCCESS":
return True
return False
def query_refund_info(self, refund_data=None):
'''
查询退款信息
:param refund_data:
:return:
'''
refund_data.update(self.default_data)
sign = self.create_sign(refund_data)
refund_data['sign'] = sign
xml_data = WeChatService.dict_to_xml(refund_data)
headers = {'Content-Type': 'application/xml'}
url = 'https://api.mch.weixin.qq.com/pay/refundquery'
r = requests.post(url=url, data=xml_data.encode('utf-8'), headers=headers)
r.encoding = 'utf-8'
logger.info("查询退款信息参数")
logger.info(r.text)
if r.status_code == 200:
_return_data = WeChatService.xml_to_dict(r.text)
return _return_data
return False
@staticmethod
def get_nonce_str():
'''
获取随机字符串
:return:
'''
return str(uuid.uuid4()).replace('-', '')
@staticmethod
def dict_to_xml(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)
@staticmethod
def xml_to_dict(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
from flask import Flask, request, url_for, jsonify, g
from flask_cors import CORS
from Libs.ErrorTips import TOKEN_NOT_PROVIDER_ERROR, TOKEN_NOT_VALID_ERROR, TOKEN_EXPIRE_ERROR
from Libs.Logger import logger
from Model.Agent.AgentAccountModel import AgentAccount
from Service.AgentService import AgentService
from Model.Base import db
from Redis_Cache import redis
from Controller.IndexController import route_index
from Controller.ToolController import route_tool
from Controller.AccountController import route_account
from Controller.ReportController import route_report
from Controller.RentController import route_rent
from Controller.RepairController import route_repair
from Controller.SpotController import route_spot
from Controller.InvoiceController import route_invoice
app = Flask(__name__)
app.config.from_object('Config.base_config')
CORS(app)
# 初始化数据库
db.init_app(app)
# 初始化redis
redis.init_app(app)
app.register_blueprint(route_index, url_prefix='/business/index')
app.register_blueprint(route_tool, url_prefix='/business/tool')
app.register_blueprint(route_account, url_prefix='/business/account')
app.register_blueprint(route_report, url_prefix='/business/report')
app.register_blueprint(route_rent, url_prefix='/business/rent')
app.register_blueprint(route_repair, url_prefix='/business/repair')
app.register_blueprint(route_spot, url_prefix='/business/spot')
app.register_blueprint(route_invoice, url_prefix='/business/invoice')
@app.before_request
def log_enter_interface():
logger.info("#################### 进入 {} 接口 ####################".format(request.path))
@app.before_request
def verify_auth_token():
'''
用户登录验证token
:return:
'''
NO_AUTH_CHECK_URL = [url_for('account.test'), url_for('account.login'), url_for('account.send_code')]
if request.path not in NO_AUTH_CHECK_URL:
token = request.headers.get('token')
if not token:
return jsonify(TOKEN_NOT_PROVIDER_ERROR)
result = AgentService.check_agent_token(token)
if result == 1:
return jsonify(TOKEN_NOT_VALID_ERROR)
elif result == 2:
return jsonify(TOKEN_EXPIRE_ERROR)
else:
g.user = result
logger.info("本次登录用户名称:{0},手机号:{1},类型:{2}".format(result.user_name, result.phone, result.level_desc))
@app.after_request
def log_out_interface(environ):
logger.info("#################### 退出 {} 接口 ####################\n".format(request.path))
return environ
if __name__ == '__main__':
app.run(port='5056')
altgraph==0.16.1
APScheduler==3.6.1
autopy==2.1.0
backports.csv==1.0.7
certifi==2019.6.16
chardet==3.0.4
cipher==0.1
Click==7.0
colorama==0.4.1
configobj==5.0.6
crypto==1.4.1
defusedxml==0.6.0
Django==2.2.1
docopt==0.6.2
dpkt==1.9.2
dss==0.8
et-xmlfile==1.0.1
Flask==1.0.3
Flask-Cache==0.13.1
Flask-Caching==1.7.2
Flask-Cors==3.0.8
flask-redis==0.4.0
Flask-Script==2.0.6
flask-sqlacodegen==1.1.6.1
Flask-SQLAlchemy==2.4.0
future==0.17.1
idna==2.8
inflect==2.1.0
itsdangerous==1.1.0
jdcal==1.4.1
Jinja2==2.10.1
jsonify==0.5
macholib==1.11
MarkupSafe==1.1.1
mysqlclient==1.4.2.post1
Naked==0.1.31
netifaces==0.10.9
odfpy==1.4.0
openpyxl==2.4.11
pefile==2019.4.18
psutil==5.6.2
pycryptodome==3.8.2
PyInstaller==3.4
PyMySQL==0.9.3
python-xlib==0.25
pytz==2019.1
pywin32-ctypes==0.2.0
PyYAML==5.1.1
qcloudsms-py==0.1.3
qrcode==6.1
records==0.5.3
redis==3.2.1
requests==2.22.0
schedule==0.6.0
Serializer==0.2.1
shellescape==3.4.1
simplejson==3.16.0
singledispatch==3.4.0.3
six==1.12.0
SQLAlchemy==1.3.5
sqlparse==0.3.0
tablib==0.13.0
tzlocal==2.0.0
urllib3==1.25.3
Werkzeug==0.15.4
xlrd==1.2.0
xlwt==1.3.0
ps -ef|grep 'tour_business/uwsgi.ini' |grep -v grep|cut -c 9-15|xargs kill -9
nohup /root/.pyenv/versions/env4tour_business/bin/uwsgi --ini /data/www/tour_business/uwsgi.ini >/dev/null 2>&1 &
[uwsgi]
# uwsgi 启动时所使用的地址与端口
socket = 127.0.0.1:5056
# 指向网站目录
chdir = /data/www/tour_business
# python 启动程序文件
wsgi-file = app.py
# python 程序内用以启动的 application 变量名
callable = app
# 处理器数
processes = 1
# 线程数
threads = 2
daemonize = /data/www/tour_business/server.log
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment