先说说智慧门店会员联通ERP,这个功能就是实现商家的会员在手机淘宝上开卡成为商家的会员,会员身份信息与商家自有ERP打通一体。开卡渠道一般分为两种,1.顾客扫描淘宝智慧门店的门店二维码,二维码对于ERP来说是带有门店信息2.就是会员自主搜索或打开开卡链接进行开卡活动,这个操作没有门店信息传入ERP。
废话少说,先见如下需求调整:
看到这个需求一开始是郁闷的,因为以前遇到过类似的需求都是开发改,从字面上看,仿佛需要改线上的代码。我们不妨分析一下内容,看是不是有更简洁的方法靠我们自己来实现。只要按照客户的要求实现功能即可,不管它手段多卑劣。
1.卡号规则,虽然比较多内容,但是我们可以确认就是 固定字符+to_char(sysdate,’YYDDMM’)+流水(使用for循环实现流水)
2.默认开卡类型,即默认传值
3.开卡店仓和手淘开卡店仓,实际上这两个字段和店仓表就是主外键关系。在传值时候可以仿照给开卡店仓传值的方法,来给手淘开卡店仓传值,关于扫码开卡或自选开卡,对于线下而言就是:’扫码门店’字段是否为空,我们可以使用这个字段进行验证,通俗来说,我用一下两张图就能解释开卡的这种逻辑
4.因为都是通过手机淘宝开卡,我们就默认传值:’Y’,或者更合理的方式,在where条件后面判断来源,传’Y’。
5.关于绑卡。逻辑与开卡类似,其实就是在第三步上进行改动,将insert改为update
我们整理一下,其实都是可以从线下脚本调整实现,大致列为下面几类:
传门店值>新会员即insert,老会员即update>固定值传固定字符>卡号流水使用for循环实现递增。我还是用下面两个图表达这种绑卡会员身份的逻辑
思路有了,环境咱们也有了,咱们动手实践。先来第一步,卡号规则,难点在于流水号生成如何递增,先确定流水号,则有初始值。要将初始值存于表中,还要将递增后的值也更新进去。
在we_os表中设置流水卡号初始值为1。新增字段
alter table we_os add card_no NUMBER(10);
update we_os set card_no=1;
commit;
cardnolength := length(v_cardno);--获取流水号的长度2018/08/21 author xiaowei
if cardnolength <> 5 then --流水号初始值为0,长度为1
while (5-cardnolength) >0 loop -- 判断流水号如果低于5位,就执行循环
v_cardno := 0||v_cardno; --每次循环都在流水号上加0,即直到为00001
cardnolength := cardnolength +1; --每次循环,都将卡号长度值加1
end loop;
end if; --循环结束,此时card_no变更为00001_cardno := cardprefix ||to_char(sysdate,'yymmdd')|| v_cardno; --卡号规则2018/08/22
--卡号=TM+180822+00001 即TM18082200001
update we_os set card_no = v_cardno+1 where appid=p_appid;--在每生成一张会员卡,card_no就加1,实现流水号递增
现在json参数进行测试
返回0,执行成功,现在我们看下卡号生成结果
因为设置初始值为0,第一个卡号就是0结尾,卡号按照需求生成成功。
现在开始实现开卡门店与手淘门店传值。
判断传入的开卡门店并赋值给开卡门店和手淘开卡门店
IF P_OPENCARDSTORE_CODE IS NOT NULL THEN--如果门店参数不为空
SELECT c.ID INTO P_OPENCARDSTORE_ID FROM C_STORE C WHERE C.CODE= P_OPENCARDSTORE_CODE; --将参数传给手淘开卡门店
ELSE --如果为空,即业务上理解为未扫门店码
SELECT W.c_Store_Id INTO P_OPENCARDSTORE_ID FROM c_client_vip W WHERE W.Id=p_c_vip_id;--将这个会员的手淘开卡门店设置为默认门店
END IF;--给手淘开卡门店P_OPENCARDSTORE_ID 赋值
update c_client_vip cc set cc.st_opencardstore_id=P_OPENCARDSTORE_ID,cc.wisdom_store='Y' where cc.mobil=p_phonenum;--将手淘开卡门店字段传给VIP档案,将是否天猫会员变更为'Y'
但是,新的问题来了。五位流水号,如果开卡人数达到99999个,第100000个人卡号就是’TM180824100000 ‘流水号达到6位数了。所以再次与客户确认卡号规则。
最终确定每天凌晨,五位流水号还原,那么就可以满足:’日期+5位流水号’为唯一数值
还原动作分两步:
1.设定还原数据的脚本,以存储过程最佳
2.设置job任务调用数据库存储过程
直接来个简单粗暴的,不传参的存储过程
CREATE OR REPLACE PROCEDURE UPDATE_WEOS_CARDNUMBER IS
BEGIN
UPDATE WE_OS SET CARD_NO=0,MODIFIEDDATE=SYSDATE WHERE APPID='20180820115920';--每次被调用时候,把调用时间更新到we_os表中
COMMIT;
END;
测试一下!
测试结果成功!
脚本设定好了,接下来就是job定时器设置,直接贴上代码
declare JOBAUTO PLS_INTEGER;
<!--pls_integer类型也是数字类型,但和number类型不同,number可以存储实数,而pls_integer只能存储-2147483647到+2147483647之间的整数,如果使用pls_integer类型时发生溢出,系统将会报错。--!>
BEGIN
sys.DBMS_JOB.submit(job=>JOBAUTO,
what=>'UPDATE_WEOS_CARDNUMBER;',--调用的存储过程名
NEXT_DATE=>TO_DATE('25-08-2018 00:00:00','DD-MM-YYYY HH24:MI:SS'),--下次执行时间
interval=>'trunc(sysdate+1)') ;--执行周期每24H一次
commit;
end;
至此在每天凌晨对流水号清零任务已启动。
改代码测试过程中遇到疑难问题一:
老的会员绑卡时候,按照要求,如果传参,保留原开卡门店,参数传给手淘开卡店仓,但是实际测试中发现,传参同时都更新了开卡门店和手淘开卡门店。
代码无限检查ing。。。。
将传参打印出来,确定是不是传参问题
jor.put('errMessage', '本次扫码传入门店参数是'||P_OPENCARDSTORE_ID);
确定不是参数问题,。。。。几近崩溃
继续查!终于发现坑爹的问题,见如下代码
--判断门店是以线上为准
if isonlinestore='Y' and v_storeid is not null then
update c_client_vip c set c.c_store_id=v_storeid,c.c_customer_id=v_customerid where c.id=p_c_vip_id;
else
if c_openstorecode is null and v_storeid is not null then --线下是空,就已线上为准
update c_client_vip c set c.c_store_id=v_storeid,c.c_customer_id=v_customerid where c.id=p_c_vip_id;
else
p_openstorecode:=c_openstorecode;
end IF;
以上代码是说,如果传入参数为空,门店以线上为准,但是这个会员的线下开卡门店有,那么就将参数更新进开卡门店字段。再来看看我们的测试请求参数,果然是以线上门店为准
ok,再次简单粗暴,确认以上代码不影响其它业务场景和流程后,赶紧注释注释注释掉!~
问题二:
设置会员表的手淘开卡门店与门店档案表主外键关联,无法创建主外键约束
alter table C_CLIENT_VIP
add constraint FK_STC_STORE foreign key (ST_OPENCARDSTORE_ID)
references C_STORE (ID) on delete set null;--设置主外键关系名FK_STC_STORE 当删除门店数据后,就将ST_OPENCARDSTORE_ID设置为null(空)
百度,也查不出来,真的坑爹。。。继续无限查问题中。。。。。
能改的都改了,找了很久很久,OK,原来会员表的ST_OPENCARDSTORE_ID有部分数据外键值为0,排查发现0不在主键表的ID中,所以创建主外键时候,0无法在主键表的ID中找到,将ST_OPENCARDSTORE_ID设置为null
update C_CLIENT_VIP set ST_OPENCARDSTORE_ID=null where id=19088
再次执行,成功了!