pricing/pricing/pricing.py
2025-12-23 17:16:53 +08:00

130 lines
3.7 KiB
Python

import json
from ahserver.serverenv import ServerEnv
from sqlor.dbpools import DBPools
from appPublic.log import debug, exception
class PricingProgram:
def __init__(self, ppid, sor):
self.ppid = ppid
self.sor = sor
async def init(self):
await self.get_program()
await self.get_pricing_type()
async def get_program(self):
recs = await self.sor.R('pricing_program', {'id': self.ppid})
if len(recs):
self.__dict__.update(recs[0])
async def get_pricing_type(self):
self.pricing_type = await self.sor.R('pricing_type',
{'id': self.ptid})
async def get_items(self, biz_date=None):
if biz_date is None:
env = ServerEnv()
biz_date = await env.get_business_date(self.sor)
ppts = await self.get_program_timing(biz_date)
if len(ppts) < 1:
return None
ppt = ppts[0]
recs = await self.sor.R('pricing_item', {'pptid': ppt.id})
return recs
async def get_program_timing(self, biz_date):
sql = """select * from pricing_program_timing
where enabled_date >= ${biz_date}$
and expired_date < ${biz_date}$
and ppid = ${ppid}$
"""
return await self.sor.sqlExe(sql, {'ppid':self.ppid,
'biz_date': biz_date})
async def get_specs(self):
recs = await self.sor.R('pricing_spec', {'ptid': self.ptid})
return recs
async def get_spec_by_id(self, psid):
recs = await self.sor.R('pricing_spec', {'id': psid})
if len(recs) > 0:
return recs[0]
return None
async def get_specs(sor, psid):
sql = """select a.* from pricing_spec a where a.id=${psid}$"""
recs = await sor.sqlExe(sql, {'psid': psid})
if len(recs)>0:
return recs[0]
return None
async def sor_get_program_items(sor, ppid, biz_date):
sql = """select b.* from pricing_program_timing a, pricing_item b
where b.pptid = a.id
and a.ppid = ${ppid}$
and a.enabled_date <= ${biz_date}$
and a.expired_date > ${biz_date}$
"""
recs = await sor.sqlExe(sql, {'ppid': ppid, 'biz_date': biz_date})
return recs
async def get_pricing_specs_by_pptid(pptid):
env = ServerEnv()
dbname = env.get_module_dbname('pricing')
db = DBPools()
async with db.sqlorContext(dbname) as sor:
sql = """select d.*
from pricing_program_timing a, pricing_program b, pricing_type c, pricing_spec d
where a.ppid = b.id
and b.ptid = c.id
and d.ptid = c.id
and a.id = ${pptid}$"""
recs = await sor.sqlExe(sql, {'pptid': pptid})
return recs
return []
async def get_remote_pricing(sor, charge, data):
env = ServerEnv()
get_callerid = env.get_callerid
userid = await get_callerid(self.ownerid)
uapi = UAPI()
ret = await uapi.call(charge.upappid, charge.apiname,
userid, params=data)
d = json.loads(ret.decode('utf-8'))
return d
async def pricing_program_charging(sor, pricing_program_id, data):
env = ServerEnv()
if not data.get('biz_date'):
biz_date = await env.get_business_date(self.sor)
data['biz_date'] = biz_date
debug(f'{pricing_program_id=}, {data=}')
pp_items = await sor_get_program_items(sor, pricing_program_id, data['biz_date'])
charges = []
debug(f'{pp_items=}, {data["biz_date"]=}')
for item in pp_items:
charge = item.copy()
spec = await get_specs(sor, charge.psid)
if spec.pricing_spec_mode == 'spec_amount':
if item.spec_value:
d = json.loads(item.spec_value)
for k,v in d.items():
if v != item['k']:
continue
cnt = data.get(spec.count_name, 1)
if charge.pricing_unit is None or charge.pricing_unit < 1:
charge.pricing_unit = 1
charge.amount = cnt * charge.pricing_amount / charge.pricing_unit
charges.append(charge)
elif spec.pricing_spec_mode == 'remote_pricing':
charge.amount = await get_remote_pricing(sor, charge, params=d)
charges.append(charge)
elif spec.pricing_spec_mode == 'spec_subtype':
sub_charges = await pricing_program_chargeing(self.sor,
charge.subppid, d)
charges += sub_charges
return charges