1.根据业务设计表结构
2.然后看原型,写出复制SQL的查询结构
3.最后在开始填满业务JAVA代码
表示积分的单价
create sequence SEQ_TEST_JF_ID start with 1 increment by 1;
create table TEST_JF_PRICE
(
ID NUMBER,
JF_TYPE VARCHAR2(1),
JF_PRICE NUMBER(9, 2)
)
/
comment on table TEST_JF_PRICE is '积分价格'
/
comment on column TEST_JF_PRICE.ID is '主键'
/
comment on column TEST_JF_PRICE.JF_TYPE is '积分类型'
/
comment on column TEST_JF_PRICE.JF_PRICE is '价格'
/
create table TEST_JF_PACKAGE
(
ID NUMBER not null
constraint TEST_JS_PACKAGE_PK
primary key,
PACKAGE_ID VARCHAR2(32),
JF_TYPE VARCHAR2(1),
COST_NUM NUMBER
)
/
comment on table TEST_JF_PACKAGE is '积分套餐'
/
comment on column TEST_JF_PACKAGE.ID is '主键'
/
comment on column TEST_JF_PACKAGE.PACKAGE_ID is '包id'
/
comment on column TEST_JF_PACKAGE.JF_TYPE is '积分类型'
/
comment on column TEST_JF_PACKAGE.COST_NUM is '消耗数量'
/
记录用户积分的变动情况
create table TEST_JF
(
ID NUMBER not null
constraint TEST_JF_PK
primary key,
USER_ID VARCHAR2(32),
DATA_TYPE NUMBER,
OPERATION_NUM NUMBER,
EXPIRED_DATE TIMESTAMP(0),
TYPE0_ID NUMBER,
JF_TYPE VARCHAR2(1),
OPERATION_ORDER VARCHAR2(32)
)
/
comment on table TEST_JF is '积分流水表'
/
comment on column TEST_JF.ID is '主键'
/
comment on column TEST_JF.USER_ID is '用户id'
/
comment on column TEST_JF.DATA_TYPE is '流水类型(1:积分购买,2:积分使用,3:积分退还,4:积分过期)'
/
comment on column TEST_JF.OPERATION_NUM is '操作数量'
/
comment on column TEST_JF.EXPIRED_DATE is '过期日期'
/
comment on column TEST_JF.TYPE0_ID is '类型为0的总量id'
/
comment on column TEST_JF.JF_TYPE is ' 积分类型'
/
comment on column TEST_JF.OPERATION_ORDER is '操作单号'
/
CREATE OR REPLACE VIEW VIEW_TEST_JF_USER AS
select t1.*, nvl(t2.use_num,0) as use_num ,
nvl(t3.return_num,0) as return_num,
nvl(t4.expired_num,0) as expired_num,
t1.buy_num-nvl(t2.use_num,0)+nvl(t3.return_num,0)-nvl(t4.expired_num,0) as own_num,
P.JF_PRICE
from (
select JF_TYPE,USER_ID,sum(OPERATION_NUM) as buy_num from TEST_JF jf where jf.DATA_TYPE=1 group by JF_TYPE,USER_ID
) t1
left join (
select JF_TYPE,USER_ID,sum(OPERATION_NUM) as use_num from TEST_JF jf where jf.DATA_TYPE=2 group by JF_TYPE,USER_ID
) t2 on t1.USER_ID=t2.USER_ID and t1.JF_TYPE=t2.JF_TYPE
left join (
select JF_TYPE,USER_ID,sum(OPERATION_NUM) as return_num from TEST_JF jf where jf.DATA_TYPE=3 group by JF_TYPE,USER_ID
) t3 on t1.USER_ID=t3.USER_ID and t1.JF_TYPE=t3.JF_TYPE
left join (
select JF_TYPE,USER_ID,sum(OPERATION_NUM) as expired_num from TEST_JF jf where jf.DATA_TYPE=4 group by JF_TYPE,USER_ID
) t4 on t1.USER_ID=t4.USER_ID and t1.JF_TYPE=t3.JF_TYPE
LEFT JOIN TEST_JF_PRICE P on P.JF_TYPE= t1.JF_TYPE
ORDER BY T1.USER_ID,T1.JF_TYPE
;
用户按照价格购买积分。
用户按照类型用积分兑换套餐。
对应类型积分不够用时候,高价的积分可以抵扣低价的积分。
找到单个套餐消耗的积分, 乘以数量算出总量
SELECT PACKAGE_ID,P.JF_TYPE,COST_NUM,JF_PRICE FROM TEST_JF_PACKAGE P
LEFT JOIN TEST_JF_PRICE R ON P.JF_TYPE=R.JF_TYPE
WHERE P.PACKAGE_ID='P1';
找到这个用户能消耗的积分
SELECT vu.* FROM VIEW_TEST_JF_USER vu
WHERE vu.USER_ID='U1' and JF_PRICE >= 200.22 ORDER BY JF_PRICE;
遍历循环相减,根据高价抵扣低价的规则,算出每个类型积分扣除数量
找到最快过期的,计算消耗数量然后插入 类型为2的数据
SELECT * FROM TEST_JF where USER_ID='U1' and JF_TYPE='C' order by EXPIRED_DATE ;
String jfType="C";
String userId="U1";
int costNum=3;
LambdaQueryWrapper<TestJf> queryWrapper = new LambdaQueryWrapper<TestJf>();
queryWrapper.eq(TestJf::getJfType,jfType);
queryWrapper.eq(TestJf::getUserId,userId);
queryWrapper.eq(TestJf::getDataType,DataType.BUY_1);
// 过期加上时间判断就行
queryWrapper.orderByAsc(TestJf::getExpiredDate);
List<TestJf> list = testJfService.list(queryWrapper);
String operationId=IdUtil.fastSimpleUUID();
for (TestJf testJf : list) {
Integer operationNum = testJf.getOperationNum();
int use2Num=operationNum;
if(costNum>=operationNum){
costNum=costNum-operationNum;
}else {
use2Num=costNum;
}
TestJf use2 = new TestJf();
use2.setUserId(userId);
use2.setJfType(jfType);
use2.setDataType(DataType.USE_2);
use2.setOperationNum(use2Num);
use2.setType0Id(testJf.getId());
use2.setOperationOrder(operationId);
testJfService.save(use2);
}
String operationId="7543e6eb514948f5b6bfdcf56e10e204";
int returnNum=2;
String jfType="C";
String userId="U1";
TestJf use2 = new TestJf();
use2.setUserId(userId);
use2.setJfType(jfType);
use2.setDataType(DataType.RETURN_3);
use2.setOperationNum(returnNum);
use2.setOperationOrder(operationId);
testJfService.save(use2);