feat(sip): 新增项目税率临时表功能

- 添加项目税率临时表相关接口和服务
- 实现税率数据的保存、查询和应用逻辑
- 优化订单审批流程,支持税率修改
-调整产品信息表,增加税率字段
dev_1.0.0
chenhao 2025-09-19 15:19:41 +08:00
parent 6b4fd7e441
commit e240213b01
18 changed files with 801 additions and 55 deletions

View File

@ -29,6 +29,7 @@
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="all-price-column">总价(¥)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="all-price-discount-column hide-column">折后总价(¥)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="catalogue-all-price-column">目录总价(¥)</th>
<th style="min-width: 100px;width: 100px;max-width: 100px;" class="tax-rate-column">税率(%)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="remark-column">备注</th>
<th style="min-width: 60px;width: 60px;max-width: 60px;" class="del-row-column">操作</th>
</tr>
@ -58,6 +59,7 @@
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="all-price-column">总价(¥)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="all-price-discount-column hide-column">折后总价(¥)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="catalogue-all-price-column">目录总价(¥)</th>
<th style="min-width: 100px;width: 100px;max-width: 100px;" class="tax-rate-column">税率(%)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="remark-column">备注</th>
<th style="min-width: 60px;width: 60px;max-width: 60px;" class="del-row-column">操作</th>
</tr>
@ -87,6 +89,7 @@
<th style="min-width: 120px;width: 120px;max-width: 120px;" class=" all-price-column">总价(¥)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="all-price-discount-column hide-column">折后总价(¥)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="catalogue-all-price-column">目录总价(¥)</th>
<th style="min-width: 100px;width: 100px;max-width: 100px;" class="tax-rate-column">税率(%)</th>
<th style="min-width: 120px;width: 120px;max-width: 120px;" class="remark-column">备注</th>
<th style="min-width: 60px;width: 60px;max-width: 60px;" class="del-row-column">操作</th>
</tr>
@ -294,6 +297,7 @@
}
function generatedTr(index,data,length){
debugger
let flag=true
let productTypeParam=productType[index]
let queryParam=productTypeParam.type
@ -346,6 +350,9 @@
<input value="${data.catalogueAllPrice || ''}" name="${submitName}[${length}].catalogueAllPrice" type="hidden" class="form-control catalogueAllPrice" placeholder="自动计算" required readonly>
<input type="text" value="${data.catalogueAllPriceFormmat || ''}" class="form-control catalogueAllPrice-formmat" placeholder="自动计算" required readonly>
</td>
<td class="tax-rate-column">
<input value="${data.taxRate || '13'}" name="${submitName}[${length}].taxRate" type="text" class="form-control tax-rate" readonly>
</td>
<td class="remark-column"><input value="${data.remark || ''}" name="${submitName}[${length}].remark" type="text" class="form-control" ></td>
<td class="del-row-column"><span style="cursor:pointer;color: #ff5722" onclick="delProductRow(this)" class="delRow">删除</span></td>

View File

@ -604,11 +604,11 @@
if (orderChannel == '1') { // 总代
$paymentMethodSelect.append('<option value="1-1">全款支付,无需预付款</option>');
$paymentMethodSelect.append('<option value="1-2">全款支付,需单独备货生产,预付订单总货款30%</option>');
$paymentMethodSelect.append('<option value="1-2">全款支付,需单独备货生产,预付订单总货款百分比</option>');
} else if (orderChannel == '2') { // 直签
$paymentMethodSelect.append('<option value="2-1">全款支付</option>');
$paymentMethodSelect.append('<option value="2-2">全款支付,需单独备货生产,预付订单总货款30%</option>');
$paymentMethodSelect.append('<option value="2-3">商业汇票支付,预付订单总货款30%</option>');
$paymentMethodSelect.append('<option value="2-2">全款支付,需单独备货生产,预付订单总货款百分比</option>');
$paymentMethodSelect.append('<option value="2-3">商业汇票支付,预付订单总货款百分比</option>');
}
// Clear description and ratio when channel changes
$('#paymentDescription').val('');

View File

@ -370,12 +370,18 @@
<option value="">请选择</option>
<th:block th:if="${projectOrderInfo.orderChannel == '1'}">
<option value="1-1" th:selected="${projectOrderInfo.paymentMethod == '1-1'}">全款支付,无需预付款</option>
<option value="1-2" th:selected="${projectOrderInfo.paymentMethod == '1-2'}">全款支付需单独备货生产预付订单总货款30%</option>
<option value="1-2" th:selected="${projectOrderInfo.paymentMethod == '1-2'}">
全款支付,需单独备货生产,预付订单总货款百分比
</option>
</th:block>
<th:block th:if="${projectOrderInfo.orderChannel == '2'}">
<option value="2-1" th:selected="${projectOrderInfo.paymentMethod == '2-1'}">全款支付</option>
<option value="2-2" th:selected="${projectOrderInfo.paymentMethod == '2-2'}">全款支付需单独备货生产预付订单总货款30%</option>
<option value="2-3" th:selected="${projectOrderInfo.paymentMethod == '2-3'}">商业汇票支付预付订单总货款30%</option>
<option value="2-2" th:selected="${projectOrderInfo.paymentMethod == '2-2'}">
全款支付,需单独备货生产,预付订单总货款百分比
</option>
<option value="2-3" th:selected="${projectOrderInfo.paymentMethod == '2-3'}">
商业汇票支付,预付订单总货款百分比
</option>
</th:block>
</select>
</td>
@ -673,7 +679,7 @@
// }
// }
let data = [[${todo}]]
let {taxRateData, ...data} = [[${todo}]]
data.approveOpinion = value
data.approveStatus = 3
data.variables = {
@ -684,6 +690,19 @@
if( $('#actualPurchaseAmount').length>0){
data.variables.actualPurchaseAmount=$('#actualPurchaseAmount').val()
}
// 如果是商务审批,收集税率数据
const taskName = [[${todo.taskName}]];
if (taskName && taskName.startsWith('商务')) {
const taxRateList = collectTaxRateData();
if (taxRateList) {
for (let i = 0; i < taxRateList.length; i++) {
for (let key in taxRateList[i]) {
data['taxRateData[' + i + '].' + key] = taxRateList[i][key];
}
}
}
}
top.layer.close(index); // 关闭层
if ([[${todo.taskName == '公司领导'}]]) {
exportPdf(true)
@ -724,6 +743,19 @@
approveBtn: 0
}
// 如果是商务审批,收集税率数据
const taskName = [[${todo.taskName}]];
if (taskName && taskName.startsWith('商务')) {
const taxRateList = collectTaxRateData();
if (taxRateList) {
for (let i = 0; i < taxRateList.length; i++) {
for (let key in taxRateList[i]) {
data['taxRateData[' + i + '].' + key] = taxRateList[i][key];
}
}
}
}
top.layer.close(index); // 关闭层
if ([[${todo.taskName == '公司领导'}]]) {
exportPdf(true)
@ -1183,14 +1215,16 @@ ${
//判断是否总代
let flag = [[${projectOrderInfo.processTemplate == '1'}]]
let discountFold = [[${projectOrderInfo.discountFold}]]
console.log(discountFold)
let id = $('[name="projectId"]').val()
window.localStorage.setItem('getDetail', 1)
$.operate.get(ctx + `sip/project/query/${id}`, function (res) {
$('#productTable tbody').html('')
$('#productTable2 tbody').html('')
$('#productTable3 tbody').html('')
res.data.softwareProjectProductInfoList ? res.data.softwareProjectProductInfoList.forEach((ele) => {
let softwareProjectProductInfoList = [[${projectOrderInfo.softwareProjectProductInfoList}]]
let hardwareProjectProductInfoList = [[${projectOrderInfo.hardwareProjectProductInfoList}]]
let maintenanceProjectProductInfoList = [[${projectOrderInfo.maintenanceProjectProductInfoList}]]
softwareProjectProductInfoList ? softwareProjectProductInfoList.forEach((ele) => {
ele.allPriceDisCount = (ele.allPrice * discountFold).toFixed(2)
ele.allPriceDisCountFormat = formatAmountNumber(ele.allPriceDisCount)
@ -1204,7 +1238,7 @@ ${
ele.guidanceDiscountFormat = ele.guidanceDiscount ? (ele.guidanceDiscount * 100).toFixed(2) : ""
addProduct(ele)
}) : '';
res.data.hardwareProjectProductInfoList ? res.data.hardwareProjectProductInfoList.forEach((ele) => {
hardwareProjectProductInfoList ? hardwareProjectProductInfoList.forEach((ele) => {
ele.allPriceDisCount = (ele.allPrice * discountFold).toFixed(2)
ele.allPriceDisCountFormat = formatAmountNumber(ele.allPriceDisCount)
@ -1219,10 +1253,10 @@ ${
addProduct2(ele)
}) : '';
res.data.maintenanceProjectProductInfoList ? res.data.maintenanceProjectProductInfoList.forEach((ele) => {
maintenanceProjectProductInfoList ? maintenanceProjectProductInfoList.forEach((ele) => {
ele.allPriceDisCount = (ele.allPrice * discountFold).toFixed(2)
ele.allPriceDisCountFormat = formatAmountNumber(ele.allPriceDisCount)
ele.allPriceDisCount = (ele.allPrice * discountFold).toFixed(2)
ele.allPriceDisCountFormat = formatAmountNumber(ele.allPriceDisCount)
ele.cataloguePriceFormmat = ele.cataloguePrice ? formatAmountNumber(ele.cataloguePrice) : ""
ele.priceFormmat = ele.price ? formatAmountNumber(ele.price) : ""
@ -1255,7 +1289,9 @@ ${
}else{
$('.discount-text').text('现金折扣')
}
})
initTaxRateEditability();
// $.operate.get(ctx + `sip/project/query/${id}`, function (res) )
}
function downFile(filePath, fileName) {
@ -1341,6 +1377,89 @@ ${
}
}
// 控制税率列的可编辑性
function initTaxRateEditability() {
const taskName = [[${todo.taskName}]];
const isBusinessTask = taskName && taskName.startsWith('商务');
// 获取所有税率输入框
const taxRateInputs = document.querySelectorAll('.tax-rate');
taxRateInputs.forEach(function (input) {
if (isBusinessTask) {
// 如果是商务任务,允许编辑
input.removeAttribute('readonly');
input.removeAttribute('disabled');
input.style.backgroundColor = '#fff';
input.style.cursor = 'text';
} else {
// 否则保持只读
input.setAttribute('readonly', 'readonly');
}
});
}
// 收集税率数据
function collectTaxRateData() {
const taxRateData = [];
// 收集软件产品税率
$('#productTable tbody tr').each(function (index) {
const taxRateInput = $(this).find('.tax-rate');
if (taxRateInput.length > 0) {
const productId = $(this).find('input[name$=".id"]').val();
const productCode = $(this).find('input[name$=".productBomCode"]').val();
const taxRate = taxRateInput.val();
if (productId || taxRate) {
taxRateData.push({
productId: productId,
projectId: $('#projectId').val(),
taxRate: taxRate || '13'
});
}
}
});
// 收集终端产品税率
$('#productTable2 tbody tr').each(function (index) {
const taxRateInput = $(this).find('.tax-rate');
if (taxRateInput.length > 0) {
const productId = $(this).find('input[name$=".id"]').val();
const productCode = $(this).find('input[name$=".productBomCode"]').val();
const taxRate = taxRateInput.val();
if (productId || taxRate) {
taxRateData.push({
productId: productId,
projectId: $('#projectId').val(),
taxRate: taxRate || '13'
});
}
}
});
// 收集第三类产品税率
$('#productTable3 tbody tr').each(function (index) {
const taxRateInput = $(this).find('.tax-rate');
if (taxRateInput.length > 0) {
const productId = $(this).find('input[name$=".id"]').val();
const productCode = $(this).find('input[name$=".productBomCode"]').val();
const taxRate = taxRateInput.val();
if (productId || taxRate) {
taxRateData.push({
productId: productId,
projectId: $('#projectId').val(),
taxRate: taxRate || '13'
});
}
}
});
return taxRateData;
}
</script>
</body>

View File

@ -382,7 +382,7 @@
<tr>
<td>描述</td>
<td colspan="5">
<textarea name="paymentDescription" id="paymentDescription" class="form-control" rows="3"
<textarea name="paymentDescription" id="paymentDescription" class="form-control" rows="3" readonly
th:field="*{paymentDescription}"></textarea>
</td>
</tr>
@ -724,6 +724,10 @@
s:[{
n: '电子订单',
v: '0'
}, {
n: '纸质合同',
v: '1'
}]
}]:undefined)
@ -908,8 +912,16 @@
})
}
$('[name="orderChannel"]').on('change', updatePaymentOptions);
updatePaymentOptions();
$('[name="orderChannel"]').on('change', function() {
// 清空付款相关字段
$('#paymentMethod').val('').trigger('change');
$('#paymentRatio').val('').prop('readonly', false);
$('#paymentDescription').val('');
// 调用原有的更新付款选项函数
updatePaymentOptions(false);
});
updatePaymentOptions(true);
// Set payment method from database
var initialPaymentMethod = /*[[${projectOrderInfo.paymentMethod}]]*/ null;
if(initialPaymentMethod) {
@ -1363,7 +1375,7 @@
}
function updatePaymentOptions() {
function updatePaymentOptions(flag) {
var orderChannel = $('[name="orderChannel"]').val();
var $paymentMethodSelect = $('#paymentMethod');
var paymentMethod = /*[[${projectOrderInfo.paymentMethod}]]*/ null;
@ -1372,14 +1384,14 @@
if (orderChannel == '1') { // 总代
$paymentMethodSelect.append('<option value="1-1">全款支付,无需预付款</option>');
$paymentMethodSelect.append('<option value="1-2">全款支付,需单独备货生产,预付订单总货款30%</option>');
$paymentMethodSelect.append('<option value="1-2">全款支付,需单独备货生产,预付订单总货款百分比</option>');
} else if (orderChannel == '2') { // 直签
$paymentMethodSelect.append('<option value="2-1">全款支付</option>');
$paymentMethodSelect.append('<option value="2-2">全款支付,需单独备货生产,预付订单总货款30%</option>');
$paymentMethodSelect.append('<option value="2-3">商业汇票支付,预付订单总货款30%</option>');
$paymentMethodSelect.append('<option value="2-2">全款支付,需单独备货生产,预付订单总货款百分比</option>');
$paymentMethodSelect.append('<option value="2-3">商业汇票支付,预付订单总货款百分比</option>');
}
if (paymentMethod) {
if (paymentMethod &&flag) {
$paymentMethodSelect.val(paymentMethod);
}
}

View File

@ -24,6 +24,14 @@
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-2 control-label">制造商全称:</label>
<div class="col-sm-10">
<input name="vendorAddress" class="form-control" type="text"></input>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">联系人:</label>
@ -72,14 +80,6 @@
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-2 control-label">生产地址:</label>
<div class="col-sm-10">
<textarea rows="3" name="vendorAddress" class="form-control" type="text"></textarea>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />

View File

@ -25,6 +25,14 @@
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-2 control-label">制造商全称:</label>
<div class="col-sm-10">
<input name="vendorAddress" th:field="*{vendorAddress}" class="form-control" type="text"></input>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">联系人:</label>
@ -85,14 +93,7 @@
</div>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label class="col-sm-2 control-label">生产地址:</label>
<div class="col-sm-10">
<textarea rows="3" name="vendorAddress" th:field="*{vendorAddress}" class="form-control" type="text"></textarea>
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />

View File

@ -25,7 +25,7 @@
<input type="text" name="vendorName"/>
</li>
<li>
<label>生产地址</label>
<label>制造商全称</label>
<input type="text" name="vendorAddress"/>
</li>
<li>
@ -109,7 +109,7 @@
{
width: '600',
field: 'vendorAddress',
title: '生产地址'
title: '制造商全称'
},
{
width: '100',

View File

@ -9,6 +9,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.config.RuoYiConfig;
@ -22,10 +23,12 @@ import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.sip.domain.ProjectInfo;
import com.ruoyi.sip.domain.ProjectOrderFileLog;
import com.ruoyi.sip.domain.ProjectTaxRateTemp;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.service.IProjectOrderConfigInfoService;
import com.ruoyi.sip.service.IProjectOrderFileLogService;
import com.ruoyi.sip.service.IProjectTaxRateTempService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -80,6 +83,9 @@ public class ProjectOrderInfoController extends BaseController
@Autowired
private IProjectOrderFileLogService projectOrderFileLogService;
@Autowired
private IProjectTaxRateTempService projectTaxRateTempService;
@RequiresPermissions("project:order:view")
@GetMapping()
public String order()
@ -91,6 +97,7 @@ public class ProjectOrderInfoController extends BaseController
public String approve(@PathVariable("id") Long id, ModelMap mmap) {
mmap.put("approve", true);
ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoById(id);
projectTaxRateTempService.updateTaxRate(projectOrderInfo);
mmap.put("projectOrderInfo", projectOrderInfo);
mmap.put("user", ShiroUtils.getSysUser());
Todo todo = new Todo();
@ -105,6 +112,7 @@ public class ProjectOrderInfoController extends BaseController
public AjaxResult approve(@PathVariable("id") Long id) {
Map<String,Object> result=new HashMap<>();
ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoById(id);
projectTaxRateTempService.updateTaxRate(projectOrderInfo);
result.put("projectOrderInfo", projectOrderInfo);
result.put("user", ShiroUtils.getSysUser());
Todo todo = new Todo();

View File

@ -77,6 +77,7 @@ public class ProjectProductInfo extends BaseEntity
private BigDecimal discount;
private String type;
private String value;
private BigDecimal taxRate;
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.sip.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.math.BigDecimal;
/**
* project_tax_rate_temp
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
public class ProjectTaxRateTemp extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 订单编号 */
@Excel(name = "订单编号")
private String orderCode;
/** 税率 */
@Excel(name = "税率")
private BigDecimal taxRate;
/** 项目ID */
@Excel(name = "项目ID")
private Long projectId;
/** 产品ID */
@Excel(name = "产品Code")
private Long productId;
}

View File

@ -4,11 +4,13 @@ package com.ruoyi.sip.flowable.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.sip.domain.ProjectTaxRateTemp;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
@ -93,4 +95,5 @@ public class Todo extends BaseEntity
private Integer recoveryType;
private Map<String, Object> variables;
private List<ProjectTaxRateTemp> taxRateData;
}

View File

@ -0,0 +1,85 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.ProjectTaxRateTemp;
/**
* Mapper
*
* @author ruoyi
* @date 2024-01-01
*/
public interface ProjectTaxRateTempMapper
{
/**
*
*
* @param id
* @return
*/
public ProjectTaxRateTemp selectProjectTaxRateTempById(Long id);
/**
*
*
* @param projectTaxRateTemp
* @return
*/
public List<ProjectTaxRateTemp> selectProjectTaxRateTempList(ProjectTaxRateTemp projectTaxRateTemp);
/**
*
*
* @param orderCode
* @return
*/
public List<ProjectTaxRateTemp> selectProjectTaxRateTempByOrderCode(String orderCode);
/**
*
*
* @param projectTaxRateTemp
* @return
*/
public int insertProjectTaxRateTemp(ProjectTaxRateTemp projectTaxRateTemp);
/**
*
*
* @param projectTaxRateTemp
* @return
*/
public int updateProjectTaxRateTemp(ProjectTaxRateTemp projectTaxRateTemp);
/**
*
*
* @param id
* @return
*/
public int deleteProjectTaxRateTempById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteProjectTaxRateTempByIds(String[] ids);
/**
*
*
* @param orderCode
* @return
*/
public int deleteProjectTaxRateTempByOrderCode(String orderCode);
/**
*
*
* @param list
* @return
*/
public int batchInsertProjectTaxRateTemp(List<ProjectTaxRateTemp> list);
}

View File

@ -0,0 +1,98 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.domain.ProjectTaxRateTemp;
/**
* Service
*
* @author ruoyi
* @date 2024-01-01
*/
public interface IProjectTaxRateTempService
{
/**
*
*
* @param id
* @return
*/
public ProjectTaxRateTemp selectProjectTaxRateTempById(Long id);
/**
*
*
* @param projectTaxRateTemp
* @return
*/
public List<ProjectTaxRateTemp> selectProjectTaxRateTempList(ProjectTaxRateTemp projectTaxRateTemp);
/**
*
*
* @param orderCode
* @return
*/
public List<ProjectTaxRateTemp> selectProjectTaxRateTempByOrderCode(String orderCode);
/**
*
*
* @param projectTaxRateTemp
* @return
*/
public int insertProjectTaxRateTemp(ProjectTaxRateTemp projectTaxRateTemp);
/**
*
*
* @param projectTaxRateTemp
* @return
*/
public int updateProjectTaxRateTemp(ProjectTaxRateTemp projectTaxRateTemp);
/**
*
*
* @param ids
* @return
*/
public int deleteProjectTaxRateTempByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteProjectTaxRateTempById(Long id);
/**
*
*
* @param orderCode
* @return
*/
public int deleteProjectTaxRateTempByOrderCode(String orderCode);
/**
*
*
* @param orderCode
* @param taxRateDataList
* @return
*/
public int saveTaxRateTemp(String orderCode, List<ProjectTaxRateTemp> taxRateDataList);
/**
*
*
* @param orderCode
* @return
*/
public int applyTaxRateTemp(String orderCode);
void updateTaxRate(ProjectOrderInfo projectOrderInfo);
}

View File

@ -29,6 +29,7 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.ApiDataQueryDto;
import com.alibaba.fastjson.JSONArray;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.dto.HomepageQueryDto;
import com.ruoyi.sip.dto.OrderExcelNumStaticsDto;
@ -110,6 +111,8 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Autowired
private IBuApproveConfigService approveConfigService;
@Autowired
private IProjectTaxRateTempService projectTaxRateTempService;
@Value("${unis.order.endHour:96}")
private Integer endHour;
@Value("${unis.mail.businessRoleId:103}")
@ -557,6 +560,12 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
if (CollUtil.isNotEmpty(todo.getVariables())) {
Map<String, Object> variables = todo.getVariables();
variables.put("approveBtn", Integer.parseInt((String) variables.get("approveBtn")));
// 处理税率数据
if (CollUtil.isNotEmpty(todo.getTaxRateData())) {
handleTaxRateData(todo, variables);
}
if (variables.containsKey("allPriceCountValue") && "商务".equals(todo.getTaskName())) {
BigDecimal allPriceCountValue = new BigDecimal((String) variables.get("allPriceCountValue"));
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
@ -1106,7 +1115,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
if ("公司领导".equals(taskName)) {
projectOrderInfo.setVersionCode("add");
}
handleRejectOrder(businessKey);
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
}
@ -1162,6 +1171,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
if (dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE) != 0) {
productInfoService.calcByDiscountFold(dbProjectOrderInfo.getDiscountFold(), dbProjectOrderInfo.getProjectId());
}
handleApproveOrder(businessKey);
}
@Override
@ -1208,4 +1218,58 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
}
return projectOrderInfoMapper.listOrderInfoVo(queryParams);
}
/**
*
*
* @param businessKey
* @param variables
*/
private void handleTaxRateData(Todo todo, Map<String, Object> variables) {
try {
List<ProjectTaxRateTemp> taxRateDataList = todo.getTaxRateData();
if (CollUtil.isNotEmpty(taxRateDataList)) {
// 保存临时税率数据
projectTaxRateTempService.saveTaxRateTemp(todo.getBusinessKey(), taxRateDataList);
log.info("保存税率临时数据成功,订单编号:{}, 数据条数:{}", todo.getBusinessKey(), taxRateDataList.size());
}
} catch (Exception e) {
log.error("处理税率数据失败,订单编号:{}", todo.getBusinessKey(), e);
}
}
/**
*
*
* @param businessKey
*/
private void handleRejectOrder(String businessKey) {
try {
// 删除临时税率数据
projectTaxRateTempService.deleteProjectTaxRateTempByOrderCode(businessKey);
log.info("订单驳回,删除临时税率数据成功,订单编号:{}", businessKey);
} catch (Exception e) {
log.error("处理订单驳回失败,订单编号:{}", businessKey, e);
}
}
/**
*
*
* @param businessKey
*/
private void handleApproveOrder(String businessKey) {
try {
// 没有待处理任务,说明审批全部通过,应用临时数据
int updateCount = projectTaxRateTempService.applyTaxRateTemp(businessKey);
log.info("订单审批全部通过,应用临时税率数据成功,订单编号:{}, 更新产品数:{}", businessKey, updateCount);
} catch (Exception e) {
log.error("处理订单审批通过失败,订单编号:{}", businessKey, e);
}
}
}

View File

@ -2,10 +2,7 @@ package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
@ -173,12 +170,17 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
@Override
public void calcByDiscountFold(BigDecimal discountFold, Long projectId) {
List<ProjectProductInfo> projectProductInfos = projectProductInfoMapper.selectProjectProductInfoListByProjectId(Collections.singletonList(projectId));
List<ProjectProductInfo> updateList = new ArrayList<>();
for (ProjectProductInfo info : projectProductInfos) {
ProjectProductInfo dto = new ProjectProductInfo();
BigDecimal price = info.getPrice().multiply(discountFold).setScale(2,RoundingMode.HALF_UP);
info.setPrice(price);
info.setAllPrice(price.multiply(new BigDecimal(info.getQuantity())).setScale(2,RoundingMode.HALF_UP));
info.setDiscount(price.divide(info.getCataloguePrice(),4,RoundingMode.HALF_UP));
dto.setPrice(price);
dto.setAllPrice(price.multiply(new BigDecimal(info.getQuantity())).setScale(2, RoundingMode.HALF_UP));
BigDecimal divide = price.divide(info.getCataloguePrice(), 4, RoundingMode.HALF_UP);
dto.setDiscount(divide.compareTo(BigDecimal.ONE) > 0 ? info.getDiscount() : divide);
dto.setId(info.getId());
updateList.add(dto);
}
projectProductInfoMapper.updateBatch(projectProductInfos);
projectProductInfoMapper.updateBatch(updateList);
}
}

View File

@ -0,0 +1,204 @@
package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.domain.ProjectProductInfo;
import com.ruoyi.sip.service.IProjectProductInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.ProjectTaxRateTempMapper;
import com.ruoyi.sip.domain.ProjectTaxRateTemp;
import com.ruoyi.sip.service.IProjectTaxRateTempService;
import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.collection.CollUtil;
/**
* Service
*
* @author ruoyi
* @date 2024-01-01
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class ProjectTaxRateTempServiceImpl implements IProjectTaxRateTempService {
@Autowired
private ProjectTaxRateTempMapper projectTaxRateTempMapper;
@Autowired
private IProjectProductInfoService projectProductInfoService;
/**
*
*
* @param id
* @return
*/
@Override
public ProjectTaxRateTemp selectProjectTaxRateTempById(Long id) {
return projectTaxRateTempMapper.selectProjectTaxRateTempById(id);
}
/**
*
*
* @param projectTaxRateTemp
* @return
*/
@Override
public List<ProjectTaxRateTemp> selectProjectTaxRateTempList(ProjectTaxRateTemp projectTaxRateTemp) {
return projectTaxRateTempMapper.selectProjectTaxRateTempList(projectTaxRateTemp);
}
/**
*
*
* @param orderCode
* @return
*/
@Override
public List<ProjectTaxRateTemp> selectProjectTaxRateTempByOrderCode(String orderCode) {
return projectTaxRateTempMapper.selectProjectTaxRateTempByOrderCode(orderCode);
}
/**
*
*
* @param projectTaxRateTemp
* @return
*/
@Override
public int insertProjectTaxRateTemp(ProjectTaxRateTemp projectTaxRateTemp) {
projectTaxRateTemp.setCreateTime(DateUtils.getNowDate());
projectTaxRateTemp.setCreateBy(ShiroUtils.getUserId().toString());
return projectTaxRateTempMapper.insertProjectTaxRateTemp(projectTaxRateTemp);
}
/**
*
*
* @param projectTaxRateTemp
* @return
*/
@Override
public int updateProjectTaxRateTemp(ProjectTaxRateTemp projectTaxRateTemp) {
return projectTaxRateTempMapper.updateProjectTaxRateTemp(projectTaxRateTemp);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteProjectTaxRateTempByIds(String ids) {
return projectTaxRateTempMapper.deleteProjectTaxRateTempByIds(Convert.toStrArray(ids));
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteProjectTaxRateTempById(Long id) {
return projectTaxRateTempMapper.deleteProjectTaxRateTempById(id);
}
/**
*
*
* @param orderCode
* @return
*/
@Override
public int deleteProjectTaxRateTempByOrderCode(String orderCode) {
return projectTaxRateTempMapper.deleteProjectTaxRateTempByOrderCode(orderCode);
}
/**
*
*
* @param orderCode
* @param taxRateDataList
* @return
*/
@Override
public int saveTaxRateTemp(String orderCode, List<ProjectTaxRateTemp> taxRateDataList) {
// 先删除该订单的旧临时数据
deleteProjectTaxRateTempByOrderCode(orderCode);
if (CollUtil.isNotEmpty(taxRateDataList)) {
// 设置订单编号和创建信息
for (ProjectTaxRateTemp temp : taxRateDataList) {
temp.setOrderCode(orderCode);
temp.setCreateTime(DateUtils.getNowDate());
temp.setCreateBy(ShiroUtils.getUserId().toString());
}
// 批量插入新的临时数据
return projectTaxRateTempMapper.batchInsertProjectTaxRateTemp(taxRateDataList);
}
return 0;
}
/**
*
*
* @param orderCode
* @return
*/
@Override
public int applyTaxRateTemp(String orderCode) {
// 获取临时税率数据
List<ProjectTaxRateTemp> tempList = selectProjectTaxRateTempByOrderCode(orderCode);
if (CollUtil.isNotEmpty(tempList)) {
int updateCount = 0;
for (ProjectTaxRateTemp temp : tempList) {
// 更新项目产品信息表中的税率数据
if (temp.getProductId() != null) {
ProjectProductInfo productInfo = new ProjectProductInfo();
productInfo.setId(temp.getProductId());
productInfo.setTaxRate(temp.getTaxRate());
updateCount += projectProductInfoService.updateProjectProductInfo(productInfo);
}
}
// 应用完成后删除临时数据
deleteProjectTaxRateTempByOrderCode(orderCode);
return updateCount;
}
return 0;
}
@Override
public void updateTaxRate(ProjectOrderInfo projectOrderInfo) {
List<ProjectTaxRateTemp> projectTaxRateTemps = projectTaxRateTempMapper.selectProjectTaxRateTempByOrderCode(projectOrderInfo.getOrderCode());
if (CollUtil.isEmpty(projectTaxRateTemps)) {
return;
}
Map<Long, BigDecimal> tempMap = projectTaxRateTemps.stream().collect(Collectors.toMap(ProjectTaxRateTemp::getProductId, ProjectTaxRateTemp::getTaxRate, (a, b) -> a));
if (CollUtil.isNotEmpty(projectOrderInfo.getSoftwareProjectProductInfoList())) {
projectOrderInfo.getSoftwareProjectProductInfoList().forEach(productInfo ->
productInfo.setTaxRate(tempMap.get(productInfo.getId()) == null ? productInfo.getTaxRate() : tempMap.get(productInfo.getId())));
}
if (CollUtil.isNotEmpty(projectOrderInfo.getHardwareProjectProductInfoList())) {
projectOrderInfo.getHardwareProjectProductInfoList().forEach(productInfo ->
productInfo.setTaxRate(tempMap.get(productInfo.getId()) == null ? productInfo.getTaxRate() : tempMap.get(productInfo.getId())));
}
if (CollUtil.isNotEmpty(projectOrderInfo.getMaintenanceProjectProductInfoList())) {
projectOrderInfo.getMaintenanceProjectProductInfoList().forEach(productInfo ->
productInfo.setTaxRate(tempMap.get(productInfo.getId()) == null ? productInfo.getTaxRate() : tempMap.get(productInfo.getId())));
}
}
}

View File

@ -23,11 +23,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectProjectProductInfoVo">
select t1.id, t1.project_id, t1.product_bom_code, t1.model, t1.product_code, t1.product_desc, t1.quantity, t1.catalogue_price,
t1.catalogue_all_price, t1.price, t1.all_price, t1.guidance_discount, t1.discount, t1.remark from project_product_info t1
t1.catalogue_all_price, t1.price, t1.all_price, t1.guidance_discount, t1.discount, t1.remark,t1.tax_rate from project_product_info t1
</sql>
<sql id="selectProjectProductRelationInfoVo">
select t1.id, t1.project_id, t1.product_bom_code, t1.model, t1.product_code, t1.product_desc, t1.quantity, t1.catalogue_price,
t1.catalogue_all_price, t1.price, t1.all_price, t1.guidance_discount, t1.discount, t1.remark,t2.type,t2.product_name,t2.vendor_code,t2.value
t1.catalogue_all_price, t1.price, t1.all_price, t1.guidance_discount, t1.discount, t1.remark,t1.tax_rate,t2.type,t2.product_name,t2.vendor_code,t2.value
from project_product_info t1
left join product_info t2 on t1.product_bom_code = t2.product_code
@ -90,6 +90,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="guidanceDiscount != null">guidance_discount,</if>
<if test="discount != null">discount,</if>
<if test="remark != null">remark,</if>
<if test="taxRate != null">tax_rate ,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="projectId != null">#{projectId},</if>
@ -105,20 +106,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="guidanceDiscount != null">#{guidanceDiscount},</if>
<if test="discount != null">#{discount},</if>
<if test="remark != null">#{remark},</if>
<if test="taxRate != null"> #{taxRate},</if>
</trim>
</insert>
<insert id="saveBatch">
insert into project_product_info (project_id, product_bom_code, model, product_code, product_desc, quantity,
catalogue_price, catalogue_all_price, price, all_price, guidance_discount, discount, remark) values
catalogue_price, catalogue_all_price, price, all_price, guidance_discount, discount, remark,tax_rate) values
<foreach collection="list" item="item" separator=",">
(#{item.projectId}, #{item.productBomCode}, #{item.model}, #{item.productCode}, #{item.productDesc},
#{item.quantity}, #{item.cataloguePrice}, #{item.catalogueAllPrice}, #{item.price}, #{item.allPrice},
#{item.guidanceDiscount}, #{item.discount}, #{item.remark})
#{item.guidanceDiscount}, #{item.discount}, #{item.remark},#{item.taxRate})
</foreach>
ON DUPLICATE KEY UPDATE product_bom_code = values(product_bom_code), model = values(model),
product_code = values(product_code), product_desc = values(product_desc), quantity = values(quantity), catalogue_price = values(catalogue_price),
catalogue_all_price = values(catalogue_all_price), price = values(price), all_price = values(all_price), guidance_discount = values(guidance_discount),
discount = values(discount), remark = values(remark)
discount = values(discount), remark = values(remark),tax_rate=values(tax_rate)
</insert>
<update id="updateProjectProductInfo" parameterType="ProjectProductInfo">
@ -130,6 +132,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="productCode != null">product_code = #{productCode},</if>
<if test="productDesc != null">product_desc = #{productDesc},</if>
<if test="quantity != null">quantity = #{quantity},</if>
<if test="taxRate != null">tax_rate = #{taxRate},</if>
<if test="cataloguePrice != null">catalogue_price = #{cataloguePrice},</if>
<if test="catalogueAllPrice != null">catalogue_all_price = #{catalogueAllPrice},</if>
<if test="price != null">price = #{price},</if>
@ -158,6 +161,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="item.guidanceDiscount != null">guidance_discount = #{item.guidanceDiscount},</if>
<if test="item.discount != null">discount = #{item.discount},</if>
<if test="item.remark != null">remark = #{item.remark},</if>
<if test="item.taxRate != null">tax_rate = #{item.taxRate},</if>
</trim>
where id = #{item.id}
</foreach>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sip.mapper.ProjectTaxRateTempMapper">
<resultMap type="ProjectTaxRateTemp" id="ProjectTaxRateTempResult">
<result property="id" column="id" />
<result property="orderCode" column="order_code" />
<result property="taxRate" column="tax_rate" />
<result property="projectId" column="project_id" />
<result property="productId" column="product_id" />
<result property="createTime" column="create_time" />
<result property="createBy" column="create_by" />
</resultMap>
<sql id="selectProjectTaxRateTempVo">
select id, order_code, tax_rate, project_id, product_id, create_time, create_by from project_tax_rate_temp
</sql>
<select id="selectProjectTaxRateTempList" parameterType="ProjectTaxRateTemp" resultMap="ProjectTaxRateTempResult">
<include refid="selectProjectTaxRateTempVo"/>
<where>
<if test="orderCode != null and orderCode != ''"> and order_code = #{orderCode}</if>
<if test="taxRate != null "> and tax_rate = #{taxRate}</if>
<if test="projectId != null "> and project_id = #{projectId}</if>
<if test="productId != null "> and product_id = #{productId}</if>
</where>
</select>
<select id="selectProjectTaxRateTempById" parameterType="Long" resultMap="ProjectTaxRateTempResult">
<include refid="selectProjectTaxRateTempVo"/>
where id = #{id}
</select>
<select id="selectProjectTaxRateTempByOrderCode" parameterType="String" resultMap="ProjectTaxRateTempResult">
<include refid="selectProjectTaxRateTempVo"/>
where order_code = #{orderCode}
</select>
<insert id="insertProjectTaxRateTemp" parameterType="ProjectTaxRateTemp" useGeneratedKeys="true" keyProperty="id">
insert into project_tax_rate_temp
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="orderCode != null and orderCode != ''">order_code,</if>
<if test="taxRate != null">tax_rate,</if>
<if test="projectId != null">project_id,</if>
<if test="productId != null">product_id,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="orderCode != null and orderCode != ''">#{orderCode},</if>
<if test="taxRate != null">#{taxRate},</if>
<if test="projectId != null">#{projectId},</if>
<if test="productId != null">#{productId},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
</trim>
</insert>
<update id="updateProjectTaxRateTemp" parameterType="ProjectTaxRateTemp">
update project_tax_rate_temp
<trim prefix="SET" suffixOverrides=",">
<if test="orderCode != null and orderCode != ''">order_code = #{orderCode},</if>
<if test="taxRate != null">tax_rate = #{taxRate},</if>
<if test="projectId != null">project_id = #{projectId},</if>
<if test="productId != null">product_id = #{productId},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="createBy != null and createBy != ''">create_by = #{createBy},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteProjectTaxRateTempById" parameterType="Long">
delete from project_tax_rate_temp where id = #{id}
</delete>
<delete id="deleteProjectTaxRateTempByIds" parameterType="String">
delete from project_tax_rate_temp where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<delete id="deleteProjectTaxRateTempByOrderCode" parameterType="String">
delete from project_tax_rate_temp where order_code = #{orderCode}
</delete>
<insert id="batchInsertProjectTaxRateTemp" parameterType="java.util.List">
insert into project_tax_rate_temp (order_code, tax_rate, project_id, product_id, create_time, create_by)
values
<foreach collection="list" item="item" separator=",">
(#{item.orderCode}, #{item.taxRate}, #{item.projectId}, #{item.productId}, #{item.createTime}, #{item.createBy})
</foreach>
</insert>
</mapper>