提交 65c0a9cb authored 作者: 张颂恩's avatar 张颂恩

Merge branch 'dev' of http://124.225.116.118:35236/tj_django/datacenter into dev

...@@ -45,8 +45,7 @@ class Policy(models.Model): ...@@ -45,8 +45,7 @@ class Policy(models.Model):
(2,_('以宴席桌数为准')), (2,_('以宴席桌数为准')),
(3,_('严格的箱与桌公式设定')), (3,_('严格的箱与桌公式设定')),
(4,_('箱数为主要条件,桌数为次要条件')), (4,_('箱数为主要条件,桌数为次要条件')),
(5,_('桌数为主要条件,箱数为次要条件')), (5,_('桌数为主要条件,箱数为次要条件'))),default=3)
(6,_('按扫码瓶数换算箱数计算'))),default=3)
grades=models.JSONField(_('奖励等级'),default=list,blank=True,null=True) grades=models.JSONField(_('奖励等级'),default=list,blank=True,null=True)
# [{ # [{
...@@ -171,6 +170,7 @@ class Apply(models.Model): ...@@ -171,6 +170,7 @@ class Apply(models.Model):
(4, _('结算中')), (4, _('结算中')),
(5, _('已结算')), (5, _('已结算')),
(6, _('开瓶数量不足,未通过结算奖励')), (6, _('开瓶数量不足,未通过结算奖励')),
(7, _('宴席资料异常')),
), default=0) ), default=0)
reason = models.CharField(_('原因'), max_length=500, blank=True, null=True) reason = models.CharField(_('原因'), max_length=500, blank=True, null=True)
annotation = models.CharField(_('批注'), max_length=500, blank=True, null=True) annotation = models.CharField(_('批注'), max_length=500, blank=True, null=True)
...@@ -186,7 +186,9 @@ class Apply(models.Model): ...@@ -186,7 +186,9 @@ class Apply(models.Model):
actual_table_num = models.SmallIntegerField(_('实际宴席桌数'), blank=True, null=True, default=0) actual_table_num = models.SmallIntegerField(_('实际宴席桌数'), blank=True, null=True, default=0)
actual_qty_x=models.IntegerField(_('实际箱数'),default=0) actual_qty_x=models.IntegerField(_('实际箱数'),default=0)
actual_qty_p=models.IntegerField(_('实际瓶数'),default=0) actual_qty_p=models.IntegerField(_('实际瓶数'),default=0)
salesman_info = models.CharField(_('业务员信息'), max_length=200, blank=True, null=True) scan_num=models.IntegerField(_('扫码数量'),default=0)
bottle_num=models.IntegerField(_('瓶数'),default=0)
is_ck=models.BooleanField(_('是否出库'),default=False,db_index=True)
class Meta: class Meta:
verbose_name = _('宴会申请') verbose_name = _('宴会申请')
......
...@@ -25,9 +25,9 @@ sK = 'fgfdvgu$#&3t@j' ...@@ -25,9 +25,9 @@ sK = 'fgfdvgu$#&3t@j'
from utils.views import time_key_check from utils.views import time_key_check
from inventory.views import LabelQuery, decrypt_11h from inventory.views import LabelQuery, decrypt_11h
from wx.views import transfer_batch from wx.views import transfer_batch
from mall.views import update_member_points_agent
import redis import redis
import math import math
from mall.views import update_member_points_agent
#2020-12-21 微信redis库 #2020-12-21 微信redis库
...@@ -99,6 +99,8 @@ def banquetList(request,obj): ...@@ -99,6 +99,8 @@ def banquetList(request,obj):
3: ['结算审核中','blue'], 3: ['结算审核中','blue'],
4: ['结算中','blue'], 4: ['结算中','blue'],
5: ['已结算','#07c160'], 5: ['已结算','#07c160'],
6: ['开瓶数量不足,未通过结算奖励','red'],
7: ['宴席资料异常','red'],
} }
status = dict[r[16]] status = dict[r[16]]
color = 'blue' color = 'blue'
...@@ -107,6 +109,8 @@ def banquetList(request,obj): ...@@ -107,6 +109,8 @@ def banquetList(request,obj):
btns = "<a href='/banquet/list/apply_codes/?id=" + str( btns = "<a href='/banquet/list/apply_codes/?id=" + str(
r[0]) + "' target='_blank' class='btn btn-default btn-sm btn-only-dlg'>申请扫码详情</a>" r[0]) + "' target='_blank' class='btn btn-default btn-sm btn-only-dlg'>申请扫码详情</a>"
btns = btns + "<a href='/banquet/list/apply_permit_detail/?id=" + str(
r[0]) + "' target='_blank' class='btn btn-default btn-sm btn-only-dlg'>查看备注</a>"
btns = btns + "<a href='/banquet/list/writeoff/?id=" + str( btns = btns + "<a href='/banquet/list/writeoff/?id=" + str(
r[0]) + "' target='_blank' class='btn btn-default btn-sm btn-only-dlg'>核销详情</a>" r[0]) + "' target='_blank' class='btn btn-default btn-sm btn-only-dlg'>核销详情</a>"
btns = btns + "<a href='/banquet/list/information_edit/?id=" + str( btns = btns + "<a href='/banquet/list/information_edit/?id=" + str(
...@@ -319,6 +323,17 @@ def banquetList(request,obj): ...@@ -319,6 +323,17 @@ def banquetList(request,obj):
]) ])
elif obj == "code_search": elif obj == "code_search":
return render(request, 'banquet/code_search.html', data) return render(request, 'banquet/code_search.html', data)
elif obj == "apply_permit_detail":#申请审批详情
id = int(request.GET.get('id','0'))
if id:
apply = Apply.objects.get(id=id)
user = User.objects.get(id=apply.permiter_id)
data["id"] = id
data["tm"] = apply.tm
data["permiter"] = user.last_name
data["reason"] = apply.reason
data["status"] = apply.get_status_display()
return render(request, 'banquet/apply_permit_detail.html', data)
return render(request, 'obj/list_obj.html', data) return render(request, 'obj/list_obj.html', data)
...@@ -390,7 +405,6 @@ def ajax_banquet(request,obj): ...@@ -390,7 +405,6 @@ def ajax_banquet(request,obj):
elif obj == "code_search": elif obj == "code_search":
return ajaxBanquetCodeSearch(request) return ajaxBanquetCodeSearch(request)
def ajaxBanquetApply(request): def ajaxBanquetApply(request):
res = { res = {
'e': '' 'e': ''
...@@ -434,6 +448,10 @@ def ajaxBanquetApply(request): ...@@ -434,6 +448,10 @@ def ajaxBanquetApply(request):
apply.ancestor_id = c.ancestor_id apply.ancestor_id = c.ancestor_id
apply.applyer_id = applyer_id apply.applyer_id = applyer_id
apply.company = c apply.company = c
if apply.status == 6:
res['e'] = '当前状态不允许修改'
return JsonResponse(res)
apply.category_id = category_id apply.category_id = category_id
if 'product_id' in d and d['product_id']: if 'product_id' in d and d['product_id']:
...@@ -443,9 +461,6 @@ def ajaxBanquetApply(request): ...@@ -443,9 +461,6 @@ def ajaxBanquetApply(request):
if 'address' in d and d['address']: if 'address' in d and d['address']:
apply.address = d['address'] apply.address = d['address']
if 'salesman_info' in d and d['salesman_info']:
apply.salesman_info = d['salesman_info']
apply.policy = policy apply.policy = policy
apply.table_num = table_num apply.table_num = table_num
apply.user_name = user_name apply.user_name = user_name
...@@ -879,9 +894,9 @@ def ajaxBanquetCancel(request): ...@@ -879,9 +894,9 @@ def ajaxBanquetCancel(request):
if obj.status == 0: if obj.status == 0:
obj.delete() obj.delete()
else: else:
res['e'] = '无法删除已审核申请' data['e'] = '无法删除已审核申请'
else: else:
res['e'] = '数据丢失' data['e'] = '数据丢失'
return JsonResponse(res) return JsonResponse(res)
...@@ -1103,10 +1118,15 @@ def ajaxBanquetSettle(request): ...@@ -1103,10 +1118,15 @@ def ajaxBanquetSettle(request):
# 如果提交箱数和核销相同 且 实际桌数与申请桌数相同 则自动返利 并修改状态为结算中 # 如果提交箱数和核销相同 且 实际桌数与申请桌数相同 则自动返利 并修改状态为结算中
if apply_codes_cnt == writeoff_cnt and apply.actual_table_num == apply.table_num: if apply_codes_cnt == writeoff_cnt and apply.actual_table_num == apply.table_num:
if apply.ancestor_id == 208869: if apply.ancestor_id == 208869:
d = ajaxBanquetConsumerScanAnalysis(id) apply.status = 3 #结算审核中
#print(d) #pids = [10558, 10559, 10560, 10561, 10562]
if d['scan_rate'] >= 0.5: # 如果是一代产品则直接结算
apply.status = 4 #结算中 #if apply.product_id in pids:
# apply.status = 4 #结算中
#else:
# d = ajaxBanquetConsumerScanAnalysis(id)
# if d['scan_rate'] >= 1:
# apply.status = 4 #结算中
else: else:
apply.status = 4 #结算中 apply.status = 4 #结算中
...@@ -1244,7 +1264,7 @@ def policy(request,action='list',id=None): ...@@ -1244,7 +1264,7 @@ def policy(request,action='list',id=None):
else: else:
form=PolicyForm(request.POST,instance=obj) form=PolicyForm(request.POST,instance=obj)
print(form)
if form.is_valid(): if form.is_valid():
form.save() form.save()
...@@ -1531,37 +1551,25 @@ def close_applys(request,agent_id,apply_id=None): ...@@ -1531,37 +1551,25 @@ def close_applys(request,agent_id,apply_id=None):
data['apply_ids'].append(r[1]) data['apply_ids'].append(r[1])
# 箱数
x_num = 'count(*)'
# 查询手动结算记录,如果有手动结算,则以手动结算为准 # 查询手动结算记录,如果有手动结算,则以手动结算为准
cur.execute("select amt from banquet_settlerecord where apply_id = "+app+" order by id desc limit 1") cur.execute("select amt from banquet_settlerecord where apply_id = "+app+" order by id desc limit 1")
r = cur.fetchone() r = cur.fetchone()
if r: if r:
amt = str(r[0]) amt = str(r[0])
else:
# # 查询扫码率 过滤不需要扫码的产品
if ancestor_id == 208869:
include_product_ids = [10124, 10125, 10126, 10127, 10128]
if product_id in include_product_ids:
analysis = ajaxBanquetConsumerScanAnalysis(int(app))
if analysis['bottle_num']:
x_num = str(math.floor(analysis['bottle_num'] / 6))
print(amt)
if amt !='0': if amt !='0':
# 写入奖励记录产品名称 # 写入奖励记录
s="insert into banquet_bonus(ancestor_id,agent_id,policy_id,apply_id,product_id,qty_x,table_num,amt,qty_p) "+\ s="insert into banquet_bonus(ancestor_id,agent_id,policy_id,apply_id,product_id,qty_x,table_num,amt,qty_p) "+\
"select "+aid+","+agent_id+","+id+","+app+",product_id,X,Z,"+amt+",P from "+\ "select "+aid+","+agent_id+","+id+","+app+",product_id,X,Z,"+amt+",P from "+\
"(select product_id,"+x_num+" X, "+z+" Z,sum(P) P from "+\ "(select product_id,count(*) X, "+z+" Z,sum(P) P from "+\
"(select label_pk_id,product_id,"+\ "(select label_pk_id,product_id,"+\
"(select count(*) from banquet_writeoff where apply_id="+app+" and label_pk_id=w.label_pk_id and label_pkg!=3) P "+\ "(select count(*) from banquet_writeoff where apply_id="+app+" and label_pk_id=w.label_pk_id and label_pkg!=3) P "+\
"from banquet_writeoff w where apply_id="+app+\ "from banquet_writeoff w where apply_id="+app+\
" group by label_pk_id,product_id"+\ " group by label_pk_id,product_id"+\
") g group by product_id"+\ ") g group by product_id"+\
") gg" ") gg"
print(s)
cur.execute(s) cur.execute(s)
#print(s)
# 写入剩余实物 # 写入剩余实物
s="INSERT INTO banquet_surplus(ancestor_id,agent_id,policy_id,apply_id,product_id,qty_x,qty_p,dt,tm) "+\ s="INSERT INTO banquet_surplus(ancestor_id,agent_id,policy_id,apply_id,product_id,qty_x,qty_p,dt,tm) "+\
......
...@@ -7092,6 +7092,35 @@ def ajax_company(request,obj): ...@@ -7092,6 +7092,35 @@ def ajax_company(request,obj):
return ajaxGetWorkCardDetail(request) return ajaxGetWorkCardDetail(request)
elif obj == 'getWorkCardByLabelCode': elif obj == 'getWorkCardByLabelCode':
return ajaxGetWorkCardByLabelCode(request) return ajaxGetWorkCardByLabelCode(request)
elif obj == 'getCompanyUserbyName':#通过名称模糊查询user
return ajaxGetCompanyUserbyName(request)
#用户名称模糊搜索
def ajaxGetCompanyUserbyName(request):
data={
'e':'',
'list':[]
}
name=request.GET.get('name','')
company_id=request.GET.get('company_id','')
agent_id=request.GET.get('agent_id','')
if name:
cur=connection.cursor()
sql = f"""
select id,last_name from company_user
where ancestor_id={company_id} and company_id={agent_id} and last_name like '%{name}%'
"""
cur.execute(sql)
for r in cur.fetchall():
data['list'].append({
'id':r[0],
'name':r[1],
})
else:
data['e'] ='数据丢失'
return JsonResponse(data)
......
...@@ -119,6 +119,9 @@ urlpatterns = [ ...@@ -119,6 +119,9 @@ urlpatterns = [
#2020-10-19 #2020-10-19
url(r'^obj/ajax/subsaldiv/(?P<division_id>\w+)/$', list_views.ajax_subdiv), url(r'^obj/ajax/subsaldiv/(?P<division_id>\w+)/$', list_views.ajax_subdiv),
#2024-11-21 根据系列查产品
url(r'^obj/ajax/series_to_product/$', list_views.ajax_series_to_product),
...@@ -1113,6 +1116,7 @@ urlpatterns = [ ...@@ -1113,6 +1116,7 @@ urlpatterns = [
url(r'^sales/do_hexiao_dispatch/$', sal_views.do_hexiao_dispatch), url(r'^sales/do_hexiao_dispatch/$', sal_views.do_hexiao_dispatch),
url(r'^sales/do_hexiao_accept/$', sal_views.do_hexiao_accept), url(r'^sales/do_hexiao_accept/$', sal_views.do_hexiao_accept),
url(r'^sales/hexiao_record/$', sal_views.hexiao_record), url(r'^sales/hexiao_record/$', sal_views.hexiao_record),
url(r'^sales/no_hexiao_record/$', sal_views.no_hexiao_record),
url(r'^sales/hexiao_record/detail/(?P<id>\d+)/$', sal_views.hexiao_record_detail), url(r'^sales/hexiao_record/detail/(?P<id>\d+)/$', sal_views.hexiao_record_detail),
url(r'^sales/hexiao_record/permit/(?P<id>\d+)/$', sal_views.hexiao_record_permit), url(r'^sales/hexiao_record/permit/(?P<id>\d+)/$', sal_views.hexiao_record_permit),
url(r'^sales/hexiao_dispatch_record/$', sal_views.hexiao_dispatch_record), url(r'^sales/hexiao_dispatch_record/$', sal_views.hexiao_dispatch_record),
...@@ -1182,6 +1186,8 @@ urlpatterns = [ ...@@ -1182,6 +1186,8 @@ urlpatterns = [
url(r'^test/consumer_winner_hit/$', sal_views.test_consumer_winner_hit), url(r'^test/consumer_winner_hit/$', sal_views.test_consumer_winner_hit),
url(r'^test/zsk_pay/$', wx_views.test_zsk),
url(r'^wx/kangnian/terminal/$', wx_views.kangnian_getTerminal), url(r'^wx/kangnian/terminal/$', wx_views.kangnian_getTerminal),
url(r'^wx/kangnian/product_list/$', wx_views.kangnian_getProductList), url(r'^wx/kangnian/product_list/$', wx_views.kangnian_getProductList),
......
...@@ -704,10 +704,14 @@ def edit_obj(request,obj_name,id=None): ...@@ -704,10 +704,14 @@ def edit_obj(request,obj_name,id=None):
if id: if id:
s = "SELECT id,name,(select count(id) from company_user where product_series @> Array[s.id] and id = "+id+") "+\ s = "SELECT id,name,(select count(id) from company_user where product_series @> Array[s.id] and id = "+id+") "+\
"FROM product_series s where company_id = "+str(c.ancestor_id) "FROM product_series s where company_id = "+str(c.ancestor_id)
else:
s = "SELECT id,name,0"+\
"FROM product_series s where company_id = "+str(c.ancestor_id)
cur.execute(s) cur.execute(s)
for r in cur.fetchall(): for r in cur.fetchall():
series.append([r[0], r[1],r[2]]) series.append([r[0], r[1],r[2]])
products = [] products = []
if id: if id:
s = "select id, name from product_product where id in (select UNNEST(product_ids) from company_user where id = "+id+") " s = "select id, name from product_product where id in (select UNNEST(product_ids) from company_user where id = "+id+") "
...@@ -2991,7 +2995,7 @@ def list_obj(request, obj): ...@@ -2991,7 +2995,7 @@ def list_obj(request, obj):
r[0],r[15], r[1], r[2], r[3], img, r[5],r[6], r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[14] r[0],r[15], r[1], r[2], r[3], img, r[5],r[6], r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[14]
]) ])
else: else:
data['clmns'] = [_('活动名称'),_('奖项'), _('奖品'), _('红包金额'), _('复购次数'), _('微信昵称'), _('微信头像'), _('姓名'), _('电话'), _('地址'), _('中奖时间'), _('领奖时间'), _('经销商'), _('区域'),_('生产批次'),_('标签序号'), _('备注')] data['clmns'] = [_('活动名称'),_('奖项'), _('奖品'), _('红包金额'), _('复购次数'), _('微信昵称'), _('微信头像'), _('姓名'), _('电话'), _('地址'), _('中奖时间'), _('领奖时间'), _('经销商'), _('区域'),_('生产批次'),_('标签序号'),_('箱码'), _('备注')]
s="select " +\ s="select " +\
"coalesce((select name from sales_activities where id=a.activity_id),'')," +\ "coalesce((select name from sales_activities where id=a.activity_id),'')," +\
"coalesce(b.name,'未中奖'),"+\ "coalesce(b.name,'未中奖'),"+\
...@@ -3009,7 +3013,8 @@ def list_obj(request, obj): ...@@ -3009,7 +3013,8 @@ def list_obj(request, obj):
"coalesce(label_code,''), "+\ "coalesce(label_code,''), "+\
"coalesce(remark,''),"+\ "coalesce(remark,''),"+\
"coalesce(cast(a.award_amount as text), ''),"+\ "coalesce(cast(a.award_amount as text), ''),"+\
"coalesce(cast((select fg_num from sales_award where id=b.award_id) as integer), 0) " + \ "coalesce(cast((select fg_num from sales_award where id=b.award_id) as integer), 0)," + \
"coalesce(xcode,'') " + \
"from "+\ "from "+\
"(select * from sales_consumerwinner "+sWhere+" and company_id="+str(c.id) +ssql+") a "+\ "(select * from sales_consumerwinner "+sWhere+" and company_id="+str(c.id) +ssql+") a "+\
"left outer join "+\ "left outer join "+\
...@@ -3024,7 +3029,7 @@ def list_obj(request, obj): ...@@ -3024,7 +3029,7 @@ def list_obj(request, obj):
if r[4]: if r[4]:
img = "<img src='"+r[4]+"' style='height:30px;cursor:pointer;' tt='"+r[3]+"'></img>" img = "<img src='"+r[4]+"' style='height:30px;cursor:pointer;' tt='"+r[3]+"'></img>"
data['data'].append([ data['data'].append([
r[0], r[1], r[2], r[15], r[16] if r[16] else '/', r[3], img, r[5],r[6], r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[14] r[0], r[1], r[2], r[15], r[16] if r[16] else '/', r[3], img, r[5],r[6], r[7],r[8],r[9],r[10],r[11],r[12],r[13],r[17],r[14]
]) ])
#2020-11-30 #2020-11-30
elif obj == 'consumerredeem': elif obj == 'consumerredeem':
...@@ -6395,3 +6400,20 @@ def agent_is_active_star(request,id=None): ...@@ -6395,3 +6400,20 @@ def agent_is_active_star(request,id=None):
""" """
cur.execute(s) cur.execute(s)
return JsonResponse(data) return JsonResponse(data)
def ajax_series_to_product(request):
cpid = request.GET.get('company_id', '')
series_ids = request.GET.get('series_ids', '')
s=f"""
select id,name from product_product where series_id in ({series_ids}) and company_id={cpid}
"""
cur = connection.cursor()
cur.execute(s)
data = []
for r in cur.fetchall():
data.append({
'id': r[0],
'name': r[1]
})
return JsonResponse(data, safe=False)
差异被折叠。
...@@ -49,8 +49,10 @@ ...@@ -49,8 +49,10 @@
var status = {{status}} var status = {{status}}
if(status >= 3){ if(status >= 3){
$("#status_select").html(` $("#status_select").html(`
<option value="2">驳回</option>
<option value="4">通过</option> <option value="4">通过</option>
<option value="1">驳回(重新核销)</option>
<option value="2">驳回(重新申请)</option>
<option value="6">开瓶数量不足,未通过结算奖励</option>
`) `)
} }
...@@ -62,6 +64,8 @@ ...@@ -62,6 +64,8 @@
3: ['结算审核中','blue'], 3: ['结算审核中','blue'],
4: ['结算中','blue'], 4: ['结算中','blue'],
5: ['已结算','#07c160'], 5: ['已结算','#07c160'],
6: ['开瓶数量不足,未通过结算奖励','red'],
7: ['宴席资料异常','red'],
} }
var firstLink = $(window.click_row).find('td:first a'); var firstLink = $(window.click_row).find('td:first a');
$(firstLink).text(status_dict[status][0]) $(firstLink).text(status_dict[status][0])
...@@ -86,6 +90,7 @@ ...@@ -86,6 +90,7 @@
<option value="0">未审核</option> <option value="0">未审核</option>
<option value="1">通过</option> <option value="1">通过</option>
<option value="2">未通过</option> <option value="2">未通过</option>
<option value="7">宴席资料异常</option>
</select> </select>
</div> </div>
</div> </div>
...@@ -95,6 +100,7 @@ ...@@ -95,6 +100,7 @@
<textarea id="txt_remark" cols="30" rows="10" placeholder="填写备注" style="width: 100%;"></textarea> <textarea id="txt_remark" cols="30" rows="10" placeholder="填写备注" style="width: 100%;"></textarea>
</div> </div>
</div> </div>
<h3 style="text-align: center; margin-top:20px;">宴会信息审核</h3>
<div> <div>
<button class="btn btn-primary" id="btn_permit" style="float:right;">保存</button> <button class="btn btn-primary" id="btn_permit" style="float:right;">保存</button>
</div> </div>
......
{% extends 'obj_form.html' %}
{% load i18n %}
{% block subtitle %}
<ol class="breadcrumb">
<li>{% trans '宴会管理' %}</li>
<li>{% trans '审核详情' %}</li>
</ol>
{% endblock %}
{% block form_content %}
<script>
$(document).ready(function () {
})
</script>
<style>
input[type=checkbox]{
display: inline-block;
width: auto;
height: auto;
margin-top: 10px;
}
</style>
{% if status|add:0 > 2 %}
<h3 style="text-align: center; margin-top:20px;">宴席结算审核</h3>
{% else %}
<h3 style="text-align: center; margin-top:20px;">宴席审核</h3>
{% endif %}
<div class="form-group">
<label class="">审核状态:{{status }}</label>
</div>
<div class="form-group">
<label class=" ">审核时间:{{tm}}</label>
</div>
<div class="form-group">
<label class=" ">审核人:{{permiter}}</label>
</div>
<div class="form-group">
<label class="">备注: {{reason}}</label>
</div>
<div>
<!-- <button class="btn btn-primary" id="btn_permit" style="float:right;">保存</button> -->
</div>
{% endblock %}
\ No newline at end of file
...@@ -10,6 +10,13 @@ ...@@ -10,6 +10,13 @@
}); });
var company_id = {{request.user.company.id}}||'';
if(company_id=='255721'){//上海悠氧 调整命名
$('#store_name').text('供应链中心')
$('#store_manager').text('供应链管理员')
$('#store_address').text('供应链地址')
}
$('#keeper_label').autocomplete({ $('#keeper_label').autocomplete({
source: function(request, response) { source: function(request, response) {
$.ajax({ $.ajax({
...@@ -77,16 +84,16 @@ ...@@ -77,16 +84,16 @@
</div> </div>
{% endif %} {% endif %}
<div class="form-group "> <div class="form-group ">
<label class="col-sm-2 control-label ">{% get_verbose_field_name form.instance 'name' %} </label> <label id="store_name" class="col-sm-2 control-label ">{% get_verbose_field_name form.instance 'name' %} </label>
<div class="col-sm-10">{{ form.name }}</div> <div class="col-sm-10">{{ form.name }}</div>
</div> </div>
<div class="form-group "> <div class="form-group ">
<label class="col-sm-2 control-label ">库房管理员</label> <label id="store_manager" class="col-sm-2 control-label ">库房管理员</label>
<div class="col-sm-10"><input type="text" class="form-control" id="keeper_label" ></div> <div class="col-sm-10"><input type="text" class="form-control" id="keeper_label" ></div>
</div> </div>
<div class="form-group "> <div class="form-group ">
<label class="col-sm-2 control-label ">仓库地址</label> <label id="store_address" class="col-sm-2 control-label ">仓库地址</label>
<div class="col-sm-10">{{ form.address }}</div> <div class="col-sm-10">{{ form.address }}</div>
</div> </div>
<div class="form-group "> <div class="form-group ">
......
...@@ -70,9 +70,15 @@ ...@@ -70,9 +70,15 @@
</div> </div>
</div> </div>
<style>
.fs-wrap{
vertical-align: middle;
}
</style>
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label">产品系列授权</label> <label class="col-md-2 control-label">产品系列授权</label>
<div class='col-sm-4'> <div class='col-sm-10'>
<select id="ySelectSeries" multiple="multiple"> <select id="ySelectSeries" multiple="multiple">
{% for s in series %} {% for s in series %}
{% ifequal s.2 1 %} {% ifequal s.2 1 %}
...@@ -82,6 +88,13 @@ ...@@ -82,6 +88,13 @@
{% endifequal %} {% endifequal %}
{% endfor %} {% endfor %}
</select> </select>
{% ifequal request.user.company_id 255721 %}
<span id="series_to_product" style="display: inline-block; 'vertical-align':middle;" class="input-group-btn">
<button type="button" class="btn btn-success">
<span class='glyphicon glyphicon-arrow-down'>添加选取系列到产品授权</span>
</button>
</span>
{% endifequal%}
</div> </div>
</div> </div>
...@@ -123,6 +136,44 @@ ...@@ -123,6 +136,44 @@
{% block js %} {% block js %}
{{ block.super }} {{ block.super }}
//把授权系列产品添加到产品授权列表
$('#series_to_product').on('click',function(){
var series= $("#ySelectSeries").ySelectedValues(",");
if(!series) return;
if($("#ySelectSeries")){
$.ajax({
url: '/obj/ajax/series_to_product',
dataType: "json",
data: {
//term: $("#id_company_name").val() ,//搜索栏里的内容
company_id: {{ request.user.company_id }},//额外参数
series_ids : series
},
success: (data)=>{
console.log('data',data);
if(data.length==0) return;
for(var i=0;i<data.length;i++){
var e=false;
$("#sel-product option").each(function(){
if($(this).val() == data[i].id){
e=true;
}
});
if(e){
toastr.error(data[i].label+"已在列表中!", "操作错误:",
{timeOut: 800, positionClass: "toast-center-center"}
);
console.log('已在列表中!',data[i].label);
}else{
$('#sel-product').append("<option value='"+data[i].id+"'>"+data[i].name+"</option>");
}
}
}
});
};
})
$('.btn-save').click(function(){ $('.btn-save').click(function(){
$(this).hide(); $(this).hide();
var g_ids=[]; var g_ids=[];
...@@ -201,10 +252,7 @@ ...@@ -201,10 +252,7 @@
}); });
$('#obj_form .btn-showpassword').click(function(){
event.preventDefault();
$('#password').show();
});
//2024-05-31 //2024-05-31
$('#sel_is_active').val('{{form.instance.is_active}}'); $('#sel_is_active').val('{{form.instance.is_active}}');
...@@ -249,6 +297,7 @@ ...@@ -249,6 +297,7 @@
); );
$('#product_label').autocomplete({ $('#product_label').autocomplete({
source: function(request, response) { source: function(request, response) {
$.ajax({ $.ajax({
......
{% load i18n %}
<style>
.ui-autocomplete {
z-index: 9999;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
var page_length = 10;
var table = $('#tb').DataTable({
dom: 'Bfrtip',
autoWidth: true,
pageLength: page_length,
buttons: [{ extend: 'excelHtml5', text: '导出到Excel' }],
language: lng,
data: {{ data| safe}}
});
table.columns().every(function () {
var that = this;
$('input', this.footer()).on('keyup change clear', function () {
if (that.search() !== this.value) {
that.search(this.value).draw();
}
});
});
$('#tb').on("click", "td a", function (event) {
event.preventDefault();
$.RefreshContent($(this).attr('href'));
});
$('.datepicker').datepicker({ dateFormat: 'yy-mm-dd' });
$('.datepicker').datepicker('setDate', new Date());
setDatePickerZh();
$('#dt_fr').val('{{date_from}}');
$('#dt_to').val('{{date_to}}');
$('.btn-qry').click(function () {
var date_from, date_to;
date_fr = $('#dt_fr').val();
date_to = $('#dt_to').val();
var params = [];
if (date_fr != '') { params.push('date_from=' + date_fr) };
if (date_to != '') { params.push('date_to=' + date_to) };
if (params.length == 0) {
bootbox.alert("{% trans '请先输入查询条件!'%}");
} else {
$.RefreshContent('{{request.path}}?' + params.join('&'));
}
});
});
function deleteItem(id) {
var r = confirm('您确定要删除吗?');
if (r) {
var durl = '{{request.path}}delete/' + id + '/'
$.RefreshContent(durl);
}
}
function permitIt(id,e) {
var event = e || window.event;
var btn = event.target;
var r = confirm('是否将状态改为允许?');
if (r) {
var durl = '{{request.path}}permit/' + id + '/'
//$.RefreshContent(durl);
$.ajax({
url:durl,
success:function(res){
if(res.e === ''){
$(btn).hide();
$(btn).siblings().text('是').css({'color':'green'})
}
else{
alert(res.e);
}
}
})
}
}
$('#user_label').autocomplete({
source: function (request, response) {
$.ajax({
url: '/obj/ajax/autocomplete/user/',
dataType: "json",
data: {
term: $("#user_label").val(),//搜索栏里的内容
company_id: '{{request.user.company.id}}',//额外参数
},
success: function (data) {
response(data);
}
});
},
select: function (event, ui) {
$("#id_user").val(ui.item.value);
$("#user_label").val(ui.item.label)
return false;
}
});
$('#modal_order').on('shown.bs.modal', function (event) {
var button = $(event.relatedTarget) // Button that triggered the modal
var id = button.data('id') // Extract info from data-* attributes
$('#id_record').val(id)
})
$("#btn-save").click(function () {
if ($("#id_user").val() !== '') {
$.SubmitForm('#form_1', '{{request.path}}');
$('#modal_order').modal('hide')
}
else {
alert('请选择业务员')
}
})
</script>
<ol class="breadcrumb">
<li>{{subtt.0}}</li>
<li>{{subtt.1}}</li>
</ol>
<form role="form" class="form-inline" style="margin-top:0px;padding-left:10px;">
<div class="col-sm-2 input-group">
<span class="input-group-addon">{% trans "开始日期"%}</span>
<input class="datepicker form-control" id="dt_fr" />
</div>
<div class="col-sm-2 input-group">
<span class="input-group-addon">{% trans "结束日期"%}</span>
<input class="datepicker form-control" id="dt_to" />
</div>
<div class="col-sm-2 input-group">
<span class='input-group-btn'>
<a type="button" class='btn btn-primary btn-qry'>
<span class='glyphicon glyphicon-search' style='padding-right:5px;'></span>{% trans '查找' %}
</a>
</span>
</div>
</form>
<div class="clearfix"></div>
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="x_panel">
<div class="table-responsive">
<table id='tb' class="table table-striped table-bordered dt-responsive nowrap" cellspacing="0" width="100%">
<thead>
{% for c in clmns %}
<th>{{c}}</th>
{% endfor %}
</thead>
<tbody></tbody>
<tfoot>
{% for c in clmns %}
<th><input type="text" placeholder="{{c}}"></th>
{% endfor %}
</tfoot>
</table>
</div>
</div>
</div>
<div class="modal fade" id="modal_order" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">分配业务员</h4>
</div>
<div class="modal-body">
<form role="form" method='POST' enctype="multipart/form-data" class="form-horizontal" id="form_1">
{% csrf_token %}
<div class="form-group">
<label for="user_label">用户账号</label>
<div>
<input id='user_label'>
</div>
</div>
<input type="hidden" id="id_user" name="user_id" />
<input type="hidden" id="id_record" name="id" />
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="btn-save">确定</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIEKDCCAxCgAwIBAgIUJ0XANv9J3dPSsKnxD1nTF2XX6+8wDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjQxMTE1MDYyMTA3WhcNMjkxMTE0MDYyMTA3WjCBgTETMBEGA1UEAwwK
MTY1MTIxNTEyOTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL
DCTpmZXopb/lhbHpgJrphZLkuJrmnInpmZDotKPku7vlhazlj7gxCzAJBgNVBAYT
AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBANI75yKUP9aDrnOoPIZT9QInz4m54rS1fy3P9bFTHlwsh9j2Ul8MDb6U
5FWfqVcpBIlUMe3rvJTApU7H7AiwleKt5o+Il3i+3nKtlpAa/+t82BymwuNbethi
BpR58jy0OdR/x4R94QkgLxmCznqn6FK6yB9xkMByXIHR9coX0QdaMoHVmW5F/WjN
cBsVPDbD7GBNsnOLRyJ2EQYjL4pc8x/xmsRVuLVM3Oe88GB28GuqworcqbAh+zJa
2Bgyp2JpuUi245IatCzOzUrD8UX5VHJT5/c/2OKq9rVqStFc6TfhxOWTbFN3EhuO
reMRC321MVqJh3ENgHKddxhnwNPpIBsCAwEAAaOBuTCBtjAJBgNVHRMEAjAAMAsG
A1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2Y2Eu
aXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRC
MDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJCMjdB
OUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQAh9oSV
wAuK28wR36eB/kPlESVH8kD1sO8W1M9TbgSnpy4bxhXqBAdWJOy4WK8fJpX/oMMX
RcM5fzBdzxs4J9UjS9M9nDAqxDz1Ir5QNGi4otN8sVxR6wmxsQmq3i40bDG1p8V/
E/C8BLYKdY4hzbHXlpap+r6rEaTq46yxjrRtr2LybbG85bvvVAY/1ga84KRI7/Yz
Mqdb6QmtuwtVZhpjDkWRFuTB0H7NBQ5UlrtxmVoUgoVJ7u7OvWy/Vdlwu5Sq2PXm
/ITP9GdOd0CTUr7qGQmTlrwIBUT+sENJokpHM7oEoE9qTFLYdL0dY4xYvR4z62cT
qP6Mtt4nqP7qLcE4
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSO+cilD/Wg65z
qDyGU/UCJ8+JueK0tX8tz/WxUx5cLIfY9lJfDA2+lORVn6lXKQSJVDHt67yUwKVO
x+wIsJXireaPiJd4vt5yrZaQGv/rfNgcpsLjW3rYYgaUefI8tDnUf8eEfeEJIC8Z
gs56p+hSusgfcZDAclyB0fXKF9EHWjKB1ZluRf1ozXAbFTw2w+xgTbJzi0cidhEG
Iy+KXPMf8ZrEVbi1TNznvPBgdvBrqsKK3KmwIfsyWtgYMqdiablItuOSGrQszs1K
w/FF+VRyU+f3P9jiqva1akrRXOk34cTlk2xTdxIbjq3jEQt9tTFaiYdxDYBynXcY
Z8DT6SAbAgMBAAECggEAAMAqARuaZr+tncgZ/zjJhSpzOUCqqI6FV7qIXAu57gZS
rdmjTaeTXPzXG98oEaGZ3IuqafkPgVB2xqM8GoPW5SpNynFoaQv1a19nTDhsdYDK
nL+TrpAjDia7c0hELydNlY6nPbfdV9T/lg27gwCaecEk+cfEBovh/KytPf17x5Tv
NObDM30mbMGyzW+sil0pb64sKrP19QCmMfj3onvq7xts9dzyAAZIQ/Q2fuZiIe6f
ipNtG+tQc4FapTixp1xiSxuDslXC6NxZEAHvTWMlvxLd4AOlMVESQPPKmKzjVi7u
WV443tP+jr+vldzsPQixXgJDSPyD3G3nMrJ+4ufrsQKBgQDvntNYkGtP4FTK+Wmz
jLYDI4aoVTcBhbDW7wenc71lYOPbBbew+1drOyd+vBoQsr/ItM3WZDP5J3/MO7qe
7OTNJ+Kkj815PtfaCM1IfEvY22pxuDXn8Fb4iOyLsddWL1pbJRjoL20EpNTYJdn3
SiDpBLC46zaANz9xd+ySCJv6hQKBgQDgmtZhaYEQGL8k+/PDsyHSb4fA9J3xachK
6hM1ixQn+by3xUjYt3Y4ht0oOC/70lj0JfTp5KEFhZk9jmwip82BeI+JkR3res+m
SZ/kmzynG7YZYpJ3jWPHcnV8+LOCi4SkgGaQHreUTxMtwQkE7rs6cIIOzBNWuFfd
leBJtInCHwKBgGjdgC6tHVmammEt39VlCi67eG3oxSbUZDzb5OSioUthqLYsfWRl
yq8x9yneliWipI3omoBt39T1NVei+BwfHk6uWuCb0ldyajKQUY6cXvErrRzRej3k
D5u7CJJmJRAhrxBeXtUWFEbJACEMB6TSey6fD9wNjA92njxBOHX8cI6lAoGAG8bq
Zmeu33fAA+no7rXzo9vJNTLLabTEYYdrUr7dgkgfb7bFWI/v3fPH3BZ+0Kzl9WPQ
UzDEPTOVjQhVFUAdaTqovcGlqp6omY8XaCVOrff+YEtRg9mHkn30S71SLf3lLJb4
mDBEUeIppAnwfJytqP+LBht09M+dhjjn4RWjx88CgYEA7L9EM+wF/1vruhnhFHc9
mNud6mSwcX+eQu6w/kWYviDkNlR1+QVoUVIQQubWkRC2WRzMp3tDXce+vBxSZmmw
bD1d32yMiJ/DMkw9bZ76190d+fhuNVCR+HBxeiNHzaHfdfwmt7kgrhdDgIoRqOZ8
SQTmU6EAoGDIOJDba3Ws66M=
-----END PRIVATE KEY-----
欢迎使用微信支付!
附件中的三份文件(证书pkcs12格式、证书pem格式、证书密钥pem格式),为接口中强制要求时需携带的证书文件。
证书属于敏感信息,请妥善保管不要泄露和被他人复制。
不同开发语言下的证书格式不同,以下为说明指引:
证书pkcs12格式(apiclient_cert.p12)
包含了私钥信息的证书文件,为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
部分安全性要求较高的API需要使用该证书来确认您的调用身份
windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户号(如:1900006031)
证书pem格式(apiclient_cert.pem)
从apiclient_cert.p12中导出证书部分的文件,为pem格式,请妥善保管不要泄漏和被他人复制
部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
您也可以使用openssl命令来自己导出:openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
证书密钥pem格式(apiclient_key.pem)
从apiclient_cert.p12中导出密钥部分的文件,为pem格式
部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
您也可以使用openssl命令来自己导出:openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
备注说明:
由于绝大部分操作系统已内置了微信支付服务器证书的根CA证书, 2018年3月6日后, 不再提供CA证书文件(rootca.pem)下载
\ No newline at end of file
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCefZbdsT6RiaCRqWKKIi4rWrntio3oX1RbCFSGHI3o2jS34Aew0QwBDDftdPS6ohgMRksIykoTTmXE8/1xgLc43Ed1kAQ2AHUkTdIRzhI3Sp5Ac6sD9B/Ys3Adb05PRvfCEcqDlRVjsLYCeFFpi9djZev97ojmKSajJ3kS7OnmuQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA6NLHoZOiPT0wgnfg0nRl3CqcyNGWDBoCDkJ5Cw/AHt5IAEQ1
R81w+5vBcLxGCttz4Qapcbpy+ck9zYiiVtOjInhS14tbgJad9jCTWm8+ejShVp/M
k9Xe1irORrxbj9YJ3L3BbYr5K3wTuAMd43Wp+7Ia7LpplmGSvOZumTRYRyFQgSs6
Vfv0x4fRQI4/JdUp+sX3DUUns0kXy8ggoI/B6kUYS6+Th+YWjcztdliJtRMb9sM5
BIJGWuGUNCDo93+UNyTxrEI8cTczfxqlzKRZSoadHa4xJF3TBKrgm4D5fZNF/ZEs
WmfsC7qalc0x0sHuPBnXTKM97d4t0WosTJkvAQIDAQABAoIBABT6Fr/9Vf8IAhSj
OeekUqAfW8BxN8Bv4HMJ9K91NBVj6B9UBevp++3Dhw6B/BqS0rI54C7twlm0ksOv
tZa2m0pqBmbCuNQRXfqWPlSF1N58WvP70loYiSsJMMwpQOOpAHr5wtF8lb4gAAPS
jhEWIyJZFflxwz0oHek0ps7Za0G/N+cFLZAdju9OXoO3mQMvuP8AQ7qT3A3sGJP4
d6K5YzMZSNT2SrwLR18VUpaFIDkCLp4XW5LZ7SJP5Ps2OoAPGawDA8g5OFC3z3J2
lZvT9BlOhkETimhwkXjuJV68RD+YmMulIxU5Q+erljACImfP43r6aOgIs7mezm2R
bSvQXmUCgYEA7N6GuphLIOV8tOfmDpCWKgmsArTVD2t/wLa4yYpffN57gz9NZ/oa
LsOIrl62MRmybWoVa/WlP9d3cNbS5NsyJeispKftMqzdiWi2d78X358GtgebxpzG
2s+e4k4pWvVSPW98YcqBn0xa0RWVtfREyyQ6ZJCxOMxShCgPKWXJZc0CgYEA+6CZ
9ctoRWGXXGC3VRYbwVEWtu3g40cTUILX7ZA1weXilE+9pr5BgmOPqm9i16GMjTKe
92rn6H2VBm5o9nlLX1KR2IiY3YEZ77QgQuOGNrJrk9GXRGOVoR4553ACaqzD/d5N
NTMYGSLlUMvu2K74S7Y1tTMfle7wKw9M0utA+gUCgYEAjENZVLVKB7jdF+MagBVu
VoZTrWaXpAHsLJoG4pFl6fN1AEtD8wZO6tIu5dJ/4KNu3Qusk7lqmVtmBxOu3oZO
M9SMJxSpiRCEPxIaut4VrP3mY3Qt8nZz6q53T1spcgtDH84cwWvBRitYu+ckOBLl
icVyLorf5tpXIpr2H3V+xSECgYBu9PPPGiHhrlYTSyaso3IbvckZYy3uqrHOp9PV
kujRlrBiHAOSGoVCnOqGClX4pekXfkHw8jhPIclsK5WnUfc1knBznlBiJIKuW6x6
MmBFkEm1xg9A/fTGNlDsSE0YgxRtxvAezGgM9YFPLo4lCIq+wBtQyrlb4SAQrM+A
lnJxjQKBgA9YtJU5xpIR9KkKqqyCZINi+XmAwffh6XoT0e8DgOHXHnc8GgODCasL
wtCqmARfdnSy8UE2NSdHHPJUVx299t6wL0VLv11MEZqKu8mJwCIiAdR5YsHbaKTp
H+qprpac3lhMgEh25H93mxjZBxaRSjLzy2+n6XQtr2vYt5sdztVQ
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6NLHoZOiPT0wgnfg0nRl
3CqcyNGWDBoCDkJ5Cw/AHt5IAEQ1R81w+5vBcLxGCttz4Qapcbpy+ck9zYiiVtOj
InhS14tbgJad9jCTWm8+ejShVp/Mk9Xe1irORrxbj9YJ3L3BbYr5K3wTuAMd43Wp
+7Ia7LpplmGSvOZumTRYRyFQgSs6Vfv0x4fRQI4/JdUp+sX3DUUns0kXy8ggoI/B
6kUYS6+Th+YWjcztdliJtRMb9sM5BIJGWuGUNCDo93+UNyTxrEI8cTczfxqlzKRZ
SoadHa4xJF3TBKrgm4D5fZNF/ZEsWmfsC7qalc0x0sHuPBnXTKM97d4t0WosTJkv
AQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFROPf3SA7LPmGcNioy4u1ub+tSR9bNhwYc1vdWhCp6Q3AjNSdXQNy3nTUFxtehmmFXTd2nHoY1ogApvecL+6Uks4ExakQTv20UUbXoRZsAUW3QU018+ljqwkB+DcxWViwiXdCBIMvsNSHIDIxx/PyX1HO3Ok6iB3bhQkrm7zlhQIDAQAB
-----END PUBLIC KEY-----
...@@ -26,7 +26,6 @@ class Pay(models.Model): ...@@ -26,7 +26,6 @@ class Pay(models.Model):
cert_serial_no=models.CharField(_('商户证书序列号'),max_length=100,blank=True,null=True) cert_serial_no=models.CharField(_('商户证书序列号'),max_length=100,blank=True,null=True)
cert_path=models.CharField(_('证书地址'),max_length=200) cert_path=models.CharField(_('证书地址'),max_length=200)
pay_id=models.CharField(_('商户号'),max_length=100) pay_id=models.CharField(_('商户号'),max_length=100)
remark=models.CharField(_('备注'),max_length=200,blank=True,null=True) remark=models.CharField(_('备注'),max_length=200,blank=True,null=True)
comp_abbr=models.CharField(_('公司缩写'),max_length=100,blank=True,null=True) comp_abbr=models.CharField(_('公司缩写'),max_length=100,blank=True,null=True)
send_hb_method = models.SmallIntegerField(_('发放类型'),blank=True,null=True) send_hb_method = models.SmallIntegerField(_('发放类型'),blank=True,null=True)
...@@ -37,7 +36,8 @@ class Pay(models.Model): ...@@ -37,7 +36,8 @@ class Pay(models.Model):
pay_platform_pn=models.CharField(_('支付平台项目编码'),max_length=50,blank=True,null=True) pay_platform_pn=models.CharField(_('支付平台项目编码'),max_length=50,blank=True,null=True)
aes_key=models.CharField(_('aes密码'),max_length=50,blank=True,null=True) aes_key=models.CharField(_('aes密码'),max_length=50,blank=True,null=True)
aes_iv=models.CharField(_('aes偏移值'),max_length=50,blank=True,null=True) aes_iv=models.CharField(_('aes偏移值'),max_length=50,blank=True,null=True)
public_key_id=models.CharField(_('公钥id'),max_length=500,blank=True,null=True)
public_key=models.CharField(_('公钥'),max_length=500,blank=True,null=True)
class Meta: class Meta:
verbose_name = _('微信商户平台') verbose_name = _('微信商户平台')
......
差异被折叠。
#橙券支付 #中数科支付
#接口文档 https://doc.apipost.net/docs/detail/34ff33e7bce7000?target_id=ef551d7ba901a
import hashlib import hashlib
import datetime import datetime
...@@ -8,46 +9,173 @@ import urllib.request ...@@ -8,46 +9,173 @@ import urllib.request
import urllib.parse import urllib.parse
import random import random
import base64 import base64
import os
from Crypto.Cipher import AES from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad from Crypto.Util.Padding import unpad
domain='' from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from wx.models import *
env = 'prod'
domainMap={
'dev':'http://ywymtest-api.azhiyun.cn',
'prod':'https://ywym-api.qidianpw.com'
}
domain = domainMap[env]
class ZSKPay: class ZSKPay:
def __init__(self, appid, k, aes_key='', aes_iv=''): def __init__(self, appid, taxId, ymId, ymKey, cert):
self.MAX_ENCRYPTION_SIZE = 117 #214
self.appid = appid self.appid = appid
self.k =k self.domain = domain
self.aes_key = aes_key self.taxId = taxId
self.aes_iv = aes_iv self.ymId = ymId
self.ymKey = ymKey
# 计算签名 self.cert = cert
def generate_sign(self,data):
return '' def encrypt_data(self, data):
encrypted_chunks = []
def http_post(self,data, type, url): current_directory = os.getcwd()
timestamp = int(round(time.time() * 1000)) with open(self.cert + "public_key.txt", "rb") as public_file:
data['timestamp'] = timestamp public_key_content = public_file.read()
data['ym-id'] = self.appid
if type: public_key_loaded = serialization.load_pem_public_key(
data['type'] = type public_key_content,
sign = self.generate_sign(data) backend=default_backend()
data['ym-key'] = sign )
data = json.dumps(data)
data = bytes(data,"utf8") # 将数据分块
headers={'Content-Type':'application/json'} for i in range(0, len(data), self.MAX_ENCRYPTION_SIZE):
request = urllib.request.Request(domain+url, data, headers) chunk = data[i:i + self.MAX_ENCRYPTION_SIZE]
res = urllib.request.urlopen(request).read().decode('utf-8')
return json.loads(res) try:
# 使用公钥加密内容
def transfer(self): ciphertext = public_key_loaded.encrypt(
data = { chunk,
padding.PKCS1v15()
)
encrypted_chunks.append(ciphertext)
except Exception as e:
print("加密块失败:", e)
# 将所有加密后的块连接在一起
resp = b''.join(encrypted_chunks)
return base64.b64encode(resp).decode('utf-8')
def decrypt_data(self, data):
current_directory = os.getcwd()
with open(current_directory+"/wx/cert/zsk/resp/private_key.txt", "rb") as public_file:
private_key_content = public_file.read()
# 加载私钥
private_key_loaded = serialization.load_pem_private_key(
private_key_content,
password=None,
backend=default_backend()
)
# 解密
data = json.jmson.loads(data)
plaintext = private_key_loaded.decrypt(
base64.b64decode(data),
padding.PKCS1v15()
)
return plaintext.decode('utf-8')
def http_post(self, data={}, url=''):
data = json.dumps(data).encode('utf-8')
# 加密数据
data = self.encrypt_data(data)
# print("加密后数据:", type(data), data)
headers = {
'Content-Type': 'application/json',
'ym-id':self.ymId,
'ym-key':self.ymKey
} }
return self.http_post_form(data, '', '')
request = urllib.request.Request(self.domain + url, bytes(json.dumps({'data': data}), "utf8"), headers, method='POST')
# 发送请求并获取响应
try:
response = urllib.request.urlopen(request)
# 读取响应体
res_body = response.read().decode('utf-8')
return json.loads(res_body)
except urllib.error.HTTPError as e:
print("HTTP错误:", e.code, e.read().decode())
except urllib.error.URLError as e:
print("网络错误:", e.reason)
#转账
def transfer(self,data):
if not data['transferNo'] or not data['transferAmount'] or not data['transferRemark'] or not data['openid'] :
raise ValueError("transferDetailList 必传")
company_id = data.get('company_id','')
batchNo = data.get('transferNo', self.generate_batchNo())
batchName = data.get('batchName','活动批次')
batchRemark = data.get('batchRemark','无')
transferDetailList = []
transferDetailList.append(data)
handle_data = {
"taxId": self.taxId,
"batchNo": batchNo,
"appid": self.appid,
"batchName": batchName,
"batchRemark": batchRemark,
"totalAmount": 0,
"totalNum": 0, #转账总笔数
"transferSceneId": "", #转账场景ID
"notifyUrl": "", #回调地址
#转账明细列表
"transferDetailList": transferDetailList
# [
# {
# "transferNo": "tj_consumer_winner_001", //商家明细单号
# "transferAmount": 30, //转账金额单位为“分”
# "transferRemark": "红包", //转账备注,【转账备注】 单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
# "openid": "oCZuC5RiJ8RId4qacC0inhy74vRc", //【收款用户openid】商户appid下,某用户的openid
# "userName": "
# }
# ]
}
for item in transferDetailList:#计算总金额和总笔数
# if not item.get('transferNo') or not item.get('transferAmount') or not item.get('transferRemark') or not item.get('openid'):
# raise ValueError("缺少转账参数")
handle_data['totalAmount'] += item['transferAmount']
handle_data['totalNum'] += 1
# print('加密前数据----:',handle_data)
body = self.http_post(data=handle_data,url='/wx-pay/transfer')
print('resp body', body)
# if body and body.get('code', '') == 200:
return body
#转账信息查询
def tranfer_info(self,data={}):
if not data.get('batchNo') or data.get('batch',''):
raise ValueError("缺少参数")
encrypt_body = self.http_post(data=data,url='/wx-pay/transfer-info')
decrypted_body = self.decrypt_data(encrypt_body['data'])
# print('解密后的查询数据',decrypted_body)
return json.loads(decrypted_body)
# 生成订单号 # 生成订单号
def generate_order_number(): def generate_batchNo(self):
timestamp = int(time.time()) timestamp = int(time.time())
random_number = random.randint(1000, 9999) random_number = random.randint(1000, 9999)
order_number = str(timestamp) + str(random_number) batchNo ='tj'+ str(timestamp) + str(random_number)
return order_number return batchNo
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论