Browse Source

[feat]

财务管理 应付账款
修改报销单确认打款后更新应付账款service方法和更新相关订单service方法;
新增根据采购订单生成应付账款service方法,修改手动结案service方法,同时更新订单信息;
修改应付账款列表页面,合并操作栏按钮,修改结案按钮显示条件,新增结案跳转方法;
新增结案页面;
dev
王晓迪 2 months ago
parent
commit
58164fa26d
  1. 4
      ruoyi-admin/src/main/java/com/ruoyi/financial/service/IFinancialAccountsPayableService.java
  2. 71
      ruoyi-admin/src/main/java/com/ruoyi/financial/service/impl/FinancialAccountsPayableServiceImpl.java
  3. 82
      ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseExpenseConfirmAmountServiceImpl.java
  4. 43
      ruoyi-admin/src/main/resources/templates/financial/payable/closed.html
  5. 83
      ruoyi-admin/src/main/resources/templates/financial/payable/payable.html

4
ruoyi-admin/src/main/java/com/ruoyi/financial/service/IFinancialAccountsPayableService.java

@ -2,6 +2,7 @@ package com.ruoyi.financial.service;
import java.util.List; import java.util.List;
import com.ruoyi.financial.domain.FinancialAccountsPayable; import com.ruoyi.financial.domain.FinancialAccountsPayable;
import com.ruoyi.purchase.domain.PurchaseOrder;
/** /**
* 财务应付账款Service接口 * 财务应付账款Service接口
@ -76,5 +77,8 @@ public interface IFinancialAccountsPayableService
// 根据编号集合查询应付账款列表 // 根据编号集合查询应付账款列表
public List<FinancialAccountsPayable> selectFinancialAccountsPayableByCodes(String[] accountsPayableCodes); public List<FinancialAccountsPayable> selectFinancialAccountsPayableByCodes(String[] accountsPayableCodes);
//根据采购订单生成应付账款
int createFinancialAccountsPayable(PurchaseOrder purchaseOrder);
int closingFinancialAccountsPayableById(FinancialAccountsPayable accountsPayable); int closingFinancialAccountsPayableById(FinancialAccountsPayable accountsPayable);
} }

71
ruoyi-admin/src/main/java/com/ruoyi/financial/service/impl/FinancialAccountsPayableServiceImpl.java

@ -1,14 +1,23 @@
package com.ruoyi.financial.service.impl; package com.ruoyi.financial.service.impl;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.purchase.domain.PurchaseOrder;
import com.ruoyi.purchase.mapper.PurchaseOrderMapper;
import com.ruoyi.system.domain.SysSupplier;
import com.ruoyi.system.mapper.SysSupplierMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.financial.mapper.FinancialAccountsPayableMapper; import com.ruoyi.financial.mapper.FinancialAccountsPayableMapper;
import com.ruoyi.financial.domain.FinancialAccountsPayable; import com.ruoyi.financial.domain.FinancialAccountsPayable;
import com.ruoyi.financial.service.IFinancialAccountsPayableService; import com.ruoyi.financial.service.IFinancialAccountsPayableService;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;
/** /**
* 财务应付账款Service业务层处理 * 财务应付账款Service业务层处理
@ -22,6 +31,15 @@ public class FinancialAccountsPayableServiceImpl implements IFinancialAccountsPa
@Autowired @Autowired
private FinancialAccountsPayableMapper financialAccountsPayableMapper; private FinancialAccountsPayableMapper financialAccountsPayableMapper;
@Autowired
private RedisCache redisCache;
@Autowired
private SysSupplierMapper supplierMapper;
@Autowired
private PurchaseOrderMapper purchaseOrderMapper;
/** /**
* 查询财务应付账款 * 查询财务应付账款
* *
@ -129,12 +147,57 @@ public class FinancialAccountsPayableServiceImpl implements IFinancialAccountsPa
return financialAccountsPayableMapper.selectFinancialAccountsPayableByCodes(accountsPayableCodes); return financialAccountsPayableMapper.selectFinancialAccountsPayableByCodes(accountsPayableCodes);
} }
//根据采购订单生成应付账款
@Override
public int createFinancialAccountsPayable(PurchaseOrder purchaseOrder){
FinancialAccountsPayable financialAccountsPayable = new FinancialAccountsPayable();
financialAccountsPayable.setAccountsPayableCode(redisCache.generateBillNo("YF"));
financialAccountsPayable.setRelevanceCode(purchaseOrder.getPurchaseOrderCode());
financialAccountsPayable.setAccountsPayableStatus("0");//待打款
financialAccountsPayable.setSupplierCode(purchaseOrder.getSupplierCode());
financialAccountsPayable.setSupplierName(purchaseOrder.getSupplierName());
SysSupplier supplier = supplierMapper.selectSysSupplierByCode(purchaseOrder.getSupplierCode());
if(supplier == null){
throw new BusinessException("供应商信息不存在,请检查");
}
financialAccountsPayable.setOpenBank(supplier.getDepositBank());
financialAccountsPayable.setOpenAccount(supplier.getBankAccount());
financialAccountsPayable.setCurrencyType("1");//RMB
financialAccountsPayable.setPriceIncludesTax(purchaseOrder.getRmbSum());
financialAccountsPayable.setPriceExcludingTax(purchaseOrder.getNoRmbSum());
financialAccountsPayable.setPaymentCondition(supplier.getPaymentTerms());
financialAccountsPayable.setPaidPrice(BigDecimal.ZERO);
financialAccountsPayable.setUnpaidPrice(purchaseOrder.getRmbSum());
financialAccountsPayable.setPurchaseBuyer(purchaseOrder.getPurchaseBuyer());
financialAccountsPayable.setStorageStatus("0");//待入库
financialAccountsPayable.setCreateBy(ShiroUtils.getLoginName());
financialAccountsPayable.setCreateTime(DateUtils.getNowDate());
return financialAccountsPayableMapper.insertFinancialAccountsPayable(financialAccountsPayable);
}
//应付账款手动结案
@Transactional(rollbackFor = Exception.class)
@Override @Override
public int closingFinancialAccountsPayableById(FinancialAccountsPayable accountsPayable) { public int closingFinancialAccountsPayableById(FinancialAccountsPayable accountsPayable) {
accountsPayable.setAccountsPayableStatus("4");//结案 FinancialAccountsPayable payable = financialAccountsPayableMapper.selectFinancialAccountsPayableById(accountsPayable.getAccountsPayableId());
accountsPayable.setUpdateBy(ShiroUtils.getLoginName()); payable.setClosedReason(accountsPayable.getClosedReason());
accountsPayable.setUpdateTime(DateUtils.getNowDate()); payable.setAccountsPayableStatus("2");//结案
int result = financialAccountsPayableMapper.updateFinancialAccountsPayable(accountsPayable); payable.setUpdateBy(ShiroUtils.getLoginName());
payable.setUpdateTime(DateUtils.getNowDate());
String relatedCode = payable.getRelevanceCode();
if(relatedCode.startsWith("CG")){
PurchaseOrder purchaseOrder = purchaseOrderMapper.selectPurchaseOrderByOrderCode(relatedCode);
purchaseOrder.setPaymentStatus("3");//待结案
purchaseOrder.setUpdateBy(ShiroUtils.getLoginName());
purchaseOrder.setUpdateTime(DateUtils.getNowDate());
int updateResult = purchaseOrderMapper.updatePurchaseOrder(purchaseOrder);
if(updateResult <= 0 ){
throw new BusinessException("关联采购订单更新失败");
}
}
int result = financialAccountsPayableMapper.updateFinancialAccountsPayable(payable);
return result; return result;
} }

82
ruoyi-admin/src/main/java/com/ruoyi/system/service/impl/BaseExpenseConfirmAmountServiceImpl.java

@ -143,7 +143,7 @@ public class BaseExpenseConfirmAmountServiceImpl implements IBaseExpenseConfirmA
return rows; return rows;
} }
// 修改关联订单子表打款状态; // 更新关联订单子表打款状态;
private int changeRelatedOrderStatus(String expenseCode,BaseExpenseConfirmAmount baseExpenseConfirmAmount){ private int changeRelatedOrderStatus(String expenseCode,BaseExpenseConfirmAmount baseExpenseConfirmAmount){
List<BaseExpenseAccountChild> expenseChildren = expenseAccountChildMapper.selectBaseExpenseAccountChildByExpenseCode(expenseCode); List<BaseExpenseAccountChild> expenseChildren = expenseAccountChildMapper.selectBaseExpenseAccountChildByExpenseCode(expenseCode);
BaseExpenseAccount baseExpenseAccount = expenseAccountMapper.selectBaseExpenseAccountByCode(expenseCode); BaseExpenseAccount baseExpenseAccount = expenseAccountMapper.selectBaseExpenseAccountByCode(expenseCode);
@ -156,26 +156,24 @@ public class BaseExpenseConfirmAmountServiceImpl implements IBaseExpenseConfirmA
if(rows<= 0){ if(rows<= 0){
throw new BusinessException("更新应付账款记录失败!"); throw new BusinessException("更新应付账款记录失败!");
} }
int updateResult = 0; String purchaseOrderCode = child.getPurchaseCode();
PurchaseOrderChild tempChild = new PurchaseOrderChild(); PurchaseOrder purchaseOrder = purchaseOrderMapper.selectPurchaseOrderByOrderCode(purchaseOrderCode);
tempChild.setPurchaseOrderCode(child.getPurchaseCode()); if(purchaseOrder == null){
//tempChild.setSupplierCode(supplierCode); throw new BusinessException("关联采购订单"+purchaseOrderCode+"不存在!");
List<PurchaseOrderChild> purchaseChildren = purchaseChildMapper.selectChildListBySupplierCodeAndOrderCode(tempChild);
if(CollectionUtils.isNotEmpty(purchaseChildren)){
for (PurchaseOrderChild purchaseChild: purchaseChildren) {
//purchaseChild.setPaymentStatus("2");
purchaseChildMapper.updatePurchaseOrderChild(purchaseChild);
updateResult ++;
}
if(updateResult <= 0){
throw new BusinessException("采购订单详情记录更新失败!");
}
int updatePurchaseOrder = updatePurchaseOrderPayableStatus(child.getPurchaseCode());
if(updatePurchaseOrder <= 0){
throw new BusinessException("采购订单打款状态更新失败!");
}
influRows ++;
} }
BigDecimal paidPrice = child.getAmounts();
if(paidPrice.compareTo(purchaseOrder.getRmbSum()) == 0){
purchaseOrder.setPaymentStatus("4");//已结案
}else if(paidPrice.compareTo(purchaseOrder.getRmbSum()) < 0){
purchaseOrder.setPaymentStatus("1");//部分打款(需要手动结案)
}
purchaseOrder.setUpdateBy(ShiroUtils.getLoginName());
purchaseOrder.setUpdateTime(DateUtils.getNowDate());
int updateResult = purchaseOrderMapper.updatePurchaseOrder(purchaseOrder);
if(updateResult <= 0 ){
throw new BusinessException("关联采购订单更新失败");
}
influRows ++;
} }
else if(child.getOutsourceCode()!=null&&!child.getOutsourceCode().isEmpty()){ else if(child.getOutsourceCode()!=null&&!child.getOutsourceCode().isEmpty()){
// 更新应付账款打款相关信息 // 更新应付账款打款相关信息
@ -208,42 +206,6 @@ public class BaseExpenseConfirmAmountServiceImpl implements IBaseExpenseConfirmA
} }
return influRows; return influRows;
} }
// 更新采购订单打款状态
public int updatePurchaseOrderPayableStatus(String purchaseOrderCode){
PurchaseOrder purchaseOrder = purchaseOrderMapper.selectPurchaseOrderByOrderCode(purchaseOrderCode);
List<PurchaseOrderChild> purchaseOrderChildren = purchaseChildMapper.selectPurchaseOrderChildByOrderCode(purchaseOrderCode);
// if(CollectionUtils.isEmpty(purchaseOrderChildren)){
// throw new BusinessException("采购订单详情记录为空!");
// }
// String isAllPaid = "3";
// // 获取所有 paymentStatus 的集合
// Set<String> statuses = purchaseOrderChildren.stream()
// .map(PurchaseOrderChild::getPaymentStatus)
// .collect(Collectors.toSet());
//
// // 判断状态
// if (statuses.size() == 1) {
// String singleStatus = statuses.iterator().next();
// if (singleStatus.equals("0")) {
// isAllPaid = "0";
// } else if (singleStatus.equals("2")) {
// isAllPaid = "1";
// }
// } else if (statuses.size() == 2 && statuses.contains("0") && statuses.contains("2")) {
// isAllPaid = "2";
// }
// if(isAllPaid.equals("1")){
//// 订单内供应商全部打款
// purchaseOrder.setPaymentStatus("2");
// }else if(isAllPaid.equals("0")){
//// 订单内供应商全未打款
// purchaseOrder.setPaymentStatus("0");
// }else if(isAllPaid.equals("2")){
// purchaseOrder.setPaymentStatus("1");
// }
purchaseOrder.setUpdateTime(DateUtils.getNowDate());
return purchaseOrderMapper.updatePurchaseOrder(purchaseOrder);
}
// 更新委外订单打款状态 // 更新委外订单打款状态
public int updateOutsourceOrderPayableStatus(String outsourceOrderCode){ public int updateOutsourceOrderPayableStatus(String outsourceOrderCode){
@ -300,12 +262,18 @@ public class BaseExpenseConfirmAmountServiceImpl implements IBaseExpenseConfirmA
if(insertResult <= 0){ if(insertResult <= 0){
throw new BusinessException("插入应付账款付款记录失败!"); throw new BusinessException("插入应付账款付款记录失败!");
} }
accountsPayable.setAccountsPayableStatus("2");
accountsPayable.setPaidPrice(paidPrice); accountsPayable.setPaidPrice(paidPrice);
accountsPayable.setActualPaidPrice(paidPrice); accountsPayable.setActualPaidPrice(paidPrice);
BigDecimal shoudPay = accountsPayable.getPriceIncludesTax(); BigDecimal shoudPay = accountsPayable.getPriceIncludesTax();
accountsPayable.setUnpaidPrice(shoudPay.subtract(paidPrice)); accountsPayable.setUnpaidPrice(shoudPay.subtract(paidPrice));
if(paidPrice.compareTo(shoudPay) == 0 ){
accountsPayable.setAccountsPayableStatus("2");//已结案
}else if(paidPrice.compareTo(shoudPay) < 0){
accountsPayable.setAccountsPayableStatus("1");//部分打款(需要手动结案)
}
accountsPayable.setOperatorPeople(ShiroUtils.getLoginName()); accountsPayable.setOperatorPeople(ShiroUtils.getLoginName());
accountsPayable.setUpdateBy(ShiroUtils.getLoginName());
accountsPayable.setUpdateTime(DateUtils.getNowDate());
int rows = accountsPayableMapper.updateFinancialAccountsPayable(accountsPayable); int rows = accountsPayableMapper.updateFinancialAccountsPayable(accountsPayable);
return rows; return rows;
} }

43
ruoyi-admin/src/main/resources/templates/financial/payable/closed.html

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('结案')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form_payable_closed" th:object="${accountsPayable}">
<input name="financialReceivablesId" th:field="*{accountsPayableId}" type="hidden">
<div class="form-group">
<label class="col-sm-4 control-label is-required">应付单号:</label>
<div class="col-sm-8">
<input readonly class="form-control" name="accountsPayableCode" th:field="*{accountsPayableCode}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label is-required">结案原因:</label>
<div class="col-sm-8">
<textarea class="form-control" id="closedReason" name="closedReason"></textarea>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "financial/payable";
$("#form_payable_closed").validate({
focusCleanup: true,
});
function submitHandler() {
if ($.validate.form()) {
var closedReason = $("#closedReason").val();
if(closedReason == null||closedReason == ''){
$.modal.msgError("请填写结案原因");
return;
}
$.operate.save(prefix + "/closed", $('#form_payable_closed').serialize());
}
}
</script>
</body>
</html>

83
ruoyi-admin/src/main/resources/templates/financial/payable/payable.html

@ -56,10 +56,6 @@
<label>合同编号:</label> <label>合同编号:</label>
<input type="text" name="contractNumber"/> <input type="text" name="contractNumber"/>
</li> </li>
<li>
<label>采购员:</label>
<input type="text" name="purchaseBuyer"/>
</li>
<li> <li>
<label>入库状态:</label> <label>入库状态:</label>
<select name="storageStatus" th:with="type=${@dict.getType('erp_inbound_status')}"> <select name="storageStatus" th:with="type=${@dict.getType('erp_inbound_status')}">
@ -68,8 +64,8 @@
</select> </select>
</li> </li>
<li> <li>
<label>更新人</label> <label>采购员</label>
<input type="text" name="updateBy"/> <input type="text" name="purchaseBuyer"/>
</li> </li>
<li class="select-time"> <li class="select-time">
<label>录入时间:</label> <label>录入时间:</label>
@ -93,7 +89,7 @@
</div> </div>
<div class="btn-group-sm" id="toolbar" role="group"> <div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-warning" onclick="exportExcel()" shiro:hasPermission="financial:payable:export"> <a class="btn btn-success" onclick="exportExcel()" shiro:hasPermission="financial:payable:export">
<i class="fa fa-download"></i> 导出 <i class="fa fa-download"></i> 导出
</a> </a>
</div> </div>
@ -109,7 +105,7 @@
var removeFlag = [[${@permission.hasPermi('financial:payable:remove')}]]; var removeFlag = [[${@permission.hasPermi('financial:payable:remove')}]];
var closingFlag = [[${@permission.hasPermi('financial:payable:payableClosing')}]]; var closingFlag = [[${@permission.hasPermi('financial:payable:payableClosing')}]];
var accountsPayableStatusDatas = [[${@dict.getType('sys_pay_close')}]]; var accountsPayableStatusDatas = [[${@dict.getType('accounts_payable_status')}]];
var currencyTypeDatas = [[${@dict.getType('sys_common_currency')}]]; var currencyTypeDatas = [[${@dict.getType('sys_common_currency')}]];
var storageStatusDatas = [[${@dict.getType('erp_inbound_status')}]]; var storageStatusDatas = [[${@dict.getType('erp_inbound_status')}]];
var prefix = ctx + "financial/payable"; var prefix = ctx + "financial/payable";
@ -177,10 +173,22 @@
{ {
title: '不含税金额', title: '不含税金额',
field: 'priceExcludingTax', field: 'priceExcludingTax',
formatter: function(value, row, index) {
if(value == null || value == ''){
return 0;
}
return value;
}
}, },
{ {
title: '含税金额', title: '含税金额',
field: 'priceIncludesTax', field: 'priceIncludesTax',
formatter: function(value, row, index) {
if(value == null || value == ''){
return 0;
}
return value;
}
}, },
{ {
title: '付款条件', title: '付款条件',
@ -189,10 +197,22 @@
{ {
title: '实付金额', title: '实付金额',
field: 'actualPaidPrice', field: 'actualPaidPrice',
formatter: function(value, row, index) {
if(value == null || value == ''){
return 0;
}
return value;
}
}, },
{ {
title: '未付金额', title: '未付金额',
field: 'unpaidPrice', field: 'unpaidPrice',
formatter: function(value, row, index) {
if(value == null || value == ''){
return 0;
}
return value;
}
}, },
{ {
title: '采购员', title: '采购员',
@ -209,10 +229,6 @@
title: '录入时间', title: '录入时间',
field: 'createTime', field: 'createTime',
}, },
{
title: '录入人',
field: 'createBy',
},
{ {
title: '更新人', title: '更新人',
field: 'updateBy', field: 'updateBy',
@ -226,11 +242,12 @@
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {
var actions = []; var actions = [];
if (row.accountsPayableStatus !== '4') { if (row.accountsPayableStatus !== '2') {
actions.push('<a class="btn btn-success btn-xs ' + closingFlag + '" href="javascript:void(0)" onclick="confirmAndClose(\'' + row.accountsPayableId + '\')"><i class="fa fa-edit"></i>结案</a> '); actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="confirmAndClose(\'' + row.accountsPayableId + '\')"><i class="fa fa-edit"></i>结案</a> ');
} }
actions.push('<a class="btn btn-primary btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="detail(\'' + row.accountsPayableId + '\')"><i class="fa fa-edit"></i>详情</a> '); actions.push('<a class="btn btn-success btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="detail(\'' + row.accountsPayableId + '\')"><i class="fa fa-edit"></i>详情</a> ');
return actions.join(''); var actionLinks = actions.join('');
return $.table.dropdownToggle(actionLinks);
} }
}] }]
}; };
@ -243,38 +260,8 @@
} }
//结案 //结案
function confirmAndClose(accountsPayableId) { function confirmAndClose(accountsPayableId) {
// 使用layer.confirm替代alert,以实现确认功能 var url = ctx+'financial/payable/closed/'+accountsPayableId;
layer.confirm("确定要结案吗?", { $.modal.open("结案",url);
title: "系统提示",
btn: ['确定', '取消'], // 自定义按钮文本
yes: function(index, layero) {
// 用户点击确定后的操作
$.ajax({
url: ctx + 'financial/payable/payableClosing/' + accountsPayableId,
type: 'GET',
dataType: 'json',
success: function(data) {
if (data.code == web_status.SUCCESS) {
// 成功后提示
layer.close(index); // 关闭当前confirm对话框
$.modal.alert("结案成功。");
$('#bootstrap-table').bootstrapTable('refresh'); // 刷新表格
} else {
layer.close(index); // 关闭当前confirm对话框
$.modal.alertError(data.msg);
}
},
error: function(error) {
layer.close(index); // 关闭当前confirm对话框
$.modal.alertError("结案失败。");
}
});
},
cancel: function(index, layero) {
// 用户点击取消的操作,通常无需处理,直接关闭对话框即可
layer.close(index);
}
});
} }
// 导出 // 导出
function exportExcel() { function exportExcel() {

Loading…
Cancel
Save