feat(finance): 新增付款计划同步至发票计划功能
- 在后端服务中实现 syncPaymentToTicketPlan 方法,用于将付款计划同步到发票计划
- 添加对应的 REST 接口 /sync/{payableBillId} 支持前端调用
- 前端页面新增“同步至发票计划”按钮,并绑定相应处理逻辑
- 提供 API 函数 syncToTicketPlan 以支持前后端通信
- 优化计算公式显示,确保数值精度和展示正确性
- 增强数据一致性校验,防止已执行的数据不匹配导致错误同步
dev_1.0.0
parent
4cc2d3beb1
commit
2f51b56298
|
|
@ -68,3 +68,11 @@ export function updateReceivingTicketPlan(payableBillId, data) {
|
|||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 同步付款计划至发票计划
|
||||
export function syncToTicketPlan(payableBillId) {
|
||||
return request({
|
||||
url: `/finance/payable/plan/sync/${payableBillId}`,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@
|
|||
<span style="margin-left: 20px;">计划付款总金额: <el-tag type="success">{{
|
||||
totalPlannedAmount.toFixed(2)
|
||||
}}</el-tag></span>
|
||||
<span>计划付款比例: <el-tag type="info">{{ this.$calc.div(totalPlannedAmount,totalPayableAmountWithTax,4)*100 }}%</el-tag></span>
|
||||
<span>计划付款比例: <el-tag type="info">{{ this.$calc.mul(this.$calc.div(totalPlannedAmount,totalPayableAmountWithTax,4),100) }}%</el-tag></span>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
|
|
@ -339,7 +339,9 @@ export default {
|
|||
const order = this.payableOrdersWithPlans.find(o => o.id === orderId);
|
||||
if (order && order.paymentPlans && order.unpaidAmount >= 0) {
|
||||
const currentAmount = this.calculateOrderCurrentPaymentAmount(orderId);
|
||||
return this.$calc.mul(this.$calc.div(currentAmount ,order.totalPriceWithTax,4 ),100);
|
||||
console.log(this.$calc.div(currentAmount ,order.totalPriceWithTax,4 ))
|
||||
console.log(11111)
|
||||
return this.$calc.mul((this.$calc.div(currentAmount ,order.totalPriceWithTax,4 )),100);
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@
|
|||
<span style="margin-left: 20px;">计划收票总金额: <el-tag type="success">{{
|
||||
totalPlannedAmount.toFixed(2)
|
||||
}}</el-tag></span>
|
||||
<span>计划收票比例: <el-tag type="info">{{ this.$calc.div(totalPlannedAmount,totalPayableAmountWithTax,4)*100 }}%</el-tag></span>
|
||||
<span>计划收票比例: <el-tag type="info">{{ this.$calc.mul(this.$calc.div(totalPlannedAmount,totalPayableAmountWithTax,4),100) }}%</el-tag></span>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
style="margin-bottom: 10px;">
|
||||
保存付款计划
|
||||
</el-button>
|
||||
<el-button v-if="isEditing" type="primary" size="mini" @click="handleSyncToTicketPlan"
|
||||
style="margin-bottom: 10px; margin-left: 10px;">
|
||||
同步至发票计划
|
||||
</el-button>
|
||||
<el-button v-else type="primary" size="mini" @click="isEditing=true"
|
||||
style="margin-bottom: 10px;">
|
||||
编辑
|
||||
|
|
@ -86,7 +90,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {getPaymentPlan, updatePaymentPlan} from "@/api/finance/payable";
|
||||
import {getPaymentPlan, updatePaymentPlan, syncToTicketPlan} from "@/api/finance/payable";
|
||||
import {isNumberStr} from "@/utils";
|
||||
|
||||
export default {
|
||||
|
|
@ -219,6 +223,13 @@ export default {
|
|||
this.fetchPaymentPlans(this.payableData.id); // Re-fetch using the correct method and ID
|
||||
});
|
||||
},
|
||||
handleSyncToTicketPlan() {
|
||||
this.$modal.confirm('是否确认同步付款计划至发票计划?').then(() => {
|
||||
return syncToTicketPlan(this.payableData.id);
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("同步成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
|
||||
handleAddPaymentPlanRow() {
|
||||
this.paymentPlans.push({
|
||||
|
|
|
|||
|
|
@ -32,4 +32,10 @@ public class OmsPayablePlanController extends BaseController {
|
|||
paymentPlanService.updatePaymentPlans(payableBillId, paymentPlanList);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@PostMapping("/sync/{payableBillId}")
|
||||
public AjaxResult syncPaymentToTicketPlan(@PathVariable("payableBillId") Long payableBillId) {
|
||||
paymentPlanService.syncPaymentToTicketPlan(payableBillId);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,4 +19,12 @@ public interface IOmsPayablePaymentPlanService {
|
|||
* @param paymentPlanList 付款计划列表
|
||||
*/
|
||||
public void updatePaymentPlans(Long payableBillId, List<OmsPayablePaymentPlan> paymentPlanList);
|
||||
|
||||
/**
|
||||
* 同步付款计划至发票计划
|
||||
*
|
||||
* @param payableBillId 应付单ID
|
||||
* @return 结果
|
||||
*/
|
||||
public void syncPaymentToTicketPlan(Long payableBillId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
package com.ruoyi.sip.service.impl;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketPlan;
|
||||
import com.ruoyi.sip.service.IOmsPayablePaymentDetailService;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketPlanService;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
|
@ -25,6 +30,9 @@ public class OmsPayablePaymentPlanServiceImpl implements IOmsPayablePaymentPlanS
|
|||
|
||||
@Autowired
|
||||
private IOmsPayablePaymentDetailService omsPayablePaymentDetailService;
|
||||
|
||||
@Autowired
|
||||
private IOmsPayableTicketPlanService ticketPlanService;
|
||||
@Override
|
||||
public List<OmsPayablePaymentPlan> selectOmsPayablePaymentPlanListByPayableBillId(Long payableBillId) {
|
||||
List<OmsPayablePaymentPlan> omsPayablePaymentPlans = omsPayablePaymentPlanMapper.selectOmsPayablePaymentPlanListByPayableBillId(payableBillId);
|
||||
|
|
@ -74,4 +82,78 @@ public class OmsPayablePaymentPlanServiceImpl implements IOmsPayablePaymentPlanS
|
|||
omsPayablePaymentPlanMapper.deleteOmsPayablePaymentPlanById(idToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void syncPaymentToTicketPlan(Long payableBillId) {
|
||||
List<OmsPayableTicketPlan> ticketPlans = ticketPlanService.listByPayableBillId(payableBillId);
|
||||
List<OmsPayablePaymentPlan> paymentPlans = selectOmsPayablePaymentPlanListByPayableBillId(payableBillId);
|
||||
|
||||
boolean hasExecutedTicket = ticketPlans.stream().anyMatch(p -> p.getDetailId() != null);
|
||||
|
||||
if (!hasExecutedTicket) {
|
||||
List<OmsPayableTicketPlan> newPlans = convertPaymentToTicket(paymentPlans, payableBillId);
|
||||
ticketPlanService.updateTicketPlan(payableBillId, newPlans);
|
||||
} else {
|
||||
List<OmsPayableTicketPlan> executedTickets = ticketPlans.stream()
|
||||
.filter(p -> p.getDetailId() != null).collect(Collectors.toList());
|
||||
List<OmsPayablePaymentPlan> executedPayments = paymentPlans.stream()
|
||||
.filter(p -> p.getDetailId() != null).collect(Collectors.toList());
|
||||
|
||||
List<OmsPayablePaymentPlan> unmatchedExecutedPayments = new ArrayList<>(executedPayments);
|
||||
|
||||
for (OmsPayableTicketPlan ticket : executedTickets) {
|
||||
boolean found = false;
|
||||
Iterator<OmsPayablePaymentPlan> it = unmatchedExecutedPayments.iterator();
|
||||
while (it.hasNext()) {
|
||||
OmsPayablePaymentPlan payment = it.next();
|
||||
if (compareDates(ticket.getPlanTicketDate(), payment.getPlanPaymentDate()) == 0 &&
|
||||
ticket.getPlanAmount().compareTo(payment.getPlanAmount()) == 0) {
|
||||
it.remove();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
throw new ServiceException("因付款计划表与开票计划表中已付款/开票数据已不一致,所以无法关联开票计划");
|
||||
}
|
||||
}
|
||||
|
||||
List<OmsPayablePaymentPlan> unexecutedPayments = paymentPlans.stream()
|
||||
.filter(p -> p.getDetailId() == null).collect(Collectors.toList());
|
||||
|
||||
List<OmsPayablePaymentPlan> toConvert = new ArrayList<>();
|
||||
toConvert.addAll(unmatchedExecutedPayments);
|
||||
toConvert.addAll(unexecutedPayments);
|
||||
|
||||
List<OmsPayableTicketPlan> newPlans = convertPaymentToTicket(toConvert, payableBillId);
|
||||
|
||||
List<OmsPayableTicketPlan> finalPlans = new ArrayList<>(executedTickets);
|
||||
finalPlans.addAll(newPlans);
|
||||
|
||||
ticketPlanService.updateTicketPlan(payableBillId, finalPlans);
|
||||
}
|
||||
}
|
||||
|
||||
private List<OmsPayableTicketPlan> convertPaymentToTicket(List<OmsPayablePaymentPlan> paymentPlans, Long payableBillId) {
|
||||
List<OmsPayableTicketPlan> list = new ArrayList<>();
|
||||
for (OmsPayablePaymentPlan p : paymentPlans) {
|
||||
OmsPayableTicketPlan t = new OmsPayableTicketPlan();
|
||||
t.setPayableBillId(payableBillId);
|
||||
t.setPlanTicketDate(p.getPlanPaymentDate());
|
||||
t.setPlanAmount(p.getPlanAmount());
|
||||
t.setPlanRate(p.getPlanRate());
|
||||
t.setDetailId(null);
|
||||
t.setRemark(p.getRemark());
|
||||
list.add(t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private int compareDates(java.util.Date d1, java.util.Date d2) {
|
||||
if (d1 == null && d2 == null) return 0;
|
||||
if (d1 == null) return -1;
|
||||
if (d2 == null) return 1;
|
||||
return d1.compareTo(d2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue