6 files added
8 files modified
New file |
| | |
| | | package cc.mrbird.febs.mall.controller; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.mall.service.ICommonService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | @Slf4j |
| | | @Validated |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping(value = "/admin/common") |
| | | public class AdminCommonController { |
| | | |
| | | @Autowired |
| | | private ICommonService commonService; |
| | | |
| | | @GetMapping(value = "/findDicByType/{type}") |
| | | public FebsResponse findDicByType(@PathVariable("type") String type) { |
| | | return new FebsResponse().success().data(commonService.findDataDicByType(type)); |
| | | } |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.mall.controller; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.mall.service.ISystemService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.Map; |
| | | |
| | | @Slf4j |
| | | @Validated |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping(value = "/admin/system") |
| | | public class AdminSystemController { |
| | | |
| | | @Autowired |
| | | private ISystemService systemService; |
| | | |
| | | @PostMapping(value = "/bonusSystemSetting") |
| | | public FebsResponse bonusSystemSetting(@RequestBody Map<String, Object> map) { |
| | | systemService.bonusSystemSetting(map); |
| | | return new FebsResponse().success().message("设置成功"); |
| | | } |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.mall.controller; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsConstant; |
| | | import cc.mrbird.febs.common.utils.FebsUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Controller; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | |
| | | |
| | | @Controller("mallSystemView") |
| | | @RequestMapping(FebsConstant.VIEW_PREFIX + "modules/system") |
| | | @RequiredArgsConstructor |
| | | public class ViewSystemController { |
| | | |
| | | @GetMapping("profitSetting") |
| | | public String profitSetting() { |
| | | return FebsUtil.view("modules/system/profitSetting"); |
| | | } |
| | | } |
| | |
| | | private BigDecimal price; |
| | | |
| | | private BigDecimal amount; |
| | | |
| | | private BigDecimal costPrice; |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import java.util.List; |
| | | |
| | | public interface DataDictionaryCustomMapper extends BaseMapper<DataDictionaryCustom> { |
| | |
| | | List<AdminAgentLevelOptionTreeVo> getAgentLevelOption(); |
| | | |
| | | AdminRankAwardUpdateInfoVo getRankAwardUpdateInfoById(@Param("id")long id); |
| | | |
| | | int updateDicValueByTypeAndCode(@Param("type") String type, @Param("code") String code, @Param("value") String value); |
| | | } |
| | |
| | | |
| | | BigDecimal selectTotalAmountForDate(@Param("date") Date date, @Param("member") Long memberId); |
| | | |
| | | BigDecimal selectTotalAmountUnCostForDate(@Param("date") Date date, @Param("member") Long memberId, @Param("type") String type); |
| | | |
| | | MallOrderInfo selectByOrderNo(@Param("orderNo") String orderNo); |
| | | } |
| | |
| | | package cc.mrbird.febs.mall.service; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2022-05-10 |
| | |
| | | /** |
| | | * 代理分红 |
| | | */ |
| | | void agentProfit(); |
| | | void agentProfit(Date date); |
| | | |
| | | /** |
| | | * 排名分红 |
New file |
| | |
| | | package cc.mrbird.febs.mall.service; |
| | | |
| | | import java.util.Map; |
| | | |
| | | public interface ISystemService { |
| | | |
| | | void bonusSystemSetting(Map<String, Object> map); |
| | | } |
| | |
| | | import cc.mrbird.febs.mall.service.IMemberProfitService; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.date.DateField; |
| | | import cn.hutool.core.date.DateUnit; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | /** |
| | | * 直推20%,隔代收益为直推奖励金额的30%,a_b_c_d,d购买1000套餐,c得200,b得200*30%=60元,a得60*30%=18元。。。 |
| | | * 以此类推,结算到一元为止。 |
| | | * |
| | | * @param orderId |
| | | */ |
| | | @Override |
| | | public void dynamicProfit(Long orderId) { |
| | | log.info("######直推奖励, 订单ID:{}######", orderId); |
| | | MallOrderInfo orderInfo = mallOrderInfoMapper.selectById(orderId); |
| | | if (orderInfo.getOrderType() == 2) { |
| | | log.info("积分订单无返利"); |
| | | return; |
| | | } |
| | | |
| | | MallMember member = mallMemberMapper.selectById(orderInfo.getMemberId()); |
| | | |
| | | if (StrUtil.isBlank(member.getReferrerId())) { |
| | |
| | | String parent = member.getReferrerId(); |
| | | List<MallOrderItem> items = mallOrderInfoMapper.getMallOrderItemByOrderId(orderId); |
| | | for (MallOrderItem item : items) { |
| | | BigDecimal dynamicProfit = item.getAmount().multiply(BigDecimal.valueOf(item.getCnt())).divide(new BigDecimal(dic.getValue()), 2, RoundingMode.HALF_UP); |
| | | // 减去成本后算收益 |
| | | BigDecimal amount = item.getPrice().subtract(item.getCostPrice()).multiply(BigDecimal.valueOf(item.getCnt())); |
| | | |
| | | BigDecimal dynamicProfit = amount.divide(new BigDecimal(dic.getValue()), 2, RoundingMode.HALF_UP); |
| | | |
| | | List<String> parents = StrUtil.split(member.getReferrerIds(), ','); |
| | | List<MallMember> members = mallMemberMapper.selectByInviteIds(parents); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void agentProfit() { |
| | | public void agentProfit(Date profitDate) { |
| | | log.info("#####==代理分红==#####"); |
| | | Date profitDate = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, -1); |
| | | BigDecimal totalIncome = mallOrderInfoMapper.selectTotalAmountForDate(profitDate, null); |
| | | if (profitDate == null) { |
| | | profitDate = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, -1); |
| | | } |
| | | BigDecimal totalIncome = mallOrderInfoMapper.selectTotalAmountUnCostForDate(profitDate, null, "D"); |
| | | |
| | | |
| | | DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.AGENT_BONUS.getType(), DataDictionaryEnum.AGENT_BONUS.getCode()); |
| | | BigDecimal profit = totalIncome.divide(new BigDecimal(dic.getValue()),2, RoundingMode.HALF_UP); |
| | | BigDecimal profit = totalIncome.divide(new BigDecimal(dic.getValue()), 2, RoundingMode.HALF_UP); |
| | | BigDecimal preProfit = profit.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); |
| | | |
| | | List<MallMember> agentMembers = mallMemberMapper.selectByIdAndNoLevel(null, AgentLevelEnum.FIRST_LEVEL.name()); |
| | |
| | | for (MallMember agentMember : agentMembers) { |
| | | DataDictionaryCustom agentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.AGENT_LEVEL_REQUIRE, agentMember.getLevel()); |
| | | |
| | | // TODO |
| | | if (agentDic == null) { |
| | | continue; |
| | | } |
| | | |
| | | JSONObject jsonObject = JSONObject.parseObject(agentDic.getValue()); |
| | | BigDecimal profitProp = jsonObject.getBigDecimal("profitProp"); |
| | | BigDecimal income = preProfit.multiply(profitProp); |
| | | |
| | | try { |
| | | walletService.reduce(income, agentMember.getId(), "score"); |
| | | } catch (Exception e) { |
| | | log.info("直推奖励异常:{}, {}", income, agentMember.getId()); |
| | | continue; |
| | | } |
| | | walletService.add(income, agentMember.getId(), "commission"); |
| | | |
| | | moneyFlowService.addMoneyFlow(agentMember.getId(), income, MoneyFlowTypeEnum.AGENT_BONUS.getValue(), null, FlowTypeEnum.COMMISSION.getValue()); |
| | | moneyFlowService.addMoneyFlow(agentMember.getId(), income.negate(), MoneyFlowTypeEnum.AGENT_BONUS.getValue(), null, FlowTypeEnum.SCORE.getValue()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void rankProfit() { |
| | | log.info("######==排名分红==####"); |
| | | |
| | | } |
| | | |
| | | public static void main(String[] args) { |
New file |
| | |
| | | package cc.mrbird.febs.mall.service.impl; |
| | | |
| | | import cc.mrbird.febs.mall.entity.DataDictionaryCustom; |
| | | import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; |
| | | import cc.mrbird.febs.mall.service.ICommonService; |
| | | import cc.mrbird.febs.mall.service.ISystemService; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author wzy |
| | | * @date 2022-05-19 |
| | | **/ |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class SystemServiceImpl implements ISystemService { |
| | | |
| | | private final DataDictionaryCustomMapper dictionaryCustomMapper; |
| | | private final ICommonService commonService; |
| | | |
| | | @Override |
| | | public void bonusSystemSetting(Map<String, Object> map) { |
| | | for (Map.Entry<String, Object> entry : map.entrySet()) { |
| | | if (entry.getValue() instanceof String) { |
| | | dictionaryCustomMapper.updateDicValueByTypeAndCode(null, entry.getKey(), (String) entry.getValue()); |
| | | } else { |
| | | List<LinkedHashMap<String, Object>> value = (List<LinkedHashMap<String, Object>>) entry.getValue(); |
| | | |
| | | for (LinkedHashMap<String, Object> dic : value) { |
| | | String type = (String) dic.get("type"); |
| | | String code = (String) dic.get("code"); |
| | | String dataValue = (String) dic.get("value"); |
| | | dictionaryCustomMapper.updateDicValueByTypeAndCode(type, code, dataValue); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | select a.* from data_dictionary_custom a |
| | | where a.id = #{id} |
| | | </select> |
| | | |
| | | <update id="updateDicValueByTypeAndCode"> |
| | | update data_dictionary_custom |
| | | set value=#{value} |
| | | <where> |
| | | 1=1 |
| | | <if test="code != null and code != ''"> |
| | | and code = #{code} |
| | | </if> |
| | | <if test="type != null and type != ''"> |
| | | and type = #{type} |
| | | </if> |
| | | </where> |
| | | </update> |
| | | </mapper> |
| | |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="selectTotalAmountUnCostForDate" resultType="java.math.BigDecimal"> |
| | | select IFNULL(sum(IFNULL(b.amount,0) - IFNULL(b.cost_price*b.cnt, 0)),0) |
| | | from mall_order_info a |
| | | inner join mall_order_item b on a.id=b.order_id |
| | | where status = 4 |
| | | <if test="member != null"> |
| | | and member_id=#{memberId} |
| | | </if> |
| | | <if test="date != null and type == 'D'"> |
| | | and date_format(a.receving_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d') |
| | | </if> |
| | | <if test="date != null and type == 'M'"> |
| | | and date_format(a.receving_time, '%Y-%m') = date_format(#{date}, '%Y-%m') |
| | | </if> |
| | | <if test="date != null and type == 'Y'"> |
| | | and date_format(a.receving_time, '%Y') = date_format(#{date}, '%Y') |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="selectByOrderNo" resultType="cc.mrbird.febs.mall.entity.MallOrderInfo"> |
| | | select * from mall_order_info where order_no=#{orderNo} |
| | | </select> |
| | |
| | | }) |
| | | }; |
| | | |
| | | self.postForJson = function (url, params, success) { |
| | | if (params) { |
| | | params.invalidate_ie_cache = new Date(); |
| | | } |
| | | $.post(url, params, function (r) { |
| | | resolveResponse(r, success); |
| | | }, "json") |
| | | }; |
| | | |
| | | // 文件下载 |
| | | self.download = function (url, params, fileName) { |
| | | self.view.loadBar.start(); |
New file |
| | |
| | | <div class="layui-fluid layui-anim febs-anim" id="profit-setting" lay-title="收益设置"> |
| | | <div class="layui-row layui-col-space8 febs-container"> |
| | | <form class="layui-form" action="" lay-filter="profit-setting-form"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-body"> |
| | | <div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief"> |
| | | <ul class="layui-tab-title"> |
| | | <li class="layui-this">分红设置</li> |
| | | <li>代理分红</li> |
| | | <li>排名分红</li> |
| | | </ul> |
| | | <div class="layui-tab-content"> |
| | | <div class="layui-tab-item layui-show" id="bonus-global-setting"> |
| | | </div> |
| | | <div class="layui-tab-item"> |
| | | <table id="agentBonus" lay-filter="agentBonus"></table> |
| | | </div> |
| | | <div class="layui-tab-item"> |
| | | <table id="rankBonus" lay-filter="rankBonus"></table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-card-footer"> |
| | | <button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="profit-setting-form-submit" id="submit">保存</button> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | |
| | | <!-- <div class="layui-form-item febs-hide">--> |
| | | <!-- <button class="layui-btn" lay-submit="" lay-filter="profit-setting-form-submit" id="submit-form"></button>--> |
| | | <!-- <button type="reset" class="layui-btn" id="reset"></button>--> |
| | | <!-- </div>--> |
| | | </div> |
| | | </div> |
| | | <style> |
| | | .layui-form-label { |
| | | width: 120px; |
| | | } |
| | | |
| | | .layui-form-item .layui-input-block { |
| | | margin-left: 150px; |
| | | } |
| | | |
| | | .layui-table-form .layui-form-item { |
| | | margin-bottom: 20px !important; |
| | | } |
| | | </style> |
| | | <script type="text/html" id="toolbar"> |
| | | <div class="layui-btn-container"> |
| | | <button class="layui-btn layui-btn-danger layui-btn-sm" type="button" lay-event="delSku">删除</button> |
| | | </div> |
| | | </script> |
| | | <script type="text/html" id="bonusSystem"> |
| | | {{# layui.each(d, function(index, item){ }} |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label ">{{item.description}}:</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="{{item.code}}" lay-verify="number" value="{{item.value}}" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | {{# }) }} |
| | | </script> |
| | | <script data-th-inline="javascript" type="text/javascript"> |
| | | layui.use(['dropdown', 'jquery', 'validate', 'febs', 'form', 'eleTree', 'laytpl', 'table'], function () { |
| | | var $ = layui.jquery, |
| | | febs = layui.febs, |
| | | form = layui.form, |
| | | table = layui.table, |
| | | validate = layui.validate, |
| | | $view = $('#profit-setting') |
| | | , templateHtml = bonusSystem.innerHTML |
| | | , $bonusSystem = $("#bonus-global-setting") |
| | | , laytpl = layui.laytpl |
| | | , agentBonusArr |
| | | , rankBonusArr; |
| | | |
| | | form.verify(validate); |
| | | form.render(); |
| | | |
| | | table.render({ |
| | | elem: '#agentBonus' |
| | | ,cols: [[ //表头 |
| | | {field: 'description', title: '代理', edit:'text'} |
| | | ,{field: 'prop', title: '返利比例(%)', edit:'text'} |
| | | ,{field: 'achieve', title: '团队业绩(万元)', edit:'text'} |
| | | ,{field: 'type', title: '比例', edit:'text', hide:'true'} |
| | | ,{field: 'code', title: '比例', edit:'text', hide:'true'} |
| | | ]] |
| | | ,data: [] |
| | | }); |
| | | table.on('edit(agentBonus)', function(obj){ |
| | | var value = obj.value //得到修改后的值 |
| | | ,data = obj.data //得到所在行所有键值 |
| | | ,field = obj.field; //得到字段 |
| | | |
| | | for (let i = 0; i < agentBonusArr.length; i++) { |
| | | if (agentBonusArr[i].code === data.code) { |
| | | var valueData = {}; |
| | | valueData.teamIncome = data.achieve; |
| | | valueData.profitProp = data.prop |
| | | agentBonusArr[i].value = JSON.stringify(valueData); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | table.render({ |
| | | elem: '#rankBonus' |
| | | ,cols: [[ //表头 |
| | | {field: 'description', title: '排名'} |
| | | ,{field: 'value', title: '返利比例(%)', edit:'text'} |
| | | ,{field: 'type', title: '比例', edit:'text', hide:'true'} |
| | | ,{field: 'code', title: '比例', edit:'text', hide:'true'} |
| | | ]] |
| | | ,data: [] |
| | | }); |
| | | |
| | | table.on('edit(rankBonus)', function(obj){ |
| | | var value = obj.value //得到修改后的值 |
| | | ,data = obj.data //得到所在行所有键值 |
| | | ,field = obj.field; //得到字段 |
| | | |
| | | for (let i = 0; i < rankBonusArr.length; i++) { |
| | | if (rankBonusArr[i].code === data.code) { |
| | | rankBonusArr[i].value = value; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | dicDataReq("BONUS_TYPE"); |
| | | dicDataReq("AGENT_LEVEL_REQUIRE"); |
| | | dicDataReq("RANK_AWARD"); |
| | | function dicDataReq(type) { |
| | | $bonusSystem.empty(); |
| | | $.get(ctx + 'admin/common/findDicByType/' + type, function (r) { |
| | | if (r.code === 200) { |
| | | var data = r.data; |
| | | if ("BONUS_TYPE" == type) { |
| | | laytpl(templateHtml).render(data, function(html) { |
| | | $bonusSystem.append(html); |
| | | }) |
| | | } |
| | | |
| | | if ("AGENT_LEVEL_REQUIRE" == type) { |
| | | for (let i = 0; i < data.length; i++) { |
| | | data[i].prop = JSON.parse(data[i].value).profitProp; |
| | | data[i].achieve = JSON.parse(data[i].value).teamIncome; |
| | | } |
| | | agentBonusArr = data; |
| | | table.reload('agentBonus', { |
| | | data : data |
| | | }); |
| | | } |
| | | |
| | | if ("RANK_AWARD" == type) { |
| | | rankBonusArr = data; |
| | | table.reload('rankBonus', { |
| | | data : data |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | form.on('submit(profit-setting-form-submit)', function (data) { |
| | | data.field.agentBonus = agentBonusArr; |
| | | data.field.rankBonus = rankBonusArr; |
| | | $.ajax({ |
| | | 'url':ctx + 'admin/system/bonusSystemSetting', |
| | | 'type':'post', |
| | | 'dataType':'json', |
| | | 'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, |
| | | 'traditional': true, |
| | | 'data':JSON.stringify(data.field), |
| | | 'success':function (data) { |
| | | if (data.code == 200) { |
| | | febs.alert.success(data.message); |
| | | } |
| | | }, |
| | | 'error':function () { |
| | | febs.alert.warn('服务器繁忙'); |
| | | } |
| | | }) |
| | | return false; |
| | | }); |
| | | }); |
| | | </script> |