From 7d80025171183cacf1e080ee78940caa5d14a0b5 Mon Sep 17 00:00:00 2001 From: ping <1017253325@qq.com> Date: Thu, 14 Aug 2025 17:15:44 +0800 Subject: [PATCH] update --- b/baiduc/baidu_confirm_auto_renew_order.dspy | 753 ++++++++++++++++++ b/kpi/bb.dspy | 17 +- b/product/add_user_inquiry.dspy | 12 + b/product/get_firstpage_net_detail.dspy | 498 +++++++++++- b/product/global_search.dspy | 80 ++ b/product/homepage_category_tree_add.dspy | 49 ++ b/product/homepage_category_tree_search.dspy | 35 + b/product/homepage_category_tree_update.dspy | 43 + b/product/publish_product_add.dspy | 6 +- b/product/publish_product_search.dspy | 122 ++- b/product/publish_product_search_detail.dspy | 67 ++ .../publish_product_search_first_page.dspy | 6 +- b/product/publish_product_to_excel.dspy | 120 +++ b/product/publish_product_update.dspy | 123 +++ b/product/search_user_inquiry.dspy | 11 +- b/user/enterprise_audit_info_add.dspy | 45 ++ b/user/enterprise_audit_info_search.dspy | 78 ++ b/user/enterprise_audit_info_update.dspy | 70 ++ 18 files changed, 2103 insertions(+), 32 deletions(-) create mode 100644 b/baiduc/baidu_confirm_auto_renew_order.dspy create mode 100644 b/product/global_search.dspy create mode 100644 b/product/homepage_category_tree_add.dspy create mode 100644 b/product/homepage_category_tree_search.dspy create mode 100644 b/product/homepage_category_tree_update.dspy create mode 100644 b/product/publish_product_search_detail.dspy create mode 100644 b/product/publish_product_to_excel.dspy create mode 100644 b/product/publish_product_update.dspy create mode 100644 b/user/enterprise_audit_info_add.dspy create mode 100644 b/user/enterprise_audit_info_search.dspy create mode 100644 b/user/enterprise_audit_info_update.dspy diff --git a/b/baiduc/baidu_confirm_auto_renew_order.dspy b/b/baiduc/baidu_confirm_auto_renew_order.dspy new file mode 100644 index 0000000..dfac1a8 --- /dev/null +++ b/b/baiduc/baidu_confirm_auto_renew_order.dspy @@ -0,0 +1,753 @@ +async def user_action_record(ns={}): + ns_dic = { + 'id': uuid(), + 'source': '百度智能云', + 'orderid': ns.get('orderid'), + 'ordertype': ns.get('ordertype'), + 'userid': ns.get('userid'), + 'reason': ns.get('reason') + } + db = DBPools() + async with db.sqlorContext('kboss') as sor: + await sor.C('user_action', ns_dic) + +async def time_convert(resoucetime=None): + if not resoucetime: + return + utc_time = datetime.datetime.strptime(resoucetime, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc) + beijing_time = utc_time.astimezone(datetime.timezone(datetime.timedelta(hours=8))) + return beijing_time.strftime("%Y-%m-%d %H:%M:%S") + +async def cal_expire_time(history_time=None, chargeduration=None, unit=None): + chargeduration = int(chargeduration) + # 当前时间 + # now = datetime.datetime.now() + now = datetime.datetime.strptime(history_time, '%Y-%m-%d %H:%M:%S') + if unit == 'MONTH': + expire_time = now + dateutil.relativedelta.relativedelta(months=chargeduration) + elif unit == 'YEAR': + expire_time = now + dateutil.relativedelta.relativedelta(years=chargeduration) + else: + expire_time = None + if expire_time: + return str(expire_time) + else: + return None + +async def affirmbz_order(ns={}): + """确认支付""" + order_type = ns.get('order_type') + sor = ns['sor'] + orgid = await sor.R('bz_order', {'id': ns['orderid']}) + + servicename = orgid[0]['servicename'] + product_url = None + # if ('BCC' in servicename) or ('GPU' in servicename): + # product_url = 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list' + + date = await get_business_date(sor=None) + # await sor.U('bz_order',{'id':ns['orderid'],'order_date': date}) + count = await getCustomerBalance(sor, orgid[0]['customerid']) + if count == None: + count = 0 + if count - float(orgid[0]['amount']) < 0: + pricedifference = count - round(orgid[0]['amount'],2) + return {'status': False, 'msg': '账户余额不足','pricedifference': round(pricedifference,2)} + await order2bill(ns['orderid'], sor) + bills = await sor.R('bill', {'orderid': ns['orderid'], 'del_flg': '0'}) + try: + # 需要加事务 + for i in bills: + ba = BillAccounting(i) + r = await ba.accounting(sor) + dates = datetime.datetime.now() + await sor.U('bz_order', {'id': ns['orderid'], 'order_status': '1','create_at':dates}) + await sor.U('bill', {'id': ns['orderid'], 'bill_state': '1'}) + order_goods = await sor.R('order_goods', {'orderid': ns['orderid']}) + for j in order_goods: + # 处理退订逻辑 + if order_type == 'REFUND': + # 找到资源并更新时间 + resource_find_sql = """select id from customer_goods where resourceid = '%s';""" % j['resourceids'] + resource_find_li = await sor.sqlExe(resource_find_sql, {}) + resource_find_id = resource_find_li[0]['id'] + await sor.U('customer_goods', {'id': resource_find_id, 'del_flg': '1'}) + + # 处理续费逻辑 + elif order_type == 'RENEW': + # 找到资源并更新时间 + resource_find_sql = """select id from customer_goods where FIND_IN_SET('%s', resourceid) and del_flg = '0';""" % j['resourceids'] + resource_find_li = await sor.sqlExe(resource_find_sql, {}) + resource_find_id = resource_find_li[0]['id'] + await sor.U('customer_goods', {'id': resource_find_id, 'start_date': j['resourcestarttime'], 'expire_date': j['resourceendtime']}) + + # 处理购买逻辑 + else: + product = await sor.R('product', {'id': j['productid']}) + nss = {} + nss['id'] = uuid() + # nss['id'] = UUID() + nss['providerrid'] = product[0]['providerid'] + nss['productname'] = product[0]['name'] + nss['productdesc'] = product[0]['description'] + nss['customerid'] = orgid[0]['customerid'] + nss['productid'] = product[0]['id'] + nss['specdataid'] = j['spec_id'] + nss['orderid'] = orgid[0]['id'] + nss['start_date'] = j['resourcestarttime'] + nss['expire_date'] = j['resourceendtime'] + nss['resourceid'] = j['resourceids'] + nss['orderkey'] = j['orderkey'] + + if product_url: + nss['product_url'] = product_url + else: + spec = json.loads(product[0]['spec_note']) if isinstance(product[0]['spec_note'], str) else product[0]['spec_note'] + spec_list_url = [item['value'] for item in spec if item['configName'] == 'listUrl'] + nss['product_url'] = spec_list_url[0] if spec_list_url else 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list' + + await sor.C('customer_goods', nss) + return {'status': True, 'msg': '支付成功'} + except Exception as error: + return {'status': False, 'msg': str(error)} + +async def baidu_new_update_resouce(ns={}): + + # 增加延迟 + import asyncio + await asyncio.sleep(12) + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'}) + user = await sor.R('users', {'id': ns.get('userid')}) + orgid = await sor.R('organization', {'id': user[0]['orgid']}) + nss = {'uuids': [ns.get('order_id')], 'queryAccountId': baidu_users[0]['baidu_id']} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/getByUuid?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com", + "ContentType": "application/json;charset=UTF-8" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=nss) as res: + data_ = await res.json() + with open('baidu_new_order_after_confirm.txt', 'a+') as f: + f.write(json.dumps(data_) + '\n') + orders = data_['orders'] + + for item in orders: + order_items = item['orderItems'] + for order_info in order_items: + resourceids = ','.join(order_info['shortIds']) if order_info.get('shortIds') else '' + if not resourceids: + continue + resourcestarttime = await time_convert(order_info.get('resourceStartTime')) if order_info.get( + 'resourceStartTime') else None + resourceendtime = await time_convert(order_info.get('resourceEndTime')) if order_info.get( + 'resourceEndTime') else None + + order_key = order_info['key'] + update_order_goods_sql = """ UPDATE order_goods og + JOIN bz_order o ON og.orderid = o.id + SET + og.resourceids = '%s', + og.resourcestarttime = '%s', + og.resourceendtime = '%s' + WHERE + og.orderkey = '%s' + AND o.provider_orderid = '%s'; """ \ + % (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id')) + await sor.sqlExe(update_order_goods_sql, {}) + update_customer_goods_sql = """ UPDATE customer_goods og + JOIN bz_order o ON og.orderid = o.id + SET + og.resourceid = '%s', + og.start_date = '%s', + og.expire_date = '%s' + WHERE + og.orderkey = '%s' + AND o.provider_orderid = '%s'; """ \ + % (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id')) + await sor.sqlExe(update_customer_goods_sql, {}) + +async def baidu_order_cancel(ns={}): + baidu_id = ns['baidu_id'] + order_id = ns['order_id'] + paydata = {'queryAccountId': baidu_id, 'orderIds': [order_id]} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=paydata) as res: + await res.json() + return { + 'status': True, + 'msg': 'order cancel success' + } + +async def get_baidu_orderlist(ns={}): + """ + 百度支付 + 1、获取订单 + 2、算出购买的产品折扣 + 3、比对账号余额 + """ + # 增加延迟 + import asyncio + await asyncio.sleep(2) + db = DBPools() + async with db.sqlorContext('kboss') as sor: + baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'}) + user = await sor.R('users', {'id': ns.get('userid')}) + orgid = await sor.R('organization', {'id': user[0]['orgid']}) + nss = {'uuids': [ns.get('order_id')], 'queryAccountId': baidu_users[0]['baidu_id']} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/getByUuid?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com", + "ContentType": "application/json;charset=UTF-8" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=nss) as res: + data_ = await res.json() + with open('baidu_new_order.txt', 'a+') as f: + f.write(json.dumps(data_) + '\n') + orders = data_['orders'] + serviceType = orders[0]['orderItems'] + + # 可能获取得到的是延迟订单 + if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED': + return { + 'status': False, + 'msg': 'delay_order' + } + + # 避免重复退订 + if orders[0]['type'] == 'REFUND' and orders[0]['status'] == 'CREATED': + order_history = await sor.R('bz_order', {'provider_orderid': ns.get('order_id'), 'business_op': 'BUY_REVERSE', 'order_status': '1'}) + if order_history: + print('此订单之前已经退费成功') + return { + 'status': True, + 'msg': '此订单之前已经退费成功' + } + + # 如果是退款 更新数据库状态 + if orders[0]['type'] == 'REFUND': + updatetime = await time_convert(orders[0]['updateTime']) if orders[0].get('updateTime') else None + update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \ + (float(orders[0]['price']), orders[0]['status'], updatetime, ns.get('order_id')) + await sor.sqlExe(update_refund_sql, {}) + + productType = 'prepay' + # 判断订单item中productType是否有后付费的产品 + for item in orders: + order_items = item['orderItems'] + for order_info in order_items: + postpay_price = order_info['itemFee']['price'] if order_info.get('itemFee') else order_info['catalogPrice'] + if not postpay_price: + # cpt1Price: 固定配置,按分钟计费 + postpay_price = order_info['pricingDetail'].get('cpt1Price') if order_info.get('pricingDetail') else 0 + + # 确定是否是后付费订单 + if order_info['productType'] == 'postpay' and postpay_price != 0: + productType = 'postpay' + # 获取余额 + user_balance = await getCustomerBalance(sor, orgid[0]['id']) + # 判断余额是否大于50 + if user_balance < 50: + await sor.rollback() + paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=paydata) as res: + await res.json() + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '后付费 该账号余额不足50,无法完成购买' + } + await user_action_record(ns_record) + return { + 'status': False, + 'msg': '您的余额小于该产品的起购金额50元, 目前无法购买立即充值' + } + # 实付价格 + total_price = 0 + # productType = '' + + # 买/续/退 字段映射 + order_type = orders[0]['type'] + if order_type == 'NEW': + business_op = 'BUY' + elif order_type == 'RENEW': + business_op = 'RENEW' + elif order_type == 'REFUND': + business_op = 'BUY_REVERSE' + else: + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '支付形式目前仅包含购买,续费,退订' + } + await user_action_record(ns_record) + return { + 'status': False, + 'msg': '线上暂不支持, 请联系售后' + } + try: + # 生成本地订单 + bz_ns = {} + bz_ns['id'] = uuid() + bz_ns['order_status'] = '0' + bz_ns['business_op'] = business_op + bz_ns['userid'] = ns.get('userid') + bz_ns['customerid'] = orgid[0]['id'] + bz_ns['order_date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + bz_ns['thirdparty_order'] = ns.get('order_id') + bz_ns['source'] = '百度智能云' + # bz_ns['originalprice'] = orders[0]['price'] + bz_ns['originalprice'] = sum(i['catalogPrice'] for i in serviceType) + bz_ns['provider_orderid'] = ns.get('order_id') + bz_ns['ordertype'] = orders[0]['productType'] + bz_ns['servicename'] = orders[0]['serviceType'] + bz_ns['autoreneworder'] = '1' if orders[0]['autoRenewOrder'] else '0' + if ns.get('specdataid'): + bz_ns['specdataid'] = ns['specdataid'] + await sor.C('bz_order', bz_ns) + for i in serviceType: + # if i['productType'] == 'prepay': + # # 预付费 + # productType = 'prepay' + # financePrice = 0 + # 获取产品id + product = await sor.R('product', {'providerpid': 'baidu_' + i['serviceType'], 'del_flg': '0'}) + if not product: + return { + 'status': False, + 'msg': '未配置该产品, 请联系售后处理' + } + # 获取协议 + saleprotocol_to_person = await sor.R('saleprotocol', + {'bid_orgid': orgid[0]['id'], 'offer_orgid': orgid[0]['parentid'], + 'del_flg': '0'}) + # 等于空就代表这个客户没有特殊折扣,就要找到买方为*的协议 + saleprotocol_to_all = await sor.R('saleprotocol', {'bid_orgid': '*', 'offer_orgid': orgid[0]['parentid'], + 'del_flg': '0', 'salemode': '0'}) + + if saleprotocol_to_person: + product_salemode = await sor.R('product_salemode', + {'protocolid': saleprotocol_to_person[0]['id'], + 'productid': product[0]['id'], + 'del_flg': '0'}) + if not product_salemode: + product_salemode = await sor.R('product_salemode', + {'protocolid': saleprotocol_to_all[0]['id'], + 'productid': product[0]['id'], + 'del_flg': '0'}) + else: + product_salemode = await sor.R('product_salemode', + {'protocolid': saleprotocol_to_all[0]['id'], + 'productid': product[0]['id'], + 'del_flg': '0'}) + if not product_salemode: + return { + 'status': False, + 'msg': '还未上线这个产品的协议配置' + } + supply_price = i['itemFee']['price'] if i.get('itemFee') else i['catalogPrice'] + financePrice = abs(supply_price * product_salemode[0]['discount']) + total_price += financePrice + + # 添加订单子表 + nss = {} + nss['id'] = uuid() + nss['orderid'] = bz_ns['id'] + nss['productid'] = product[0]['id'] + nss['providerid'] = product[0]['providerid'] + if i['count'] > 1: + nss['list_price'] = abs(i['realCatalogPrice'] / i['count']) + else: + nss['list_price'] = abs(i['realCatalogPrice']) + nss['discount'] = product_salemode[0]['discount'] + nss['quantity'] = i['count'] + nss['price'] = abs(round(nss['list_price'] * product_salemode[0]['discount'], 2)) + # 计算总价 + # nss['amount'] = round(total_price, 2) + nss['amount'] = abs(round(nss['price'] * nss['quantity'], 2)) + nss['chargemode'] = i.get('productType') + nss['servicename'] = i.get('serviceType') + nss['chargeduration'] = i.get('time') + nss['unit'] = i.get('timeUnit') + nss['resourceids'] = ','.join(i['shortIds']) if i.get('shortIds') else '' + nss['orderkey'] = i.get('key') + + # 如果是续费订单 由于没有返回日期, 重新计算日期 + if order_type == 'RENEW': + history_time_sql = "select resourcestarttime, resourceendtime from order_goods where FIND_IN_SET('%s', resourceids) order by resourceendtime desc;" % \ + nss['resourceids'] + history_time = await sor.sqlExe(history_time_sql, {}) + new_end_time = await cal_expire_time(history_time=history_time[0]['resourceendtime'], + chargeduration=nss['chargeduration'], unit=nss['unit']) + # 开始日期不变 更新到期日期 + nss['resourcestarttime'] = history_time[0]['resourcestarttime'] + nss['resourceendtime'] = new_end_time + else: + if i.get('resourceStartTime'): + nss['resourcestarttime'] = await time_convert(i.get('resourceStartTime')) + else: + nss['resourcestarttime'] = await time_convert(orders[0]['updateTime']) + + if i.get('resourceEndTime'): + nss['resourceendtime'] = await time_convert(i.get('resourceEndTime')) + + # 后付费没有资源结束时间 + if i.get('productType') == 'prepay': + end_time = await time_convert(orders[0]['updateTime']) + nss['resourceendtime'] = await cal_expire_time(history_time=end_time, + chargeduration=nss['chargeduration'], + unit=nss['unit']) + else: + nss['resourceendtime'] = None + + await sor.C('order_goods', nss) + + # 循环后更新订单中总价 + await sor.U('bz_order', {'id': bz_ns['id'], 'amount': round(total_price, 2)}) + except Exception as e: + await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')}) + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '发生错误, %s' % str(e)[:100] + } + await user_action_record(ns_record) + import traceback + with open('baiducloud_err.txt', 'w') as f: + f.write(str(e)+ traceback.format_exc()) + traceback.print_exc() + await sor.rollback() + return { + 'status': False, + 'msg': '产品错误, 请联系售后' + } + + # 判断用户账户余额是否足够支付 + try: + count = await getCustomerBalance(sor, orgid[0]['id']) + if order_type == 'REFUND': + count = total_price + 0.1 + + if round(total_price,2) <= count: + #判断预付费或者后付费 + if productType == 'prepay' or productType == 'postpay': + # 调用扣费接口 + affirmbz_order_ns = { + 'sor': sor, + 'orderid': bz_ns['id'], + 'order_type': order_type + } + affirmbz_order_res = await affirmbz_order(affirmbz_order_ns) + if not affirmbz_order_res['status']: + # if True: + await sor.rollback() + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '支付错误, 请联系售后, %s' % affirmbz_order_res.get('msg') + } + await user_action_record(ns_record) + return { + 'status': False, + 'msg': '支付错误, 请联系售后' + } + + # 预配置local_refund用于本地操作 + if order_type == 'REFUND' and not ns.get('local_refund'): + return { + 'status': True, + 'msg': '本地退费成功' + } + else: + # 调用支付订单接口 + paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderId':ns.get('order_id')} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=paydata) as res: + data_ = await res.json() + if data_ == {'success': True}: + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '购买成功' + } + await user_action_record(ns_record) + ns_cron_job = { + 'id': uuid(), + 'source': 'baidu', + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': 'buy success' + } + await sor.C('baidu_cron_job', ns_cron_job) + # return { + # 'status': True, + # 'orderid': bz_ns['id'] + # } + else: + await sor.rollback() + await baidu_order_cancel( + {'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')}) + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '支付成功后, order_pay接口错误, 回滚, %s' % str(data_)[:400] + } + await user_action_record(ns_record) + return { + 'status': False, + 'msg': '产品分配排队中, 请联系售后详询' + } + else: + # 取消订单 + await sor.rollback() + paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=paydata) as res: + await res.json() + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '无法购买后付费产品' + } + await user_action_record(ns_record) + return {'status': False, 'msg': '无法购买后付费产品'} + else: + #取消订单 + await sor.rollback() + paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderIds':[ns.get('order_id')]} + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format + method = 'POST' + header = { + "Host": "billing.baidubce.com" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=paydata) as res: + await res.json() + ns_record = { + 'orderid': ns.get('order_id'), + 'ordertype': orders[0]['type'], + 'userid': ns.get('userid'), + 'reason': '该账号余额不足,无法完成购买' + } + await user_action_record(ns_record) + return {'status': False,'msg': '该账号余额不足,无法完成购买'} + except Exception as e: + await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')}) + import traceback + with open('baiducloud_err.txt', 'w') as f: + f.write(str(e)+ traceback.format_exc()) + traceback.print_exc() + await sor.rollback() + return { + 'status': False, + 'msg': '产品错误, 请联系售后' + } + # 更新资源时间 资源id + # if order_type == 'NEW': + # await baidu_new_update_resouce(ns) + return { + 'status': True, + 'orderid': bz_ns['id'], + 'originalprice': bz_ns.get('originalprice'), + 'servicename': bz_ns.get('servicename'), + 'amount': total_price + } + +async def get_order_list_base_page(baidu_id, pageNo=1, pageSize=500): + ns = {'queryAccountId': baidu_id, 'pageNo': pageNo, 'pageSize': pageSize} + method = 'POST' + ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()]) + url = 'https://billing.baidubce.com/v1/order/list?%s' % ns_format + header = { + "Host": "billing.baidubce.com", + "ContentType": "application/json;charset=UTF-8" + } + header = await get_auth_header(method=method, url=url, header=header) + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=ns) as res: + data_orders = await res.json() + return data_orders + + +async def update_baidu_order_list(ns={}): + """ + ns = {'queryAccountId': '139fc7a23b314596ad78b6bb8e7c1503', 'orderType': 'REFUND'} + :return: + """ + db = DBPools() + async with db.sqlorContext('kboss') as sor: + username = None + # 更新机构下全部用户订单信息 + if ns.get('orgid'): + users_find_sql = """SELECT DISTINCT b.baidu_id FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0';""" % ns.get('orgid') + users = await sor.sqlExe(users_find_sql, {}) + + # 更新个人订单信息 + elif ns.get('userid'): + users = await sor.R('baidu_users', {'user_id': ns['userid']}) + username_li = await sor.R('users', {'id': ns['userid']}) + username = username_li[0]['username'] if username_li else None + else: + users = [] + + update_count = 0 + add_count = 0 + for baidu_id in users: + data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=1, pageSize=1000) + page_num_count = int(data_orders['totalCount'] / data_orders['pageSize']) + 1 + for page_num in range(1, page_num_count + 1): + data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=page_num, pageSize=1000) + orders = data_orders['orders'] + for item in orders: + updatetime = await time_convert(item.get('updateTime')) if item.get('updateTime') else None + ns_dic = { + "id": uuid(), + "orderid": item.get("uuid"), + "ordertype": item.get("type"), + "accountid": item.get("accountId"), + "servicetype": item.get("serviceType"), + "producttype": item.get("productType"), + "shortids": ','.join(item['shortIds']) if item.get('shortIds') else '', + "price": item.get("price"), + "status": item.get("status"), + "autoreneworder": '1' if item.get("autoRenewOrder") else '0', + "createtime": await time_convert(item.get('createTime')) if item.get( + 'createTime') else None, + "updatetime": updatetime + } + ns_exist_order = { + 'orderid': item.get("uuid") + } + exist_order = await sor.R('baidu_orders', ns_exist_order) + if exist_order and exist_order[0]['updatetime'] != updatetime: + update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \ + (item.get("price"), item.get("status"), updatetime, + item.get("uuid")) + await sor.sqlExe(update_refund_sql, {}) + update_count += 1 + + if not exist_order: + await sor.C('baidu_orders', ns_dic) + add_count += 1 + + return { + 'status': True, + 'msg': '同步数据成功, 新增 %s 条, 更新 %s 条' % (add_count, update_count), + 'data': { + 'username': username + } + } + +async def baidu_confirm_auto_renew_order(ns={}): + if ns.get('domain_name'): + orgid_li = await sor.R('reseller', {'domain_name': ns.get('domain_name'), 'del_flg': '0'}) + orgid = orgid_li[0]['orgid'] + else: + orgid = 'mIWUHBeeDM8mwAFPIQ8pS' + + # 读取baidu_orders表格 确定状态是renew的订单ID + renew_results = [] + db = DBPools() + async with db.sqlorContext('kboss') as sor: + renew_sql = """"SELECT bo.*, bs.user_id FROM baidu_orders AS bo LEFT JOIN baidu_users AS bs ON bo.accountid = bs.baidu_id WHERE bo.ordertype = 'RENEW' AND bo.status = 'NEED_CONFIRM' AND bo.del_flg = '0';""" + renew_results = await sor.sqlExe(renew_sql, {}) + + renew_status_count = 0 + # 执行 get_baidu_orderlist sor分开运行 + for renew_res in renew_results: + order_id = renew_res.get('orderid') + user_id = renew_res.get('user_id') + + renew_status = await get_baidu_orderlist({'order_id': order_id, 'userid': user_id}) + if renew_status.get('status'): + renew_status_count += 1 + + + # 并触发update函数 + update_msg = await update_baidu_order_list({'orgid': orgid}) + + return { + 'status': True, + 'msg': '续费订单执行结束, 触发了%s条数据' % len(renew_results), + 'data': { + 'renew_status_count': renew_status_count, + 'update_msg': update_msg, + } + + } + +ret = await baidu_confirm_auto_renew_order(params_kw) +return ret \ No newline at end of file diff --git a/b/kpi/bb.dspy b/b/kpi/bb.dspy index d232b31..af5b549 100644 --- a/b/kpi/bb.dspy +++ b/b/kpi/bb.dspy @@ -19,7 +19,7 @@ async def bb(ns={}): # raise ValueError("供应商没有配置产品") # 获取当前日期 - current_date = datetime.datetime.now() + # current_date = datetime.datetime.now() # 计算两个月后的日期 # future_date = current_date + dateutil.relativedelta.relativedelta(months=6) @@ -31,9 +31,18 @@ async def bb(ns={}): # } # users_id = await get_user() # await asyncio.sleep(10) - import os - current_path = os.getcwd() - return {'current_date': current_path} + # import os + # current_path = os.getcwd() + # return {'current_date': current_path} + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + await sor.U('white_list', {'id': ns.get('id'), 'user_id': ns.get('user_id')}) + return { + 'status': True, + 'msg': 'Data inserted successfully', + 'data': '' + } ret = await bb(params_kw) return ret \ No newline at end of file diff --git a/b/product/add_user_inquiry.dspy b/b/product/add_user_inquiry.dspy index 0b5bf4c..88e0670 100644 --- a/b/product/add_user_inquiry.dspy +++ b/b/product/add_user_inquiry.dspy @@ -1,8 +1,20 @@ async def add_user_inquiry(ns={}): + if not ns.get('url_link'): + return { + 'status': False, + 'msg': '请传递url_link' + } + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + db = DBPools() async with db.sqlorContext('kboss') as sor: ns_c = { 'id': uuid(), + 'domain_name': domain_name, + 'publish_type': ns.get('publish_type'), + 'relate_id': ns.get('relate_id'), 'content': ns.get('content'), 'custom_type': ns.get('custom_type'), 'name': ns.get('name'), diff --git a/b/product/get_firstpage_net_detail.dspy b/b/product/get_firstpage_net_detail.dspy index d92532c..77987ca 100644 --- a/b/product/get_firstpage_net_detail.dspy +++ b/b/product/get_firstpage_net_detail.dspy @@ -151,7 +151,8 @@ detailDataDCI = { }, ] } - ] + ], + "products": [] } detailDataHL = { @@ -316,7 +317,8 @@ detailDataHL = { } ] } - ] + ], + "products": [] } detailDataS = { @@ -471,7 +473,8 @@ detailDataS = { } ] } - ] + ], + "products": [] } detailDataAI = { @@ -609,7 +612,8 @@ detailDataAI = { } ] } - ] + ], + "products": [] } detailDataYITI = { @@ -766,7 +770,8 @@ detailDataYITI = { }, ] }, - ] + ], + "products": [] } detailDataLJS = { @@ -868,7 +873,479 @@ detailDataLJS = { "content": "2.GPU 加速 AI 推理,裸金属低延迟保障实时分析(如监控画面秒级报警);资源独占确保视频数据安全,符合安防 / 工业合规。" }] } - ] + ], + "products": [ + { + "title": "NVIDIA-4090", + "description": "配备GPU的云端服务器,可以为机器学习、高性能计算、图形图像渲染等计算密集型应用提供加速处理能力。根据需求场景的不同,既可提供弹性的GPU云服务器,也可提供高性能的GPU裸金属服务器,助力您的业务创新,提升竞争优势。", + "price": "6000", + "pre_price": "7143", + "price_unit": "台/月", + "discount": 8.4, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/1.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "AMD EPYC 7542 32 C * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G DDR4-3200 * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "NVIDIA-4090-24GB * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "960G SATA SSD * 2 (Raid)", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "3.84T U.2 NVMe SSD * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "Mellanox Connect4 25G SFP28 2-port * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-4090", + "description": "轻量应用服务器(Light server)是一种内置应用型镜像或系统型镜像的小规格云服务器, 绑定适配大小的磁盘和带宽,为中小型企业和个人用户提供官网搭建、web应用搭建、云上学习和测试等场景的服务。", + "price": "6000", + "pre_price": "7143", + "price_unit": "台/月", + "discount": 8.4, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/2.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "AMD EPYC 7542 32 C * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G DDR4-3200 * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "NVIDIA-4090-24GB * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "960G SATA SSD * 2 (Raid)", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "3.84T U.2 NVMe SSD * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "Mellanox Connect4 25G SFP28 2-port * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-A100", + "description": "对象存储BOS(Baidu Object Storage)是一款稳定、安全、高效、高可拓展的云存储服务,支持标准、低频、冷和归档存储等多种存储类型满足多场景的存储需求。用户可以将任意数量和形式的非结构化数据存入BOS,并对数据进行管理和处理。", + "price": "31000", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/3.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "AMD EPYC 7543 32 C * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G DDR4-3200 * 32", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "NVIDIA-A100-80GB-Nvlink * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "960G SATA SSD * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "3.84T U.2 NVMe SSD * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "MCX653105A - HDAT CX6 200G 1P HDR * 4", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-A800", + "description": "云数据库 RDS为用户提供高性价比、安全可靠、性能卓越、易于维护的企业级云数据库服务。", + "price": "32000", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "Intel (R) Xeon (R) Platinum 8358 32 C * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G DDR4-3200 * 32", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "NVIDIA-A800-80GB-Nvlink * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "960G SATA SSD * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "3.84T U.2 NVMe SSD * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "MCX653105A - HDAT CX6 200G 1P HDR *4", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "昇腾-910B", + "description": "裸金属服务器是一种融合了高性能 GPU 计算能力、裸金属服务器物理资源独占性及云计算弹性扩展特性的新型服务器形态。它既具备传统裸金属服务器的强劲性能与安全性,又能像云服务器一样按需灵活调整资源,适用于对算力、资源独占性和弹性要求极高的场景。", + "price": "22000", + "pre_price": "27500", + "price_unit": "台/月", + "discount": 8, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/5.png", + "list": [ + { + "id": 23, + "name": "CPU", + "content": "鲲鹏920 * 4", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 24, + "name": "内存", + "content": "32G DDR4-3200 * 32", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 25, + "name": "GPU", + "content": "昇腾-910B-64GB * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 26, + "name": "系统盘", + "content": "480G SATA SSD * 2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 27, + "name": "数据盘", + "content": "3.84T U.2 NVMe SSD * 1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 28, + "name": "网卡", + "content": "200G QSFP ROCE * 8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-4090", + "description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.", + "price": "9000", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "Intel Xeon Gold 6430*2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G-DDR5 ECC*16", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "4090-24G 涡轮版*8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "SATA-SSD-480G*2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "NVMe-SSD 3.84T*2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "25G 光口双口CX5*1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-4090-48G", + "description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.", + "price": "8800", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "Intel Xeon 6530/32核心/2.1GHz;*2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G DDR5 4800MHZ ECC REG*16", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "8*RTX4090(48g)涡轮;(直通模式)", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "SATA-SSD-960G*1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "NVMe-SSD 3.84T*2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "25G 光口双口CX5*1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-4090", + "description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.", + "price": "8000", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "Intel Xeon 6530/32核心/2.1GHz *2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64G DDR5 4800MHZ ECC REG*16", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "8*RTX4090(24g)涡轮;(直通模式)", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "SATA-SSD-960G*1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "NVMe-SSD 3.84T*2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "25G 光口双口CX5*1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-4090", + "description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.", + "price": "7200", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "Intel Xeon 6530/32核心/2.1GHz *2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "32GB DDR4-3200ECCREG RDIMM *16", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "Geforce RTX4090 24GPCI-e 涡轮GPU卡 *8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "2.5\"480G SATA 读取密集 SSD *2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "NVMe-SSD 1.92T *2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "25G 光口双口CX5 *2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + }, + { + "title": "NVIDIA-4090", + "description": "High-performance GPU server with powerful computing capabilities, suitable for AI training, deep learning, etc.", + "price": "7000", + "pre_price": None, + "price_unit": "台/月", + "discount": None, + "bgImgUrl": "https://www.kaiyuancloud.cn/idfile?path=firstpagebg/4.png", + "list": [ + { + "id": 1, + "name": "CPU", + "content": "AMD EPYC 7502/32核心/2.5GHz *1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssc2x.png" + }, + { + "id": 2, + "name": "内存", + "content": "64GB DDR4-3200ECCREG RDIMM *16", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/cpu2x.png" + }, + { + "id": 3, + "name": "GPU", + "content": "Geforce RTX4090 24GPCI-e 涡轮GPU卡 *8", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/sdcard2x.png" + }, + { + "id": 4, + "name": "系统盘", + "content": "2.5\"480G SATA 读取密集 SSD *1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/servermini2x.png" + }, + { + "id": 5, + "name": "数据盘", + "content": "NVMe-SSD 3.84T *2", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/serverpath2x.png" + }, + { + "id": 6, + "name": "网卡", + "content": "25G 光口双口CX5 *1", + "icon": "https://www.kaiyuancloud.cn/idfile?path=firstpagehot/ssdr2x.png" + } + ] + } + ], } detailDataRQY = { @@ -969,7 +1446,8 @@ detailDataRQY = { "content": "在处理大规模计算任务时,容器可以帮助管理和调度大量的计算任务,确保资源的高效利用‌" }] } - ] + ], + "products": [] } detailDataLJS910B = { @@ -1088,7 +1566,8 @@ detailDataLJS910B = { "content": "2.GPU 加速 AI 推理,裸金属低延迟保障实时分析(如监控画面秒级报警);资源独占确保视频数据安全,符合安防 / 工业合规。" }] } - ] + ], + "products": [] } @@ -1224,7 +1703,8 @@ detailDataYITIKUNLUN = { "content": "与某运营商深度合作—— 技术测评领先、共建实验室、商业化落地,制定智能计算技术架构、评估AI 芯片功能/性能等指标、打造算力原生平台、为实验室提供强大算力底座,携手运营商解决智算发展中面临的挑战,共同实现智算技术引领。" }] } - ] + ], + "products": [] } async def get_firstpage_net_detail(ns={}): diff --git a/b/product/global_search.dspy b/b/product/global_search.dspy new file mode 100644 index 0000000..776db6c --- /dev/null +++ b/b/product/global_search.dspy @@ -0,0 +1,80 @@ +async def global_search(ns={}): + if not ns.get('url_link') or not ns.get('publish_type'): + return { + 'status': False, + 'msg': '请传递路由链接(url_link)和发布类型(publish_type)' + } + if not ns.get('keyword'): + return { + 'status': False, + 'msg': '请传递搜索关键词' + } + if not ns.get('display_page'): + return { + 'status': False, + 'msg': '请传递回显页面(display_page)' + } + + # 增加分页功能 + current_page = int(ns.get('current_page')) if ns.get('current_page') else 1 + page_size = int(ns.get('page_size')) if ns.get('page_size') else 8 + + # 分页查询 + offset = (current_page - 1) * page_size + + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + db = DBPools() + async with db.sqlorContext('kboss') as sor: + try: + # 增加分页条件 + # 分页条件 + find_sql = """SELECT * FROM user_publish_product WHERE publish_type = '%s' AND domain_name = '%s' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' ORDER BY priority DESC LIMIT %s OFFSET %s;""" + find_sql = find_sql % (ns.get('publish_type'), domain_name, page_size, offset) + + # 添加keyword模糊查询 筛选product_name, requirement_summary + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(product_name LIKE '%%%%%s%%%%' OR requirement_summary LIKE '%%%%%s%%%%') AND " % (ns.get('keyword'), ns.get('keyword')) + find_sql.split('WHERE')[1] + + # 如果是overview sql不筛选requirement_summary + if ns.get('display_page') == 'overview': + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(product_name LIKE '%%%%%s%%%%') AND " % (ns.get('keyword')) + find_sql.split('WHERE')[1] + + # 计算筛选后 返回总数量 count(*) + count_sql = """SELECT COUNT(*) AS total_count FROM user_publish_product WHERE publish_type = '%s' AND domain_name = '%s' AND audit_status = 'approved' AND listing_status = 'listing' AND del_flg = '0' AND (product_name LIKE '%%%%%s%%%%' OR requirement_summary LIKE '%%%%%s%%%%');""" + count_sql = count_sql % (ns.get('publish_type'), domain_name, ns.get('keyword'), ns.get('keyword')) + count_result = await sor.sqlExe(count_sql, {}) + total_count = count_result[0]['total_count'] + + result = await sor.sqlExe(find_sql, {}) + for res in result: + if res.get('img') and res['img'] != 'null': + res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img'] + else: + res['img'] = None + + # 根据display_page区分返回字段 + if ns.get('display_page') == 'overview': + # result 产品名称去重后的 产品名称列表 根据名称去重 + product_names = list(set([item['product_name'] for item in result])) + # 产品名称添加 uuid形成的八位id 形成列表嵌套字典的格式 + result = [{ 'id': str(uuid())[:8], 'product_name': product_name} for product_name in product_names] + + return { + 'status': True, + 'msg': 'search success', + 'data': { + 'current_page': current_page, + 'page_size': page_size, + 'total_count': total_count, + 'result': result + } + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to search publish product, %s' % str(e) + } + +ret = await global_search(params_kw) +return ret \ No newline at end of file diff --git a/b/product/homepage_category_tree_add.dspy b/b/product/homepage_category_tree_add.dspy new file mode 100644 index 0000000..e0fa9e8 --- /dev/null +++ b/b/product/homepage_category_tree_add.dspy @@ -0,0 +1,49 @@ +async def homepage_category_tree_add(ns={}): + if not ns.get('url_link'): + return { + 'status': False, + 'msg': '请传递路由链接' + } + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 区分运营和普通客户 + user_list = await sor.R('users', {'id': userid}) + if not user_list: + return { + 'status': False, + 'msg': '没有找到匹配的用户' + } + orgid = user_list[0]['orgid'] + ns_dic = { + 'id': uuid(), + 'domain_name': domain_name, + 'orgid': orgid, + 'parentid': ns.get('parentid', None), + 'priority': ns.get('priority', 99), + 'name': ns.get('name', ''), + 'icon': ns.get('icon', None), + 'source': ns.get('source', None), + 'listurl': ns.get('listurl', None), + } + try: + await sor.C('homepage_category_tree', ns_dic) + return { + 'status': True, + 'msg': 'product category created successfully' + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to create product category, %s' % str(e) + } + +ret = await homepage_category_tree_add(params_kw) +return ret \ No newline at end of file diff --git a/b/product/homepage_category_tree_search.dspy b/b/product/homepage_category_tree_search.dspy new file mode 100644 index 0000000..dd29793 --- /dev/null +++ b/b/product/homepage_category_tree_search.dspy @@ -0,0 +1,35 @@ +async def homepage_category_tree_search(ns={}): + if not ns.get('url_link'): + return { + 'status': False, + 'msg': '请传递路由链接' + } + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + db = DBPools() + async with db.sqlorContext('kboss') as sor: + ns_dic = { + 'domain_name': domain_name, + 'del_flg': '0' + } + try: + category_list = await sor.R('homepage_category_tree', ns_dic) + # 对icon字段增加前缀 + for category in category_list: + if category.get('iconurl') and ('http' not in category['iconurl']): + category['iconurl'] = 'https://' + domain_name + category['iconurl'] + + return { + 'status': True, + 'msg': 'product category created successfully', + 'data': category_list + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to create product category, %s' % str(e) + } + +ret = await homepage_category_tree_search(params_kw) +return ret \ No newline at end of file diff --git a/b/product/homepage_category_tree_update.dspy b/b/product/homepage_category_tree_update.dspy new file mode 100644 index 0000000..d5e7f89 --- /dev/null +++ b/b/product/homepage_category_tree_update.dspy @@ -0,0 +1,43 @@ +async def homepage_category_tree_update(ns={}): + if not ns.get('url_link'): + return { + 'status': False, + 'msg': '请传递路由链接' + } + if not ns.get('id'): + return { + 'status': False, + 'msg': '请传递分类ID' + } + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 区分运营和普通客户 + user_list = await sor.R('users', {'id': userid}) + if not user_list: + return { + 'status': False, + 'msg': '没有找到匹配的用户' + } + orgid = user_list[0]['orgid'] + ns.pop('userid', None) + try: + await sor.U('homepage_category_tree', ns) + return { + 'status': True, + 'msg': 'product category updated successfully' + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to update product category, %s' % str(e) + } + +ret = await homepage_category_tree_update(params_kw) +return ret \ No newline at end of file diff --git a/b/product/publish_product_add.dspy b/b/product/publish_product_add.dspy index 9502515..4427aef 100644 --- a/b/product/publish_product_add.dspy +++ b/b/product/publish_product_add.dspy @@ -45,8 +45,9 @@ async def publish_product_add(ns={}): ns_dic = { "id": uuid(), "publish_type": ns.get("publish_type"), + "cart_flag": ns.get("cart_flag"), "orgid": orgid, - "img": ns.get('img'), + "img": ns.get('img') if ns.get('img') else None, "domain_name": domain_name, "product_name": ns.get("product_name"), "product_category": product_category, @@ -65,6 +66,7 @@ async def publish_product_add(ns={}): "price": ns.get("price"), "unit": ns.get("unit"), "discount": ns.get("discount"), + "service_charge": ns.get("service_charge"), "short_term": ns.get("short_term"), "priority": ns.get("priority") if ns.get("priority") else 1, "status": ns.get("status") if ns.get("status") else '0', @@ -79,7 +81,7 @@ async def publish_product_add(ns={}): if ns.get('discount') == '0': ns['discount'] = None ns_dic['discount'] = None - + if ns.get('price') and ns.get('discount'): ns_dic['discount_price'] = float(ns.get('price')) * float(ns['discount']) / 10 else: diff --git a/b/product/publish_product_search.dspy b/b/product/publish_product_search.dspy index 995fb82..5da93e8 100644 --- a/b/product/publish_product_search.dspy +++ b/b/product/publish_product_search.dspy @@ -1,20 +1,63 @@ +async def get_user_role(ns={}): + sor = ns['sor'] + # get role + ns['del_flg'] = '0' + res_role = await sor.R('userrole', ns) + if res_role: + user_role = res_role[0] + else: + return { + "status": False, + "msg": "userrole table, user id can not find..." + } + roleid = user_role.get('roleid') + # get role name + role_name = await sor.R('role', {'id': roleid}) + if role_name: + role = role_name[0].get('role') + else: + return { + "status": False, + "msg": "role table, can not get role name" + } + + return role + async def publish_product_search(ns={}): """ 普通客户查看 运营查看自己提交内容 运营查看所有用户内容 + + 运营: 待审 已审 上架 + 客户: 已审 上架 驳回 :param ns: :return: """ - offset = ns['offset'] - flag = ns.get('flag') + offset = ns.get('offset') + manager_self = ns.get('manager_self') if ns.get('userid'): userid = ns.get('userid') else: userid = await get_user() + if not ns.get('url_link'): + return { + 'status': False, + 'msg': 'url_link is required' + } + + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + + publish_type = ns.get('publish_type') + page_size = int(ns['page_size']) if ns.get('page_size') else 8 + current_page_param = int(ns['current_page']) if ns.get('current_page') else 1 + current_page = (current_page_param - 1) * page_size + db = DBPools() - async with db.sqlorContext('kboss') as sor: + async with db.sqlorContext('kboss') as sor: # 区分运营和普通客户 user_list = await sor.R('users', {'id': userid}) if not user_list: @@ -31,32 +74,83 @@ async def publish_product_search(ns={}): if user_role != '客户': ns['del_flg'] = '0' - # 业主机构角色并且是只查看业主机构自己 flag==single - if orgid == 'mIWUHBeeDM8mwAFPIQ8pS' and flag == 'single': + # 业主机构角色并且是只查看业主机构自己 manager_self==single + if orgid == 'mIWUHBeeDM8mwAFPIQ8pS' and manager_self == 'single': + count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id + WHERE org.parentid IS NULL AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % publish_type + find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id - WHERE org.parentid IS NULL AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % offset - # 业主机构角色并且是查看所有(包括业主机构自己) flag!=single + WHERE org.parentid IS NULL AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (publish_type, page_size, current_page) + # 业主机构角色并且是查看所有(不包括业主机构自己) manager_self!=single (WHERE (org.id = '%s' or org.parentid = '%s') elif orgid == 'mIWUHBeeDM8mwAFPIQ8pS': + count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id + WHERE org.parentid = '%s' AND org.org_type != '1' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % (orgid, publish_type) + find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id - WHERE org.id = '%s' or org.parentid = '%s' AND org.org_type != '1' AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, orgid, offset) + WHERE org.parentid = '%s' AND org.org_type != '1' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page) # 其他机构非用户角色 只查看自己 - elif flag == 'single': + elif manager_self == 'single': + count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id + WHERE org.id = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % (orgid, publish_type) + find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id - WHERE org.id = '%s' AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, offset) - # 其他机构非用户角色查看所有 + WHERE org.id = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page) + # 其他机构非用户角色查看所有客户 (WHERE (org.id = '%s' or org.parentid = '%s') AND upr.del_flg = '0') else: + count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id + WHERE org.parentid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC;""" % (orgid, publish_type) + find_sql = """SELECT upr.* FROM user_publish_product AS upr LEFT JOIN organization AS org ON upr.orgid = org.id - WHERE (org.id = '%s' or org.parentid = '%s') AND upr.del_flg = '0' ORDER BY upr.create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, orgid, offset) + WHERE org.parentid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page) # 客户角色 else: ns['del_flg'] = '0' ns['orgid'] = user_list[0]['id'] - find_sql = """SELECT * FROM user_publish_product WHERE orgid = '%s' AND del_flg = '0' ORDER BY create_at DESC LIMIT 20 OFFSET %s;""" % (orgid, offset) + count_sql = """SELECT COUNT(*) AS total_count, upr.* FROM user_publish_product AS upr WHERE upr.orgid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page) + find_sql = """SELECT upr.* FROM user_publish_product AS upr WHERE upr.orgid = '%s' AND upr.del_flg = '0' AND upr.publish_type = '%s' ORDER BY upr.create_at DESC LIMIT %s OFFSET %s;""" % (orgid, publish_type, page_size, current_page) + + # 截取count_sql和find_sql中的 WHERE, 向WHERE后追加新的筛选条件 + # 如果审核状态是pending,approved, 查询待审和已审的数据 + if ns.get('audit_status') == 'pending,approved': + count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "(upr.audit_status = 'pending' OR upr.audit_status = 'approved') AND " + count_sql.split('WHERE')[1] + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(upr.audit_status = 'pending' OR upr.audit_status = 'approved') AND " + find_sql.split('WHERE')[1] + elif ns.get('audit_status'): + count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "upr.audit_status = '%s' AND " % ns.get('audit_status') + count_sql.split('WHERE')[1] + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "upr.audit_status = '%s' AND " % ns.get('audit_status') + find_sql.split('WHERE')[1] + + if ns.get('listing_status'): + count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "upr.listing_status = '%s' AND " % ns.get('listing_status') + count_sql.split('WHERE')[1] + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "upr.listing_status = '%s' AND " % ns.get('listing_status') + find_sql.split('WHERE')[1] + + # 添加start_date和end_date筛选 + if ns.get('start_date') and ns.get('end_date'): + count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "(upr.create_at BETWEEN '%s' AND '%s') AND " % (ns.get('start_date'), ns.get('end_date')) + count_sql.split('WHERE')[1] + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "(upr.create_at BETWEEN '%s' AND '%s') AND " % (ns.get('start_date'), ns.get('end_date')) + find_sql.split('WHERE')[1] + + # 添加keyword模糊查询 只筛选产品名称 + if ns.get('keyword'): + count_sql = count_sql.split('WHERE')[0] + ' WHERE ' + "upr.product_name LIKE '%%%%%s%%%%' AND " % ns.get('keyword') + count_sql.split('WHERE')[1] + find_sql = find_sql.split('WHERE')[0] + ' WHERE ' + "upr.product_name LIKE '%%%%%s%%%%' AND " % ns.get('keyword') + find_sql.split('WHERE')[1] + print(count_sql) + total_count = (await sor.sqlExe(count_sql, {}))[0]['total_count'] result = await sor.sqlExe(find_sql, {}) + + # 处理图片 + for res in result: + if res.get('img') and res['img'] != 'null': + res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img'] + else: + res['img'] = None return { 'status': True, 'msg': 'Requirements retrieved successfully', - 'data': result + 'data': { + "id": uuid(), + "total_count": total_count, + "page_size": page_size, + "current_page": current_page_param, + "product_list": result + } } except Exception as e: return { diff --git a/b/product/publish_product_search_detail.dspy b/b/product/publish_product_search_detail.dspy new file mode 100644 index 0000000..c212b01 --- /dev/null +++ b/b/product/publish_product_search_detail.dspy @@ -0,0 +1,67 @@ +async def get_user_role(ns={}): + sor = ns['sor'] + # get role + ns['del_flg'] = '0' + res_role = await sor.R('userrole', ns) + if res_role: + user_role = res_role[0] + else: + return { + "status": False, + "msg": "userrole table, user id can not find..." + } + roleid = user_role.get('roleid') + # get role name + role_name = await sor.R('role', {'id': roleid}) + if role_name: + role = role_name[0].get('role') + else: + return { + "status": False, + "msg": "role table, can not get role name" + } + + return role + +async def publish_product_search_detail(ns={}): + """ + :param ns: + :return: + """ + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + user_role = None + # 区分运营和普通客户 + if userid: + user_list = await sor.R('users', {'id': userid}) + orgid = user_list[0]['orgid'] + user_role = await get_user_role({'userid': userid, 'sor': sor}) + + # 如果用户角色是运营并且from='b' product_list中的phone_number和email做加星号处理 + product_list = await sor.R('user_publish_product', {'id': ns.get('id'), 'del_flg': '0'}) + if user_role == '运营' and ns.get('from') == 'b': + pass + else: + for product in product_list: + if product.get('phone_number'): + product['phone_number'] = product['phone_number'][:3] + '****' + product['phone_number'][7:] + else: + product['phone_number'] = '198****8601' + if product.get('email'): + product['email'] = product['email'][:2] + '****' + product['email'][6:] + else: + product['email'] = 'kawa@****.com' + + return { + 'status': True, + 'msg': 'Product retrieved successfully', + 'data': product_list[0] + } + +ret = await publish_product_search_detail(params_kw) +return ret \ No newline at end of file diff --git a/b/product/publish_product_search_first_page.dspy b/b/product/publish_product_search_first_page.dspy index 262b638..da7477b 100644 --- a/b/product/publish_product_search_first_page.dspy +++ b/b/product/publish_product_search_first_page.dspy @@ -44,8 +44,10 @@ async def publish_product_search_first_page(ns={}): list2 = [item.strip() for item in res['company_type'].split(',')] if not bool(set(list1) & set(list2)): continue - - res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img'] + if res.get('img') and res['img'] != 'null': + res['img'] = 'https://' + domain_name + '/idfile?path=' + res['img'] + else: + res['img'] = None # 电话和邮箱模糊化处理 if res.get('phone_number'): diff --git a/b/product/publish_product_to_excel.dspy b/b/product/publish_product_to_excel.dspy new file mode 100644 index 0000000..548749c --- /dev/null +++ b/b/product/publish_product_to_excel.dspy @@ -0,0 +1,120 @@ +async def publish_product_to_excel(ns={}): + if not ns.get('ids') and (not ns.get('result')): + return { + 'status': False, + 'msg': '请传递产品ID' + } + result = [] + if ns.get('ids'): + db = DBPools() + async with db.sqlorContext('kboss') as sor: + ids = json.loads(ns.get('ids')) if isinstance(ns.get('ids'), str) else ns.get('ids') + # 根据ids查询user_publish_product表 + find_sql = """SELECT * FROM user_publish_product WHERE id IN (%s) AND del_flg = '0';""" % ','.join(["'%s'" % id for id in ids]) + result = await sor.sqlExe(find_sql, {}) + if not result: + return { + 'status': False, + 'msg': '没有找到匹配的产品' + } + if ns.get('result_from_search'): + result = ns.get('result_from_search') + + # 结果转换成 中文名称:值 的字典列表 + field_mapping = { + # 'id': 'id', + # 'publish_type': '类型', + 'img': '图片链接', + # 'cart_flag': '是否支持显卡', + # 'domain_name': '所属域名', + # 'orgid': '所属机构', + 'product_name': '商品名称', + # 'product_category': '所属类别', + 'company_name': '企业名称', + # 'company_type': '公司类别', + 'contact_person': '联系人', + 'job_title': '职务', + 'phone_number': '手机号码', + 'email': '邮箱', + 'cpu': 'cpu', + 'memory': '内存', + 'gpu': 'gpu', + 'sys_disk': '系统盘', + 'data_disk': '数据盘', + 'net_card': '网卡', + 'price': '价格', + 'unit': '价格单位', + 'discount': '价格折扣', + 'discount_price': '折扣后价格', + 'service_charge': '服务费', + 'short_term': '是否短租', + # 'priority': '排序优先级', + 'status': '上架状态', + # 'title': '主题', + # 'label': '标签', + # 'first_page': '是否推送到首页', + # 'admin_push': '是否是运营人员提交', + 'requirement_summary': '需求概述', + 'related_parameters': '相关参数', + 'application_scenario': '应用场景', + 'audit_status': '审核状态', + 'listing_status': '上架状态', + 'reject_reason': '驳回原因', + 'update_time': '更新时间', + 'create_at': '创建时间', + # 'publish_time': '发布日期', + # 'del_flg': '删除标志' + } + # 转换字典键为中文 + for data_dic in result: + # 如果有图片路径 则转换为完整的图片链接 + if data_dic.get('img') and data_dic['img'] != 'null': + data_dic['img'] = 'https://' + data_dic['domain_name'] + '/idfile?path=' + data_dic['img'] + else: + data_dic['img'] = None + # 转换字典键为中文 对应的值要有映射 + # 拆分后:显式循环结构(便于后续处理) + new_data_dic = {} + for key, value in data_dic.items(): + if key == 'publish_type': + # 显示类型映射 + if value == '1': + value = '产品' + elif value == '2': + value = '需求' + if key == 'audit_status': + # 显示审核状态映射 + if value == 'pending': + value = '待审' + elif value == 'approved': + value = '通过' + elif value == 'rejected': + value = '拒绝' + if key == 'listing_status': + # 显示上架状态映射 + if value == '1': + value = '上架' + elif value == '0': + value = '下架' + if key == 'short_term': + # 显示短租状态映射 + if value == '1': + value = '是' + elif value == '0': + value = '否' + # 获取中文映射键 + chinese_key = field_mapping.get(key) + # 仅保留有映射关系的字段 + if chinese_key is not None: + new_data_dic[chinese_key] = value + data_dic.clear() + data_dic.update(new_data_dic) + + return { + 'status': True, + 'msg': 'export to excel success', + 'data': result + } + +ret = await publish_product_to_excel(params_kw) +return ret \ No newline at end of file diff --git a/b/product/publish_product_update.dspy b/b/product/publish_product_update.dspy new file mode 100644 index 0000000..3c397b3 --- /dev/null +++ b/b/product/publish_product_update.dspy @@ -0,0 +1,123 @@ +async def get_user_role(ns={}): + sor = ns['sor'] + # get role + ns['del_flg'] = '0' + res_role = await sor.R('userrole', ns) + if res_role: + user_role = res_role[0] + else: + return { + "status": False, + "msg": "userrole table, user id can not find..." + } + roleid = user_role.get('roleid') + # get role name + role_name = await sor.R('role', {'id': roleid}) + if role_name: + role = role_name[0].get('role') + else: + return { + "status": False, + "msg": "role table, can not get role name" + } + + return role + +async def publish_product_update(ns={}): + """ + 运营审批 + 运营编辑 + 客户编辑 + 运营发布 + """ + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 区分运营和普通客户 + user_list = await sor.R('users', {'id': userid}) + if not user_list: + return { + 'status': False, + 'msg': '没有找到匹配的用户' + } + + # 处理图片 如果包含http就跳过 + if ns.get('img') and ns['img'].startswith('http'): + ns.pop('img', None) + + orgid = user_list[0]['orgid'] + ns.pop('userid', None) + + ns_dic = ns + if ns.get('discount') == '0': + ns['discount'] = None + ns_dic['discount'] = None + + if ns.get('price') and ns.get('discount'): + ns_dic['discount_price'] = float(ns.get('price')) * float(ns['discount']) / 10 + elif ns.get('price'): + ns_dic['discount_price'] = ns['price'] + else: + pass + + user_role = await get_user_role({'userid': userid, 'sor': sor}) + # 编辑状态 + # 非客户角色编辑客户的产品 + if user_role != '客户' and ns.get('orgid') != orgid: + # 非客户角色审核客户的产品 + # 如果是待审状态 更新审核状态为通过 上架状态为上架 + if ns.get('audit_status') == 'approved': + ns_dic['audit_status'] = 'approved' + ns_dic['listing_status'] = 'listing' + # 如果是上架商品 更新publish_time为当前时间 + if ns.get('listing_status') == 'listing': + ns_dic['publish_time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + # 如果是下架商品 更新publish_time为None + elif ns.get('listing_status') == 'delisting': + ns_dic['publish_time'] = None + # 如果是删除商品 更新publish_time为None + elif ns.get('del_flg') == '1': + ns_dic['publish_time'] = None + else: + ns_dic['publish_time'] = None + + # 非客户角色编辑自己的产品 默认审批通过和发布成功 + elif user_role != '客户': + # 运营删除自己的产品 + if ns.get('del_flg') == '1': + pass + else: + ns['status'] = '1' + ns_dic['audit_status'] = 'approved' + # 运营下架自己的产品 + if not ns.get('listing_status') == 'delisting': + ns_dic['listing_status'] = 'listing' + ns_dic['first_page'] = '1' + # 客户编辑以后 审核状态是: 待审 上架状态是:空 + else: + # 客户要下架自己的产品 + if ns.get('listing_status') == 'delisting': + ns_dic['audit_status'] = None + ns_dic['listing_status'] = 'delisting' + # 客户仅编辑不是下架产品 + else: + ns_dic['audit_status'] = 'pending' + ns_dic['listing_status'] = None + ns_dic['publish_time'] = None + try: + await sor.U('user_publish_product', ns_dic) + return { + 'status': True, + 'msg': 'publish product created successfully' + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to publish product, %s' % str(e) + } + +ret = await publish_product_update(params_kw) +return ret \ No newline at end of file diff --git a/b/product/search_user_inquiry.dspy b/b/product/search_user_inquiry.dspy index 537d159..1dae62e 100644 --- a/b/product/search_user_inquiry.dspy +++ b/b/product/search_user_inquiry.dspy @@ -1,7 +1,16 @@ async def search_user_inquiry(ns={}): + if not ns.get('url_link'): + return { + 'status': False, + 'msg': '请传递url_link' + } + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + db = DBPools() async with db.sqlorContext('kboss') as sor: - search_sql = """select * from product_inquiry order by create_at desc;""" + search_sql = """select * from product_inquiry where domain_name = '%s' and del_flg = '0' order by update_time desc;""" % domain_name result = await sor.sqlExe(search_sql, {}) return { 'status': True, diff --git a/b/user/enterprise_audit_info_add.dspy b/b/user/enterprise_audit_info_add.dspy new file mode 100644 index 0000000..5873196 --- /dev/null +++ b/b/user/enterprise_audit_info_add.dspy @@ -0,0 +1,45 @@ +async def enterprise_audit_info_add(ns={}): + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 检查orgid是否存在 + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + user_list = await sor.R('users', {'id': userid}) + if not user_list: + return { + 'status': False, + 'msg': 'user not found' + } + orgid = user_list[0]['orgid'] + ns_dic = { + 'id': uuid(), + 'orgid': orgid, + 'account_type': ns.get('account_type'), + 'company_name': ns.get('company_name'), + 'license_number': ns.get('license_number'), + 'license_original_img': ns.get('license_original_img'), + 'license_copy_img': ns.get('license_copy_img'), + 'office_address': ns.get('office_address'), + 'registered_address': ns.get('registered_address'), + 'contact_name': ns.get('contact_name'), + 'telephone': ns.get('telephone'), + 'mobile_phone': ns.get('mobile_phone'), + 'email': ns.get('email'), + 'audit_status': 'pending', # 默认待审 + } + try: + await sor.C('enterprise_audit_info', ns_dic) + return { + 'status': True, + 'msg': 'enterprise audit info created successfully' + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to create enterprise audit info, %s' % str(e) + } + +ret = await enterprise_audit_info_add(params_kw) +return ret \ No newline at end of file diff --git a/b/user/enterprise_audit_info_search.dspy b/b/user/enterprise_audit_info_search.dspy new file mode 100644 index 0000000..3bc5eb1 --- /dev/null +++ b/b/user/enterprise_audit_info_search.dspy @@ -0,0 +1,78 @@ +async def get_user_role(ns={}): + sor = ns['sor'] + # get role + ns['del_flg'] = '0' + res_role = await sor.R('userrole', ns) + if res_role: + user_role = res_role[0] + else: + return { + "status": False, + "msg": "userrole table, user id can not find..." + } + roleid = user_role.get('roleid') + # get role name + role_name = await sor.R('role', {'id': roleid}) + if role_name: + role = role_name[0].get('role') + else: + return { + "status": False, + "msg": "role table, can not get role name" + } + + return role + +async def enterprise_audit_info_search(ns={}): + if not ns.get('url_link'): + return { + 'status': False, + 'msg': '请传递url_link' + } + domain_name = ns.get('url_link').split("//")[1].split("/")[0] + if 'localhost' in domain_name: + domain_name = 'dev.opencomputing.cn' + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 检查orgid是否存在 + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + user_list = await sor.R('users', {'id': userid}) + if not user_list: + return { + 'status': False, + 'msg': 'user not found' + } + orgid = user_list[0]['orgid'] + user_role = await get_user_role({'userid': userid, 'sor': sor}) + try: + if user_role == '客户': # 客户查询 + find_sql = """SELECT * FROM enterprise_audit_info WHERE orgid = '%s' AND del_flg = '0';""" % orgid + else: # 运营查询 enterprise_audit_info和organization表关联查询 enterprise_audit_info中的orgid和organization表中的id关联查询 + find_sql = """SELECT eai.* FROM enterprise_audit_info AS eai LEFT JOIN organization as org ON eai.orgid = org.id WHERE org.parentid = '%s' AND eai.del_flg = '0' ORDER BY eai.update_time DESC;""" % orgid + # 执行查询 + res = await sor.sqlExe(find_sql, {}) + + # 处理结果中的图片路径 增加前缀 + for item in res: + if item.get('license_original_img'): + item['license_original_img'] = 'https://' + domain_name + '/idfile?path=' + item['license_original_img'] + if item.get('license_copy_img'): + item['license_copy_img'] = 'https://' + domain_name + '/idfile?path=' + item['license_copy_img'] + + return { + 'status': True, + 'msg': 'enterprise audit info search successfully', + 'data': res + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to search enterprise audit info, %s' % str(e) + } + +ret = await enterprise_audit_info_search(params_kw) +return ret \ No newline at end of file diff --git a/b/user/enterprise_audit_info_update.dspy b/b/user/enterprise_audit_info_update.dspy new file mode 100644 index 0000000..4fbbb93 --- /dev/null +++ b/b/user/enterprise_audit_info_update.dspy @@ -0,0 +1,70 @@ +async def get_user_role(ns={}): + sor = ns['sor'] + # get role + ns['del_flg'] = '0' + res_role = await sor.R('userrole', ns) + if res_role: + user_role = res_role[0] + else: + return { + "status": False, + "msg": "userrole table, user id can not find..." + } + roleid = user_role.get('roleid') + # get role name + role_name = await sor.R('role', {'id': roleid}) + if role_name: + role = role_name[0].get('role') + else: + return { + "status": False, + "msg": "role table, can not get role name" + } + + return role + +async def enterprise_audit_info_update(ns={}): + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 检查orgid是否存在 + if ns.get('userid'): + userid = ns.get('userid') + else: + userid = await get_user() + user_list = await sor.R('users', {'id': userid}) + if not user_list: + return { + 'status': False, + 'msg': 'user not found' + } + user_role = await get_user_role({'userid': userid, 'sor': sor}) + ns.pop('userid', None) + # ns['orgid'] = orgid + try: + if user_role == '客户': # 客户更新 + ns['audit_status'] = 'pending' # 客户更新时默认审核状态为待审 + else: # 运营更新 如果是approved reject_reason为空 + if ns.get('audit_status') == 'approved': + ns['reject_reason'] = None + + # 生成更新的sql语句 + update_sql = """UPDATE enterprise_audit_info SET """ + for key, value in ns.items(): + if value is None: + update_sql += f"{key} = NULL, " + continue + update_sql += f"{key} = '{value}', " + update_sql = update_sql[:-2] + f" WHERE id = '{ns.get('id')}';""" + await sor.sqlExe(update_sql, {}) + return { + 'status': True, + 'msg': '更新成功' + } + except Exception as e: + return { + 'status': False, + 'msg': 'Failed to update enterprise audit info, %s' % str(e) + } + +ret = await enterprise_audit_info_update(params_kw) +return ret \ No newline at end of file