kboss/b/zj/zj_get_bill.dspy
2025-07-16 14:27:17 +08:00

256 lines
13 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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