256 lines
13 KiB
Plaintext
256 lines
13 KiB
Plaintext
async def zj_get_bill(nss={}):
|
||
"""
|
||
if nss['user_id'] can get single person bill
|
||
passing parameters: billMonth, payTime, user_id
|
||
:param nss: "billMonth": "2023-08" / "payTime": "2023/08/07"
|
||
:return:
|
||
"""
|
||
|
||
# logger = logging.getLogger('job_info')
|
||
# logging.basicConfig(level=logging.INFO,
|
||
# format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
|
||
# datefmt='%Y-%m-%d %H:%M:%S',
|
||
# filename='zj_bill_scheduler.log',
|
||
# filemode='a')
|
||
# nss = {
|
||
# 'orgid': '',
|
||
# 'billMonth': '',
|
||
# 'payTime': ''
|
||
# }
|
||
|
||
# if not begin and end time, get current day
|
||
# 获取当前时间
|
||
now_time = datetime.datetime.now()
|
||
# 获取前一天时间
|
||
end_time = now_time + datetime.timedelta(days=-1)
|
||
# 前一天时间只保留 年-月-日
|
||
enddate = end_time.strftime('%Y/%m/%d')
|
||
if not nss.get('billMonth'):
|
||
nss['billMonth'] = time.strftime('%Y-%m')
|
||
if not nss.get('payTime'):
|
||
nss['payTime'] = enddate
|
||
print("中金账单时间billMonth: %s, payTime: %s" % (nss.get('billMonth'), nss.get('payTime')))
|
||
ns = {
|
||
'ak': 'c752863753f8',
|
||
'sk': 'c6efdbd682084a2f96e7500e5a535449',
|
||
'appId': 'cdz-server',
|
||
# 'userid': 'sa-9_B-VjlnhaUzAzUvZt',
|
||
"supId": "99",
|
||
"page": "1",
|
||
"limit": "1000",
|
||
# "billMonth": "2023-08",
|
||
"billMonth": nss.get('billMonth'),
|
||
# "payTime": "2023/08/07"
|
||
"payTime": nss.get('payTime')
|
||
}
|
||
ak = ns.get('ak')
|
||
sk = ns.get('sk')
|
||
appId = ns.get('appId')
|
||
if not (ak and sk and appId):
|
||
return {
|
||
"code":"1",
|
||
"msg":"ak or sk or appId is None"
|
||
}
|
||
timestamp = str(int(time.time() * 1000))
|
||
token = str(uuid())
|
||
sign = sk + appId + token + timestamp
|
||
md5_object = hashlib.md5()
|
||
md5_object.update(sign.encode())
|
||
sign = md5_object.hexdigest()
|
||
db = DBPools()
|
||
async with db.sqlorContext('kboss') as sor:
|
||
# 获取中金id
|
||
jncs_li = await sor.R('organization', {'orgname': '中金超算', 'del_flg': '0'})
|
||
jscs_id = jncs_li[0].get('id')
|
||
|
||
# get sync already user
|
||
users_li = await sor.R('zj_users', {'sync_status': 1, 'del_flg': '0'})
|
||
|
||
# filter single person
|
||
if nss.get('user_id'):
|
||
users_li = [1]
|
||
|
||
for user in users_li:
|
||
nss['orgid'] = user.get('orgid')
|
||
# find uin from zj_user
|
||
if nss.get('orgid'):
|
||
orgid = nss.get('orgid')
|
||
else:
|
||
orgid_li = await sor.R('users', {'id': await get_user()})
|
||
orgid = orgid_li[0].get('orgid') if orgid_li else ''
|
||
|
||
# 这个人所在的销售机构id
|
||
parent_find_li = await sor.R('organization', {'id': orgid})
|
||
parent_id = parent_find_li[0].get('parentid') if parent_find_li else ''
|
||
|
||
uin_li = await sor.R('zj_users', {'orgid': orgid})
|
||
uin = uin_li[0].get('thirdid') if uin_li else ''
|
||
if not (orgid and uin):
|
||
return {
|
||
'status': False,
|
||
'msg': 'get bill failed, orgid or uin is empty...'
|
||
}
|
||
url = 'http://101.36.139.188:8888/cdz-admin/zjapi/v1/bill/list'
|
||
header = {
|
||
'content-type': 'application/json',
|
||
'appId': appId,
|
||
'ak': ak,
|
||
'timestamp': timestamp,
|
||
'token': token,
|
||
'sign': sign
|
||
}
|
||
data = {
|
||
"supId": '99',
|
||
"uin": uin,
|
||
"page": ns.get('page'),
|
||
"limit": ns.get('limit') or '1000',
|
||
"billMonth": ns.get('billMonth'),
|
||
"payTime": ns.get('payTime')
|
||
}
|
||
res = requests.post(url=url, headers=header, json=data)
|
||
res_data = json.loads(res.text)
|
||
code = json.loads(res.text).get('code')
|
||
if code != 200:
|
||
return res_data
|
||
else:
|
||
data_list = res_data.get('data').get('list') if res_data.get('data') else []
|
||
# get all bill id
|
||
bills = await sor.R('zj_bill', {})
|
||
orderid_list = [bill.get('zj_orderid') for bill in bills]
|
||
if data_list:
|
||
try:
|
||
for bill_local in data_list:
|
||
existid = bill_local.get('orderId') # TODO 字段唯一性 如何去重字段
|
||
if existid in orderid_list:
|
||
continue
|
||
bill_local['id'] = uuid()
|
||
bill_local['customerid'] = orgid
|
||
bill_local['zj_orderid'] = bill_local.get('orderId')
|
||
lowercase_dict = {key.lower(): value for key, value in bill_local.items()}
|
||
# add zj_bill
|
||
await sor.C('zj_bill', lowercase_dict) # TODO zj_orderId 字段修改 payTime不是null create_at字段失效
|
||
|
||
# modify the starting time through fee time
|
||
update_order_time_sql = """UPDATE customer_goods set start_date = '%s', expire_date = '%s'WHERE orderid = '%s';""" % \
|
||
(lowercase_dict['feebegintime'], lowercase_dict['feeendtime'], lowercase_dict['orderid'])
|
||
await sor.sqlExe(update_order_time_sql, {})
|
||
|
||
actionTypeName = bill_local['actionTypeName']
|
||
if '退款' in actionTypeName:
|
||
business_op = 'BUY_REVERSE'
|
||
else:
|
||
business_op = 'BUY'
|
||
|
||
# 计算折扣后的价格
|
||
# 获取针对个人的折扣配置
|
||
real_discount = 1.0
|
||
person_discount_sql = """select * from saleprotocol where offer_orgid = '%s' and bid_orgid = '%s' and
|
||
salemode = '0' and del_flg = '0' and CURRENT_DATE <= end_date and
|
||
CURRENT_DATE >= start_date""" % (parent_id, orgid)
|
||
tongyi_discount_sql = """select * from saleprotocol where offer_orgid = '%s' and bid_orgid = '*' and
|
||
salemode = '0' and del_flg = '0' and CURRENT_DATE <= end_date and
|
||
CURRENT_DATE >= start_date""" % parent_id
|
||
# 没有个人配置 获取中金产品统一配置折扣
|
||
for sql_detail in [person_discount_sql, tongyi_discount_sql]:
|
||
person_discount_li = await sor.sqlExe(sql_detail, {})
|
||
for person_discount in person_discount_li:
|
||
protocolid = person_discount['id']
|
||
xieyi_zi_search_li = await sor.R('product_salemode', {'protocolid': protocolid, 'del_flg': '0'})
|
||
for xieyi_zi in xieyi_zi_search_li:
|
||
# 协议会同时存在两个产品 一个是正常产品id 另外一个是*
|
||
# *会存在 此处过滤 不会影响折扣设置
|
||
if xieyi_zi['productid'] == '*':
|
||
continue
|
||
provider_zi_id = xieyi_zi['providerid']
|
||
zi_discount = xieyi_zi['discount']
|
||
if provider_zi_id == jscs_id:
|
||
# 判断产品是否存在 有可能在产品表已经删除
|
||
prd_res_exists_li = await sor.R('product', {'id': xieyi_zi['productid'], 'del_flg': '0'})
|
||
if not prd_res_exists_li:
|
||
continue
|
||
real_discount = float(zi_discount)
|
||
break
|
||
if real_discount != 1.0:
|
||
break
|
||
realcost = float(bill_local.get('realCost')) if bill_local.get('realCost') else 0
|
||
|
||
# if not realcost assume mistake, but postPay realcost is 0
|
||
# if not realcost:
|
||
# raise ValueError("bill realcost is empty")
|
||
|
||
amount = real_discount * realcost
|
||
# add bill
|
||
nss_bill = {
|
||
'id': uuid(),
|
||
'customerid': orgid,
|
||
'orderid': bill_local.get('orderId'),
|
||
'business_op': business_op,
|
||
'provider_amt': bill_local.get('realCost'),
|
||
'amount': amount,
|
||
'bill_date': bill_local.get('payTime').split(" ")[0].replace('/', '-'),
|
||
'bill_timestamp': bill_local.get('payTime'),
|
||
'bill_state': 0, # TODO 字段调整
|
||
'productid': bill_local.get('productCode'),
|
||
'providerid': jscs_id,
|
||
'provider_billid': bill_local['id'],
|
||
'resourceid': bill_local.get('resourceId'),
|
||
'quantity': 1
|
||
}
|
||
# add data to bill
|
||
await sor.C('bill', nss_bill)
|
||
|
||
# 比对账户余额和账单金额
|
||
balance_yuan = await getCustomerBalance(sor, orgid)
|
||
print('%s orgid: %s, 余额为: %s' % (time.strftime('%Y-%m-%d %H:%M:%S'), orgid, balance_yuan))
|
||
print('将要扣除的金额: %s' % nss_bill['amount'])
|
||
if not balance_yuan:
|
||
print('%s 用户%s 余额为空' % (time.strftime('%Y-%m-%d %H:%M:%S'), orgid))
|
||
raise ValueError("用户余额为空")
|
||
if balance_yuan < amount:
|
||
print('%s 用户%s 余额不足' % (time.strftime('%Y-%m-%d %H:%M:%S'), orgid))
|
||
raise ValueError("用户余额不足")
|
||
|
||
# 记账
|
||
ba = BillAccounting(nss_bill)
|
||
await ba.accounting(sor)
|
||
|
||
# 修改本地bill状态 0:未支付,1:已支付;2:已取消
|
||
ns_bill_status = {
|
||
'id': nss_bill['id'],
|
||
'bill_state': 1
|
||
}
|
||
await sor.U('bill', ns_bill_status)
|
||
|
||
# 修改订单状态 0:未支付,1:已交付;2:已关闭;3:已取消;4:后付费
|
||
# 获取订单id
|
||
if not '按量' in bill_local['payModeName']:
|
||
orderid_get_sql = """SELECT zo.*, bo.id AS boid FROM zj_order zo, bz_order bo WHERE zo.id =
|
||
bo.provider_orderid AND zo.customerid = '%s' AND zo.orderId = '%s';""" \
|
||
% (orgid, bill_local['zj_orderid'])
|
||
bz_order_id_li = await sor.sqlExe(orderid_get_sql, {})
|
||
if not bz_order_id_li:
|
||
print('无法从zj_order中获取指定orderid, %s' % bill_local)
|
||
with open('zj_bill.log', 'a+') as f:
|
||
f.write('%s orgid: %s, 无法从zj_order表中获取orderid: %s' %
|
||
(time.strftime('%Y-%m-%d %H:%M:%S'), orgid, bill_local))
|
||
else:
|
||
bz_order_id = bz_order_id_li[0]['boid']
|
||
ns_order_status = {
|
||
'id': bz_order_id,
|
||
'order_status': 1
|
||
}
|
||
await sor.U('bz_order', ns_order_status)
|
||
print('orgid: %s, res_data: %s' % (orgid, res_data))
|
||
except Exception as e:
|
||
print('%s get bill failed' % time.strftime('%Y-%m-%d %H:%M:%S'))
|
||
raise e
|
||
else:
|
||
print('%s orgid: %s bill is emtpy' % (time.strftime('%Y-%m-%d %H:%M:%S'), orgid))
|
||
print('%s get all users bill success' % time.strftime('%Y-%m-%d %H:%M:%S'))
|
||
return {
|
||
'status': True,
|
||
'msg': 'get bill success'
|
||
}
|
||
|
||
ret = await zj_get_bill(params_kw)
|
||
return ret |