diff --git a/discount/.init.py.swp b/discount/.init.py.swp new file mode 100644 index 0000000..b5465ae Binary files /dev/null and b/discount/.init.py.swp differ diff --git a/discount/init.py b/discount/init.py new file mode 100644 index 0000000..06d6370 --- /dev/null +++ b/discount/init.py @@ -0,0 +1,137 @@ +from appPublic.qr import gen_qr +from appPublic.uniqueID import getID +from sqlor.dbpools import get_sor_context +from ahserver.serverenv import ServerEnv +from ahserver.filestorage import FileStorage + +async def discount_qrcode(request, params_kw): + """ + discount less then 1 and greate then 0 + valid_term is digit + one of ["D", "M", "Y"] + expired_date is a date after it the promote qrcode invalidable + """ + discount = params_kw.discount + valid_term = params_kw.valid_term + expired_date = params_kw.expired_date + env = request._run_ns + resellerid = await env.get_userorgid() + id = getID() + url = env.entire_url('./promote') + f'?id={id}' + fs = FileStorage() + p = fs._name2path(f'{getID()}.png') + gen_qr(url, p) + webp = fs.webpath(p) + async with get_sor_context(env, 'discount') as sor: + biz_date = await env.get_business_date(sor) + if biz_date <= expired_date: + raise Exception('Promote QRCODE is out of time') + + ret = { + 'id': id, + 'resellerid': resellerid, + 'discount': discount, + 'valid_term': valid_term, + 'expired_date': expired_date, + 'qr_webpath': webp + } + await sor.C('discount_qr', Cret.copy()) + return ret + return None +async def set_promote_discount(request, params_kw): + env = request._run_ns + id = params_kw.id + customerid = await env.get_userorgid() + async with get_sor_context(env, 'discount') as sor: + recs = await sor.R('discount_qr', {'id': id}) + if not recs: + raise Exception(f'promote id({id}) not exists') + biz_date = await env.get_business_date(sor) + if recs[0].expired_date <= biz_date: + raise Exception('Promote QRCODE is out of time') + cnt = int(recs[0].valid_term[:-1]) + unit = recs[0].valid_term[-1] + enabled_date = biz_date + expired_date = '' + if unit == 'D': + expired_date = env.strdate_add(enabled_date, days=cnt) + elif unit == 'M': + expired_date = env.strdate_add(enabled_date, months=cnt) + elif unit == 'Y': + expired_date = env.strdate_add(enabled_date, years=cnt) + else: + raise Exception(f'Invalid valid_term({recs[0].valid_term})') + need_new_discount = await disable_old_discount(sor, recs[0].resellerid, + customerid, biz_date, recs[0].discount) + if not need_new_discount: + return + await sor.C('discount', { + 'id': getID(), + 'resellerid': recs[0].resellerid, + 'customerid': customerid, + 'discount': recs[0].discount, + 'enabled_date': enabled_date, + 'expired_date': expired_date + } + +async def disable_old_discount(sor, resellerid, customerid, biz_date, new_discount): + sql = """select * from discount +where resellerid = ${resellerid}$ + and customerid=${customerid}$ + and enabled_date <= ${biz_date}$ + and expired_date > ${biz_date}$ for update""" + recs = await sor.sqlExe(sql, {'resellerid': resellerid, 'customerid': customerid, 'biz_date': biz_date}) + if not recs: + return True + if new_discount > news[0].discount: + return False + await sor.U('discount', {'id': recs[0].id, 'expired_date': biz_date}) + return True + +async def sor_get_star_discount(sor, resellerid, biz_date): + env = ServerEnv() + sql = """select * from discount +where resellerid = ${resellerid}$ + and enabled_date <= ${biz_date}$ + and expired_date > ${biz_date}$""" + ns = { + "resellerid": resellerid, + "biz_date": biz_date + } + recs = await sqlExe(sql, ns) + if not recs: + return 1 + + return recs[0].discount + + +async def sor_get_customer_discount(sor, resellerid, customerid): + env = ServerEnv() + biz_date = await env.get_business_date(sor) + sql = """select * from discount +where resellerid = ${resellerid}$ + and customerid = ${customerid}$ + and enabled_date <= ${biz_date}$ + and expired_date > ${biz_date}$""" + ns = { + "resellerid": resellerid, + "customerid": customerid, + "biz_date": biz_date + } + recs = await sqlExe(sql, ns) + if not recs: + return await sor_get_star_discount(sor, resellerid, biz_date) + + return recs[0].discount + +async def get_customer_discount(resellerid, customerid): + env = ServerEnv() + async with get_sor_context(env, 'discount') as sor: + return sor_get_customer_discount(sor, resellerid, customerid) + return 1 + +def load_discount(): + env = ServerEnv() + env.get_customer_discount = get_customer_discount + env.sor_get_customer_discount = sor_get_customer_discount + env.discount_qrcode = discount_qrcode + env.set_promote_discount = set_promote_discount diff --git a/models/discount.xlsx b/models/discount.xlsx new file mode 100644 index 0000000..38aaca9 Binary files /dev/null and b/models/discount.xlsx differ diff --git a/models/discount_qr.xlsx b/models/discount_qr.xlsx new file mode 100644 index 0000000..f21104c Binary files /dev/null and b/models/discount_qr.xlsx differ diff --git a/wwwroot/generate_qr.dspy b/wwwroot/generate_qr.dspy new file mode 100644 index 0000000..5bc6ee9 --- /dev/null +++ b/wwwroot/generate_qr.dspy @@ -0,0 +1,58 @@ +params_kw.discount = float(params_kw.discount) +if params_kw.discount <= 0 or params_kw.discount >= 1: + e = Exception(f'discount({params_kw.discount}) invalid') + exception(f'{e}') + raise e + +if params_kw.valid_term[-1] not in ['D', 'M', 'Y']: + e = Exception(f'valid_term must ends with "D", "M" or "Y"') + exception(f'{e}') + raise e +cnt = int(params_kw.valid_term[:-1]) +if cnt < 0: + e = Exception(f'valid_term({params_kw.valid_term}) invalid') + exception(f'{e}') + raise e + +if not params_kw.expired_date: + params_kw.expired_date = '9999-12-31' +x = await discount_qrcode(request, params_kw) +return { + "widgettype": "VBox", + "options": { + "width": "100%", + "height": "100%" + }, + "subwidgets": [ + { + "widgettype": "Image", + "options": { + "width": "auto", + "height": "auto", + "url": entire_url('/idfile') + f'?path={x.qr_webpath}' + } + }, { + "widgettype": "HBox", + "options": { + "width": "100%", + "cheight": 2 + }, + "subwidgets": [ + { + "widgettype": "Text", + "options": { + "otext": "折扣:", + "i18n": True, + "cwidth": 3 + } + },{ + "widgettype": "Text", + "options":{ + "text": x.discount + } + } + ] + } + ] +} + diff --git a/wwwroot/promote.ui b/wwwroot/promote.ui new file mode 100644 index 0000000..6d91df8 --- /dev/null +++ b/wwwroot/promote.ui @@ -0,0 +1,37 @@ +{ + "widgettype": "Form", + "options": { + "width": "100%", + "height": "100%", + "fields": [ + { + "name": "valid_term", + "label": "有效期", + "uitype": "str", + "tip":"格式:xY, xM, xD,x是1到多位数字,Y(年),M(月),D(日)" + },{ + "name": "expired_date", + "label": "促销失效日期", + "uitype": "date", + "tip": "促销二维码需在此日期前使用" + },{ + "name": "discount", + "lable": "折扣", + "uitype": "float", + "tip": "折扣>0, < 1, 最终价格=产品价格*折扣, 折扣越小,折扣力度越大" + } + ] + }, + "binds":[ + { + "wid": "self", + "event": "submit", + "actiontype": "urlwidget", + "target": "self", + "options": { + "url": "{{entire_url('generate_qr.dspy')}}", + "params": {} + } + } + ] +} diff --git a/wwwroot/promote/index.dspy b/wwwroot/promote/index.dspy new file mode 100644 index 0000000..583deae --- /dev/null +++ b/wwwroot/promote/index.dspy @@ -0,0 +1,5 @@ +orgid = await get_userorgid() +if orgid is None: + return UiError(title='Error', message='You need login') + +ret = await set_promote_discount(request, params_kw)