feat(sip): 实现直签国代/省代时自动应用折上折

- 新增折上折计算逻辑,适用于直签且客户等级为国代或省代的情况
- 在项目管理、订单管理和产品列表等页面中实现折上折的计算和显示- 新增 foldOnFold 方法判断是否应用折上折
- 修改 saveBatch 方法以支持折上折计算
master
chenhao 2025-07-01 17:13:10 +08:00
parent b8c47fc032
commit ec62b4a4a7
12 changed files with 156 additions and 28 deletions

View File

@ -95,6 +95,7 @@
<!-- JS 函数引用或内联 --> <!-- JS 函数引用或内联 -->
<script th:inline="javascript"> /*<![CDATA[*/ <script th:inline="javascript"> /*<![CDATA[*/
const updatePriceProductList=['8813A3YA','8813A3YB','8813A7U4','8813A7U2'] const updatePriceProductList=['8813A3YA','8813A3YB','8813A7U4','8813A7U2']
const FOLD_ON_FOLD = 0.988;
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
// 初始化删除逻辑等 // 初始化删除逻辑等
$('.productTable .delRow').on('click', function () { $('.productTable .delRow').on('click', function () {
@ -125,6 +126,7 @@
}) })
let shipmentAmount = $('#shipmentAmount'); let shipmentAmount = $('#shipmentAmount');
if (shipmentAmount){ if (shipmentAmount){
allPrice = Number(allPrice).toFixed(2);
shipmentAmount.val(allPrice) shipmentAmount.val(allPrice)
$('#displayshipmentAmount').val(formatAmountNumber(allPrice)) $('#displayshipmentAmount').val(formatAmountNumber(allPrice))
} }
@ -274,14 +276,27 @@
let priceVal = currentTd.find('.'+name).val() let priceVal = currentTd.find('.'+name).val()
$(that).val(priceVal) $(that).val(priceVal)
} }
function getFlag() {
let level = $('#level');
let orderChannel = $('#orderChannel');
if (!level.length || !orderChannel.length){
return [[${foldOnFold}]];
}
return level && orderChannel && orderChannel.val() === '2' && (level.val() === '01' || level.val() === '02');
}
function initPrice() { function initPrice() {
$('.productTable .quantity').on('input', function () { $('.productTable .quantity').on('input', function () {
let num = $(this).val() let num = $(this).val()
let priceVal = $(this).parent().parent().find('.price').val() let priceVal = $(this).parent().parent().find('.price').val()
let cateVal = $(this).parent().parent().find('.cataloguePrice').val() let cateVal = $(this).parent().parent().find('.cataloguePrice').val()
if (priceVal && num) { if (priceVal && num) {
$(this).parent().parent().find('.allPrice').val((num * priceVal).toFixed(2)) let allPrice = num * priceVal;
$(this).parent().parent().find('.allPrice-formmat').val(formatAmountNumber((num * priceVal).toFixed(2))) if (getFlag()) {
allPrice *= FOLD_ON_FOLD
}
$(this).parent().parent().find('.allPrice').val(allPrice.toFixed(2))
$(this).parent().parent().find('.allPrice-formmat').val(formatAmountNumber(allPrice.toFixed(2)))
} }
if (cateVal && num) { if (cateVal && num) {
@ -335,7 +350,13 @@
let price = $(this).parent().parent().parent().find('.price').val() let price = $(this).parent().parent().parent().find('.price').val()
$(this).parent().parent().parent().find('.price-formmat').val(formatAmountNumber(price)) $(this).parent().parent().parent().find('.price-formmat').val(formatAmountNumber(price))
let num = $(this).parent().parent().parent().find('.quantity').val() let num = $(this).parent().parent().parent().find('.quantity').val()
$(this).parent().parent().parent().find('.allPrice').val((price * num).toFixed(2))
let allPriceNumber = price * num
if (getFlag()) {
allPriceNumber *= FOLD_ON_FOLD
}
$(this).parent().parent().parent().find('.allPrice').val(allPriceNumber.toFixed(2))
let allPrice = $(this).parent().parent().parent().find('.allPrice').val() let allPrice = $(this).parent().parent().parent().find('.allPrice').val()
$(this).parent().parent().parent().find('.allPrice-formmat').val(formatAmountNumber(allPrice)) $(this).parent().parent().parent().find('.allPrice-formmat').val(formatAmountNumber(allPrice))
setOrderPriceData() setOrderPriceData()
@ -344,9 +365,12 @@
let val = $(this).val() let val = $(this).val()
let num = $(this).parent().parent().find('.quantity').val() let num = $(this).parent().parent().find('.quantity').val()
$(this).parent().parent().find('.price').val(val) $(this).parent().parent().find('.price').val(val)
let allPriceNumber = val * num
$(this).parent().parent().find('.allPrice').val((val * num).toFixed(2)) if (getFlag()) {
$(this).parent().parent().find('.allPrice-formmat').val(formatAmountNumber((val * num).toFixed(2))) allPriceNumber *= FOLD_ON_FOLD
}
$(this).parent().parent().find('.allPrice').val(allPriceNumber.toFixed(2))
$(this).parent().parent().find('.allPrice-formmat').val(formatAmountNumber(allPriceNumber.toFixed(2)))
let cataloguePrice = $(this).parent().parent().find('.cataloguePrice').val() let cataloguePrice = $(this).parent().parent().find('.cataloguePrice').val()
let discount = (val*1.0000/cataloguePrice).toFixed(4); let discount = (val*1.0000/cataloguePrice).toFixed(4);

View File

@ -102,12 +102,12 @@
}, },
{ {
field: 'orderCode', field: 'orderCode',
title: '关联合同编号', title: '合同编号',
}, },
{ {
field: 'orderName', field: 'orderName',
title: '关联合同名称', title: '合同名称',
formatter:function (value,row){ formatter:function (value,row){
return `<span style="color: #1686d8;cursor:pointer;" onclick="openOrderDeail('${row.orderId}')">${value}</span>` return `<span style="color: #1686d8;cursor:pointer;" onclick="openOrderDeail('${row.orderId}')">${value}</span>`
}, },

View File

@ -236,7 +236,7 @@
<tr> <tr>
<td>下单通路<span class="is-required">*</span></td> <td>下单通路<span class="is-required">*</span></td>
<td > <td >
<select name="orderChannel" class="form-control" required th:field="*{orderChannel}"> <select name="orderChannel" id="orderChannel" class="form-control" required th:field="*{orderChannel}">
<option value="">请选择</option> <option value="">请选择</option>
<option value="1">总代</option> <option value="1">总代</option>
<option value="2">直签</option> <option value="2">直签</option>
@ -269,7 +269,7 @@
class="form-control" readonly placeholder="选择后带入" required></td> class="form-control" readonly placeholder="选择后带入" required></td>
<td>进货商类型<span class="is-required">*</span></td> <td>进货商类型<span class="is-required">*</span></td>
<td> <td>
<select name="level" class="form-control" readonly :placeholder="选择后带入" th:field="*{level}" <select name="level" id="level" class="form-control" readonly :placeholder="选择后带入" th:field="*{level}"
th:with="type=${@dict.getType('identify_level')}" style="pointer-events: none"> th:with="type=${@dict.getType('identify_level')}" style="pointer-events: none">
<option value="">选择后带入</option> <option value="">选择后带入</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" <option th:each="dict : ${type}" th:text="${dict.dictLabel}"
@ -357,6 +357,55 @@
var hardwareProjectProductInfoList = [] var hardwareProjectProductInfoList = []
var maintenanceProjectProductInfoList = [] var maintenanceProjectProductInfoList = []
// function changePrice(){
// changeAllPrice().then(()=>{
//
// setOrderPriceData()
// console.log('修改总价完成')
// })
// }
// function changeAllPrice() {
// console.log('产品总价修改开始')
// return new Promise (resolve => {
// if (getFlag()) {
// $('#productTable tbody').find('tr').find('.allPrice').each(function (index) {
// let data = parseFloat($(this).val());
// $(this).val((FOLD_ON_FOLD*data).toFixed(2))
// $(this).parent().find('.allPrice-formmat').val(formatAmountNumber($(this).val()))
//
// })
// $('#productTable2 tbody').find('tr').find('.allPrice').each(function (index) {
// let data = parseFloat($(this).val());
// $(this).val((FOLD_ON_FOLD*data).toFixed(2))
// $(this).parent().find('.allPrice-formmat').val(formatAmountNumber($(this).val()))
// })
// $('#productTable3 tbody').find('tr').find('.allPrice').each(function (index) {
// let data = parseFloat($(this).val());
// $(this).val((FOLD_ON_FOLD*data).toFixed(2))
// $(this).parent().find('.allPrice-formmat').val(formatAmountNumber($(this).val()))
// })
// }
// else {
// $('#productTable tbody').find('tr').find('.allPrice').each(function (index) {
// let data = parseFloat($(this).val());
// $(this).val((data/FOLD_ON_FOLD).toFixed(2))
// $(this).parent().find('.allPrice-formmat').val(formatAmountNumber($(this).val()))
// })
// $('#productTable2 tbody').find('tr').find('.allPrice').each(function (index) {
// let data = parseFloat($(this).val());
// $(this).val((data/FOLD_ON_FOLD).toFixed(2))
// $(this).parent().find('.allPrice-formmat').val(formatAmountNumber($(this).val()))
// })
// $('#productTable3 tbody').find('tr').find('.allPrice').each(function (index) {
// let data = parseFloat($(this).val());
// $(this).val((data/FOLD_ON_FOLD).toFixed(2))
// $(this).parent().find('.allPrice-formmat').val(formatAmountNumber($(this).val()))
// })
// }
// console.log('产品总价修改完成')
// resolve()
// })
// }
function initProductList() { function initProductList() {
initProjectList() initProjectList()
let data = { let data = {
@ -430,6 +479,18 @@
$.modal.alertWarning("项目编号为必填"); $.modal.alertWarning("项目编号为必填");
return; return;
} }
let flag = true;
$('.discount').each(function () {
if (parseFloat($(this).val()) > 1) {
flag = false;
return false; // 退出 each 循环
}
});
if (!flag) {
$.modal.alertWarning("折扣不能大于100%");
return;
}
$.operate.save(prefix + "/edit", $('#form-order-edit').serialize()); $.operate.save(prefix + "/edit", $('#form-order-edit').serialize());
return return
} }

View File

@ -112,6 +112,7 @@
title: '创建时间' title: '创建时间'
}, },
{ {
width: '200',
title: '操作', title: '操作',
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {

View File

@ -1,8 +1,12 @@
package com.ruoyi.sip.controller; package com.ruoyi.sip.controller;
import java.util.Collections;
import java.util.List; import java.util.List;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.service.IProjectOrderInfoService;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -35,6 +39,8 @@ public class ProjectInfoController extends BaseController
@Autowired @Autowired
private IProjectInfoService projectInfoService; private IProjectInfoService projectInfoService;
@Autowired
private IProjectOrderInfoService orderInfoService;
@RequiresPermissions("sip:project:view") @RequiresPermissions("sip:project:view")
@GetMapping() @GetMapping()
@ -129,6 +135,10 @@ public class ProjectInfoController extends BaseController
{ {
ProjectInfo projectInfo = projectInfoService.selectProjectInfoById(id); ProjectInfo projectInfo = projectInfoService.selectProjectInfoById(id);
mmap.put("projectInfo", projectInfo); mmap.put("projectInfo", projectInfo);
List<ProjectOrderInfo> orderInfoList = orderInfoService.selectProjectOrderInfoByProjectId(Collections.singletonList(id));
ProjectOrderInfo orderInfo = CollUtil.isNotEmpty(orderInfoList) ? orderInfoList.get(0) : null;
mmap.put("orderInfo", orderInfo);
mmap.put("foldOnFold", orderInfoService.foldOnFold(orderInfo));
return prefix + "/edit"; return prefix + "/edit";
} }
@GetMapping("/query/{id}") @GetMapping("/query/{id}")

View File

@ -122,6 +122,7 @@ public class ProjectOrderInfoController extends BaseController
ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoById(id); ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoById(id);
mmap.put("projectOrderInfo", projectOrderInfo); mmap.put("projectOrderInfo", projectOrderInfo);
mmap.put("user", ShiroUtils.getSysUser()); mmap.put("user", ShiroUtils.getSysUser());
mmap.put("foldOnFold", projectOrderInfoService.foldOnFold(projectOrderInfo));
return prefix + "/edit"; return prefix + "/edit";
} }

View File

@ -76,4 +76,5 @@ public interface IProjectOrderInfoService
List<StatisticsDetailDto> listHomePageData(HomepageQueryDto dto); List<StatisticsDetailDto> listHomePageData(HomepageQueryDto dto);
ProjectOrderInfo selectProjectOrderInfoByOrderCode(String orderCode); ProjectOrderInfo selectProjectOrderInfoByOrderCode(String orderCode);
Boolean foldOnFold(ProjectOrderInfo info);
} }

View File

@ -1,6 +1,8 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import com.ruoyi.sip.domain.ProjectProductInfo; import com.ruoyi.sip.domain.ProjectProductInfo;
/** /**
@ -61,5 +63,5 @@ public interface IProjectProductInfoService
List<ProjectProductInfo> selectProjectProductInfoListByProjectId(List<Long> projectId); List<ProjectProductInfo> selectProjectProductInfoListByProjectId(List<Long> projectId);
void saveBatch(List<ProjectProductInfo> addList); void saveBatch(List<ProjectProductInfo> addList, Supplier<Boolean> supplier);
} }

View File

@ -75,7 +75,6 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
public static final String BG_TYPE_DICT_TYPE = "bg_type"; public static final String BG_TYPE_DICT_TYPE = "bg_type";
public static final String PROJECT_STAGE_DICT_TYPE = "project_stage"; public static final String PROJECT_STAGE_DICT_TYPE = "project_stage";
public static final String OPERATE_INSTITUTION_DICT_TYPE = "operate_institution"; public static final String OPERATE_INSTITUTION_DICT_TYPE = "operate_institution";
private FutureValidatorForOffsetTime futureValidatorForOffsetTime;
/** /**
* *
@ -191,7 +190,14 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
for (ProjectProductInfo projectProductInfo : projectProductInfoList) { for (ProjectProductInfo projectProductInfo : projectProductInfoList) {
projectProductInfo.setProjectId(projectInfo1.getId()); projectProductInfo.setProjectId(projectInfo1.getId());
} }
productInfoService.saveBatch(projectProductInfoList); productInfoService.saveBatch(projectProductInfoList, () -> {
List<ProjectOrderInfo> projectOrderInfos = orderInfoService.selectProjectOrderInfoByProjectId(Collections.singletonList(projectInfo1.getId()));
if (CollUtil.isEmpty(projectOrderInfos)) {
return false;
}
ProjectOrderInfo projectOrderInfo = projectOrderInfos.get(0);
return orderInfoService.foldOnFold(projectOrderInfo);
});
} }
//插入变更记录信息 //插入变更记录信息
List<ProjectWorkProgress> projectWorkProgressList = projectInfo1.getProjectWorkProgressList(); List<ProjectWorkProgress> projectWorkProgressList = projectInfo1.getProjectWorkProgressList();

View File

@ -161,7 +161,10 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService {
projectProductInfo.setProjectId(projectId); projectProductInfo.setProjectId(projectId);
} }
} }
productInfoService.saveBatch(projectProductInfoList); productInfoService.saveBatch(projectProductInfoList, () -> {
//直签+国代/省代时这里的总价自动再做1.2%的折扣
return foldOnFold(projectOrderInfo);
});
} }
} }
@ -324,6 +327,16 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService {
} }
@Override
public Boolean foldOnFold(ProjectOrderInfo projectOrderInfo) {
if (projectOrderInfo == null) {
return false;
}
//直签+国代/省代时这里的总价自动再做1.2%的折扣
return "2".equals(projectOrderInfo.getOrderChannel()) && ("01".equals(projectOrderInfo.getLevel()) || "02".equals(projectOrderInfo.getLevel()));
}
private List<ProjectOrderInfo> fetchProjectInfos(ProjectOrderInfo projectOrderInfo) { private List<ProjectOrderInfo> fetchProjectInfos(ProjectOrderInfo projectOrderInfo) {
List<ProjectOrderInfo> projectOrderInfos = projectOrderInfoMapper.selectProjectOrderInfoList(projectOrderInfo); List<ProjectOrderInfo> projectOrderInfos = projectOrderInfoMapper.selectProjectOrderInfoList(projectOrderInfo);
if (CollUtil.isEmpty(projectOrderInfos)) { if (CollUtil.isEmpty(projectOrderInfos)) {

View File

@ -6,6 +6,9 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.StringJoiner; import java.util.StringJoiner;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
@ -32,6 +35,8 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
private ProjectProductInfoMapper projectProductInfoMapper; private ProjectProductInfoMapper projectProductInfoMapper;
@Autowired @Autowired
private IProductInfoService productInfoService; private IProductInfoService productInfoService;
//折上折
private static final String FOLD_ON_FOLD = "0.988";
/** /**
* *
@ -105,7 +110,7 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
} }
@Override @Override
public void saveBatch(List<ProjectProductInfo> list) { public void saveBatch(List<ProjectProductInfo> list, Supplier<Boolean> supplier) {
//校验数据是否在产品库中 //校验数据是否在产品库中
List<String> codeList = list.stream().map(ProjectProductInfo::getProductBomCode).distinct().collect(Collectors.toList()); List<String> codeList = list.stream().map(ProjectProductInfo::getProductBomCode).distinct().collect(Collectors.toList());
List<ProductInfo> productInfos = productInfoService.selectProductInfoByCodeList(codeList); List<ProductInfo> productInfos = productInfoService.selectProductInfoByCodeList(codeList);
@ -119,18 +124,22 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
if (stringJoiner.length() > 0) { if (stringJoiner.length() > 0) {
throw new ServiceException(StringUtils.format("产品编码[{}]在产品库中未找到,请确认后重试", stringJoiner.toString())); throw new ServiceException(StringUtils.format("产品编码[{}]在产品库中未找到,请确认后重试", stringJoiner.toString()));
} }
// for (ProjectProductInfo info : list) { for (ProjectProductInfo info : list) {
// //计算价格 防止前端价格计算错误 //计算价格 防止前端价格计算错误
// if (info.getGuidanceDiscount() != null && info.getDiscount() == null) { if (info.getGuidanceDiscount() != null && info.getDiscount() == null) {
// info.setDiscount(info.getGuidanceDiscount()); info.setDiscount(info.getGuidanceDiscount());
// } }
// if (info.getCataloguePrice() != null && info.getDiscount() != null) { if (info.getCataloguePrice() != null && info.getDiscount() != null) {
// info.setPrice(info.getCataloguePrice().multiply(info.getDiscount()).setScale(2, RoundingMode.HALF_UP)); info.setPrice(info.getCataloguePrice().multiply(info.getDiscount()).setScale(2, RoundingMode.HALF_UP));
// } }
// if (info.getPrice() != null && info.getQuantity() != null) { if (info.getPrice() != null && info.getQuantity() != null) {
// info.setAllPrice(info.getPrice().multiply(new BigDecimal(info.getQuantity())).setScale(2, RoundingMode.HALF_UP)); BigDecimal allPrice = info.getPrice().multiply(new BigDecimal(info.getQuantity()));
// } if (supplier.get()) {
// } allPrice = allPrice.multiply(new BigDecimal(FOLD_ON_FOLD));
}
info.setAllPrice(allPrice.setScale(2, RoundingMode.HALF_UP));
}
}
List<ProjectProductInfo> projectProductInfos = projectProductInfoMapper.selectProjectProductInfoListByProjectId(Collections.singletonList(list.get(0).getProjectId())); List<ProjectProductInfo> projectProductInfos = projectProductInfoMapper.selectProjectProductInfoListByProjectId(Collections.singletonList(list.get(0).getProjectId()));
Set<Long> idSet = list.stream().map(ProjectProductInfo::getId).collect(Collectors.toSet()); Set<Long> idSet = list.stream().map(ProjectProductInfo::getId).collect(Collectors.toSet());

View File

@ -142,7 +142,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where t1.id = #{id} where t1.id = #{id}
</select> </select>
<select id="selectProjectOrderInfoByProjectId" resultType="com.ruoyi.sip.domain.ProjectOrderInfo"> <select id="selectProjectOrderInfoByProjectId" resultType="com.ruoyi.sip.domain.ProjectOrderInfo">
<include refid="selectProjectOrderInfoVo"/> <include refid="selectProjectOrderInfoRelationVo"/>
where t1.project_id in ( where t1.project_id in (
<foreach item="item" collection="list" separator=","> <foreach item="item" collection="list" separator=",">
#{item} #{item}