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

View File

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

View File

@ -236,7 +236,7 @@
<tr>
<td>下单通路<span class="is-required">*</span></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="1">总代</option>
<option value="2">直签</option>
@ -269,7 +269,7 @@
class="form-control" readonly placeholder="选择后带入" required></td>
<td>进货商类型<span class="is-required">*</span></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">
<option value="">选择后带入</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
@ -357,6 +357,55 @@
var hardwareProjectProductInfoList = []
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() {
initProjectList()
let data = {
@ -430,6 +479,18 @@
$.modal.alertWarning("项目编号为必填");
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());
return
}

View File

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

View File

@ -1,8 +1,12 @@
package com.ruoyi.sip.controller;
import java.util.Collections;
import java.util.List;
import cn.hutool.core.collection.CollUtil;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -35,6 +39,8 @@ public class ProjectInfoController extends BaseController
@Autowired
private IProjectInfoService projectInfoService;
@Autowired
private IProjectOrderInfoService orderInfoService;
@RequiresPermissions("sip:project:view")
@GetMapping()
@ -129,6 +135,10 @@ public class ProjectInfoController extends BaseController
{
ProjectInfo projectInfo = projectInfoService.selectProjectInfoById(id);
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";
}
@GetMapping("/query/{id}")

View File

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

View File

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

View File

@ -1,6 +1,8 @@
package com.ruoyi.sip.service;
import java.util.List;
import java.util.function.Supplier;
import com.ruoyi.sip.domain.ProjectProductInfo;
/**
@ -61,5 +63,5 @@ public interface IProjectProductInfoService
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 PROJECT_STAGE_DICT_TYPE = "project_stage";
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) {
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();

View File

@ -161,7 +161,10 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService {
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) {
List<ProjectOrderInfo> projectOrderInfos = projectOrderInfoMapper.selectProjectOrderInfoList(projectOrderInfo);
if (CollUtil.isEmpty(projectOrderInfos)) {

View File

@ -6,6 +6,9 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
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 cn.hutool.core.collection.CollUtil;
@ -32,6 +35,8 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
private ProjectProductInfoMapper projectProductInfoMapper;
@Autowired
private IProductInfoService productInfoService;
//折上折
private static final String FOLD_ON_FOLD = "0.988";
/**
*
@ -105,7 +110,7 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
}
@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<ProductInfo> productInfos = productInfoService.selectProductInfoByCodeList(codeList);
@ -119,18 +124,22 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
if (stringJoiner.length() > 0) {
throw new ServiceException(StringUtils.format("产品编码[{}]在产品库中未找到,请确认后重试", stringJoiner.toString()));
}
// for (ProjectProductInfo info : list) {
// //计算价格 防止前端价格计算错误
// if (info.getGuidanceDiscount() != null && info.getDiscount() == null) {
// info.setDiscount(info.getGuidanceDiscount());
// }
// if (info.getCataloguePrice() != null && info.getDiscount() != null) {
// info.setPrice(info.getCataloguePrice().multiply(info.getDiscount()).setScale(2, RoundingMode.HALF_UP));
// }
// if (info.getPrice() != null && info.getQuantity() != null) {
// info.setAllPrice(info.getPrice().multiply(new BigDecimal(info.getQuantity())).setScale(2, RoundingMode.HALF_UP));
// }
// }
for (ProjectProductInfo info : list) {
//计算价格 防止前端价格计算错误
if (info.getGuidanceDiscount() != null && info.getDiscount() == null) {
info.setDiscount(info.getGuidanceDiscount());
}
if (info.getCataloguePrice() != null && info.getDiscount() != null) {
info.setPrice(info.getCataloguePrice().multiply(info.getDiscount()).setScale(2, RoundingMode.HALF_UP));
}
if (info.getPrice() != null && info.getQuantity() != null) {
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()));
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}
</select>
<select id="selectProjectOrderInfoByProjectId" resultType="com.ruoyi.sip.domain.ProjectOrderInfo">
<include refid="selectProjectOrderInfoVo"/>
<include refid="selectProjectOrderInfoRelationVo"/>
where t1.project_id in (
<foreach item="item" collection="list" separator=",">
#{item}