fix:付款单申请退款时可修改金额、可分多笔退款
parent
27ac07ad0a
commit
1735901ffe
|
|
@ -104,10 +104,11 @@ export function applyPaymentApi(data) {
|
|||
}
|
||||
|
||||
// 申请退款
|
||||
export function applyRefund(id) {
|
||||
export function applyRefund(data) {
|
||||
return request({
|
||||
url: '/finance/payment/applyRefund/'+id,
|
||||
method: 'get',
|
||||
url: '/finance/payment/applyRefund',
|
||||
method: 'post',
|
||||
data: data,
|
||||
needLoading: true
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,14 +122,14 @@
|
|||
|
||||
<el-dialog title="项目转移" :visible.sync="transferDialogVisible" width="500px" append-to-body>
|
||||
<el-form ref="transferForm" :model="transferForm" :rules="transferRules" label-width="100px">
|
||||
<el-form-item label="原汇智负责人">
|
||||
<el-form-item label="原汇智负责人" label-width="130px">
|
||||
<el-input
|
||||
v-model="transferForm.originalHzSupportUserName"
|
||||
placeholder="原汇智负责人"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="新汇智负责人" prop="hzSupportUserName">
|
||||
<el-form-item label="新汇智负责人" prop="hzSupportUserName" label-width="130px">
|
||||
<el-input
|
||||
v-model="transferForm.hzSupportUserName"
|
||||
placeholder="请选择新汇智负责人"
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@
|
|||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-refresh-right"
|
||||
v-if="scope.row.paymentStatus === '2' && scope.row.refundStatus !== 'REFUND_APPLIED' && scope.row.paymentBillType !== 'REFUND'"
|
||||
v-if="canApplyRefund(scope.row)"
|
||||
@click="handleApplyRefund(scope.row)"
|
||||
>申请退款</el-button>
|
||||
<el-button
|
||||
|
|
@ -304,6 +304,56 @@
|
|||
<el-button type="primary" @click="submitApplyPayment">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 申请退款弹窗 -->
|
||||
<el-dialog title="申请退款" :visible.sync="applyRefundOpen" width="600px" append-to-body>
|
||||
<el-form ref="applyRefundForm" :model="applyRefundForm" :rules="applyRefundRules" label-width="120px">
|
||||
<el-form-item label="退款方式" prop="paymentMethod">
|
||||
<el-select v-model="applyRefundForm.paymentMethod" placeholder="请选择退款方式" style="width: 100%">
|
||||
<el-option
|
||||
v-for="dict in dict.type.payment_method"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="账户名称" prop="payName">
|
||||
<el-input v-model="applyRefundForm.payName" placeholder="请输入账户名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="银行账号" prop="payBankNumber">
|
||||
<el-input v-model="applyRefundForm.payBankNumber" placeholder="请输入银行账号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="银行开户行" prop="payBankOpenAddress">
|
||||
<el-input v-model="applyRefundForm.payBankOpenAddress" placeholder="请输入银行开户行" />
|
||||
</el-form-item>
|
||||
<el-form-item label="银行行号" prop="bankNumber">
|
||||
<el-input v-model="applyRefundForm.bankNumber" placeholder="请输入银行行号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="含税金额" prop="totalPriceWithTax">
|
||||
<el-input v-model="applyRefundForm.totalPriceWithTax" @input="syncApplyRefundAmounts" />
|
||||
</el-form-item>
|
||||
<el-form-item label="剩余可退款金额">
|
||||
<el-input :value="applyRefundMaxAmount" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="未税金额">
|
||||
<el-input v-model="applyRefundForm.totalPriceWithoutTax" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="税额">
|
||||
<el-input v-model="applyRefundForm.taxAmount" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="税率">
|
||||
<el-input :value="formatTaxRate(applyRefundTaxRate)" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input type="textarea" :rows="3" v-model="applyRefundForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="applyRefundOpen = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitApplyRefund">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -377,6 +427,25 @@ export default {
|
|||
// 付款申请弹窗
|
||||
applyPaymentOpen: false,
|
||||
applyPaymentForm: {},
|
||||
// 退款申请弹窗
|
||||
applyRefundOpen: false,
|
||||
applyRefundTaxRate: null,
|
||||
applyRefundOriginalTotalPriceWithTax: null,
|
||||
applyRefundMaxAmount: null,
|
||||
applyRefundCalcWithoutTax: false,
|
||||
applyRefundCalcTaxAmount: false,
|
||||
applyRefundForm: {},
|
||||
applyRefundRules: {
|
||||
paymentMethod: [{ required: true, message: "请选择退款方式", trigger: "change" }],
|
||||
payName: [{ required: true, message: "请输入账户名称", trigger: "blur" }],
|
||||
payBankNumber: [{ required: true, message: "请输入银行账号", trigger: "blur" }],
|
||||
payBankOpenAddress: [{ required: true, message: "请输入银行开户行", trigger: "blur" }],
|
||||
bankNumber: [{ required: true, message: "请输入银行行号", trigger: "blur" }],
|
||||
totalPriceWithTax: [
|
||||
{ required: true, message: "请输入含税金额", trigger: "blur" },
|
||||
{ validator: (rule, value, callback) => this.validateApplyRefundTotalPrice(rule, value, callback), trigger: ["blur", "change"] }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
|
@ -393,7 +462,9 @@ export default {
|
|||
payBankNumber: row.payBankNumber,
|
||||
payBankOpenAddress: row.payBankOpenAddress,
|
||||
bankNumber: row.bankNumber,
|
||||
totalPriceWithTax: row.totalPriceWithTax
|
||||
totalPriceWithTax: row.totalPriceWithTax,
|
||||
totalPriceWithoutTax: row.totalPriceWithoutTax,
|
||||
taxAmount: row.taxAmount
|
||||
};
|
||||
this.applyPaymentOpen = true;
|
||||
},
|
||||
|
|
@ -501,12 +572,105 @@ export default {
|
|||
},
|
||||
/** 申请退款按钮操作 */
|
||||
handleApplyRefund(row) {
|
||||
this.$modal.confirm('收款单退款申请,确认提交至财务审批吗?').then(() => {
|
||||
return applyRefund(row.id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("申请退款成功");
|
||||
}).catch(() => {});
|
||||
this.applyRefundTaxRate = row.taxRate || null;
|
||||
this.applyRefundOriginalTotalPriceWithTax = row.totalPriceWithTax || null;
|
||||
this.applyRefundMaxAmount = row.remainingRefundAmount || row.totalPriceWithTax || null;
|
||||
this.applyRefundCalcWithoutTax = this.isValidRefundAmount(row.totalPriceWithoutTax);
|
||||
this.applyRefundCalcTaxAmount = this.isValidRefundAmount(row.taxAmount);
|
||||
this.applyRefundForm = {
|
||||
id: row.id,
|
||||
paymentMethod: row.paymentMethod || null,
|
||||
payName: row.payName || null,
|
||||
payBankNumber: row.payBankNumber || null,
|
||||
payBankOpenAddress: row.payBankOpenAddress || null,
|
||||
bankNumber: row.bankNumber || null,
|
||||
totalPriceWithTax: row.remainingRefundAmount || row.totalPriceWithTax || null,
|
||||
totalPriceWithoutTax: null,
|
||||
taxAmount: null,
|
||||
remark: null
|
||||
};
|
||||
this.syncApplyRefundAmounts();
|
||||
this.applyRefundOpen = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs["applyRefundForm"] && this.$refs["applyRefundForm"].clearValidate();
|
||||
});
|
||||
},
|
||||
canApplyRefund(row) {
|
||||
const remainingRefundAmount = Number(row.remainingRefundAmount);
|
||||
return row.paymentBillType !== 'REFUND'
|
||||
&& row.paymentStatus === '2'
|
||||
&& ['WAIT_REFUNDED', 'PART_REFUNDED', null, undefined, ''].includes(row.refundStatus)
|
||||
&& !Number.isNaN(remainingRefundAmount)
|
||||
&& remainingRefundAmount > 0;
|
||||
},
|
||||
validateApplyRefundTotalPrice(rule, value, callback) {
|
||||
if (value === null || value === undefined || value === '') {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
const currentValue = Number(value);
|
||||
const maxValue = Number(this.applyRefundMaxAmount);
|
||||
if (Number.isNaN(currentValue)) {
|
||||
callback(new Error("含税金额格式不正确"));
|
||||
return;
|
||||
}
|
||||
if (currentValue <= 0) {
|
||||
callback(new Error("含税金额必须大于0"));
|
||||
return;
|
||||
}
|
||||
if (!Number.isNaN(maxValue) && currentValue > maxValue) {
|
||||
callback(new Error("含税金额不能大于剩余可退款金额"));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
},
|
||||
syncApplyRefundAmounts() {
|
||||
const totalPriceWithTax = Number(this.applyRefundForm.totalPriceWithTax);
|
||||
const taxRate = Number(this.applyRefundTaxRate);
|
||||
if (Number.isNaN(totalPriceWithTax) || this.applyRefundForm.totalPriceWithTax === '' || this.applyRefundForm.totalPriceWithTax === null) {
|
||||
this.applyRefundForm.totalPriceWithoutTax = null;
|
||||
this.applyRefundForm.taxAmount = null;
|
||||
return;
|
||||
}
|
||||
if (Number.isNaN(taxRate)) {
|
||||
this.applyRefundForm.totalPriceWithoutTax = this.applyRefundCalcWithoutTax ? totalPriceWithTax.toFixed(2) : null;
|
||||
this.applyRefundForm.taxAmount = this.applyRefundCalcTaxAmount ? '0.00' : null;
|
||||
return;
|
||||
}
|
||||
const taxAmount = (totalPriceWithTax * taxRate).toFixed(2);
|
||||
const totalPriceWithoutTax = (totalPriceWithTax - Number(taxAmount)).toFixed(2);
|
||||
this.applyRefundForm.taxAmount = this.applyRefundCalcTaxAmount ? taxAmount : null;
|
||||
this.applyRefundForm.totalPriceWithoutTax = this.applyRefundCalcWithoutTax ? totalPriceWithoutTax : null;
|
||||
},
|
||||
isValidRefundAmount(value) {
|
||||
const amount = Number(value);
|
||||
return value !== null && value !== undefined && value !== '' && !Number.isNaN(amount) && amount !== 0;
|
||||
},
|
||||
submitApplyRefund() {
|
||||
this.$refs["applyRefundForm"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
const submitData = {
|
||||
id: this.applyRefundForm.id,
|
||||
paymentMethod: this.applyRefundForm.paymentMethod,
|
||||
payName: this.applyRefundForm.payName,
|
||||
payBankNumber: this.applyRefundForm.payBankNumber,
|
||||
payBankOpenAddress: this.applyRefundForm.payBankOpenAddress,
|
||||
bankNumber: this.applyRefundForm.bankNumber,
|
||||
totalPriceWithTax: this.applyRefundForm.totalPriceWithTax,
|
||||
totalPriceWithoutTax: this.applyRefundForm.totalPriceWithoutTax,
|
||||
taxAmount: this.applyRefundForm.taxAmount,
|
||||
remark: this.applyRefundForm.remark
|
||||
};
|
||||
this.$modal.confirm('付款单退款申请,确认提交至财务审批吗?').then(() => {
|
||||
return applyRefund(submitData);
|
||||
}).then(() => {
|
||||
this.applyRefundOpen = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("申请退款成功");
|
||||
}).catch(() => {});
|
||||
});
|
||||
},
|
||||
handleDelete(id){
|
||||
this.$modal.confirm('确认删除该笔预付单数据吗?').then(() => {
|
||||
|
|
@ -559,6 +723,10 @@ export default {
|
|||
if (value === null || value === undefined || value === '') return '';
|
||||
return value.substring(0, 10);
|
||||
},
|
||||
formatTaxRate(value) {
|
||||
if (value === null || value === undefined || value === '') return '';
|
||||
return `${Number(value) * 100}%`;
|
||||
},
|
||||
handleUpdatePaymentBillSubmit(form) {
|
||||
console.log(form);
|
||||
updatePaymentBill(form).then(response => {
|
||||
|
|
|
|||
|
|
@ -259,11 +259,11 @@ public class OmsPaymentBillController extends BaseController
|
|||
/**
|
||||
* 申请退款
|
||||
*/
|
||||
@GetMapping("/applyRefund/{id}")
|
||||
@PostMapping("/applyRefund")
|
||||
@ResponseBody
|
||||
public AjaxResult applyRefund(@PathVariable("id") Long id) {
|
||||
public AjaxResult applyRefund(@RequestBody OmsPaymentBill paymentBill) {
|
||||
try {
|
||||
return omsPaymentBillService.applyRefund(id);
|
||||
return omsPaymentBillService.applyRefund(paymentBill);
|
||||
} catch (Exception e) {
|
||||
logger.error("申请退款失败", e);
|
||||
return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ public class OmsPaymentBill extends BaseEntity
|
|||
@Excel(name = "税额")
|
||||
private BigDecimal taxAmount;
|
||||
|
||||
/** 税率 */
|
||||
private BigDecimal taxRate;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
|
|
@ -130,6 +133,10 @@ public class OmsPaymentBill extends BaseEntity
|
|||
|
||||
/** 退款状态 */
|
||||
private String refundStatus;
|
||||
/** 已申请退款金额 */
|
||||
private BigDecimal refundedAmount;
|
||||
/** 剩余可退款金额 */
|
||||
private BigDecimal remainingRefundAmount;
|
||||
private String hzUserName;
|
||||
private Long approveUser;
|
||||
private Date applyTime;
|
||||
|
|
@ -194,8 +201,8 @@ public class OmsPaymentBill extends BaseEntity
|
|||
@Getter
|
||||
public enum RefundStatusEnum {
|
||||
|
||||
/** 应付单生成 */
|
||||
REFUNDED("REFUND_APPLIED", "已申请退款"),
|
||||
REFUNDED("REFUND_APPLIED", "全部退款"),
|
||||
PART_REFUNDED("PART_REFUNDED", "部分退款"),
|
||||
WAIT_REFUNDED("WAIT_REFUNDED", "未退款")
|
||||
|
||||
;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Param;
|
|||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface OmsPayablePaymentDetailMapper {
|
||||
public int insertOmsPayablePaymentDetail(OmsPayablePaymentDetail omsPayablePaymentDetail);
|
||||
|
|
@ -19,6 +20,8 @@ public interface OmsPayablePaymentDetailMapper {
|
|||
|
||||
List<OmsPayablePaymentDetail> selectByPaymentPlanIds(@Param("paymentPlanIds") List<Long> paymentPlanIds);
|
||||
|
||||
List<Map<String, Object>> listPaymentBillTaxRate(@Param("paymentBillCodeList") List<String> paymentBillCodeList);
|
||||
|
||||
int clearWriteOffByWriteOffId(Long[] ids);
|
||||
|
||||
List<PaymentBillPayableDetailDTO> listPayableByWriteOffId(List<Long> writeOffIds);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.ruoyi.sip.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPaymentBill;
|
||||
import com.ruoyi.sip.domain.dto.PaymentBillDetailDTO;
|
||||
|
|
@ -100,4 +101,7 @@ public interface OmsPaymentBillMapper
|
|||
|
||||
List<OmsPaymentBill> listPreResidueAmountByVendorCodeList(List<String> collect);
|
||||
|
||||
List<Map<String, Object>> listRefundSummaryByOriginalBillIds(@Param("originalBillIds") List<Long> originalBillIds,
|
||||
@Param("excludeApproveStatus") String excludeApproveStatus);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
|
|||
import com.ruoyi.sip.domain.dto.ProjectPaymentBillDto;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
public interface IOmsPayablePaymentDetailService {
|
||||
|
|
@ -21,6 +22,8 @@ public interface IOmsPayablePaymentDetailService {
|
|||
|
||||
List<OmsPayablePaymentDetail> listBypaymentCode(String paymentBillCode);
|
||||
|
||||
Map<String, java.math.BigDecimal> getPaymentBillTaxRateMap(List<String> paymentBillCodeList);
|
||||
|
||||
List<OmsPayablePaymentDetail> listByWriteOffIds(Long[] ids);
|
||||
|
||||
void insertBatch(List<OmsPayablePaymentDetail> detailList);
|
||||
|
|
|
|||
|
|
@ -86,10 +86,10 @@ public interface IOmsPaymentBillService
|
|||
/**
|
||||
* 申请退款
|
||||
*
|
||||
* @param originalPaymentId 原始付款单ID
|
||||
* @param omsPaymentBill 退款申请参数
|
||||
* @return 结果
|
||||
*/
|
||||
public AjaxResult applyRefund(Long originalPaymentId);
|
||||
public AjaxResult applyRefund(OmsPaymentBill omsPaymentBill);
|
||||
|
||||
/**
|
||||
* 上传退款图
|
||||
|
|
|
|||
|
|
@ -125,6 +125,26 @@ public class OmsPayablePaymentDetailServiceImpl implements IOmsPayablePaymentDet
|
|||
return omsPayablePaymentDetailMapper.list(omsPayablePaymentDetail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, BigDecimal> getPaymentBillTaxRateMap(List<String> paymentBillCodeList) {
|
||||
if (CollUtil.isEmpty(paymentBillCodeList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<Map<String, Object>> taxRateList = omsPayablePaymentDetailMapper.listPaymentBillTaxRate(paymentBillCodeList);
|
||||
if (CollUtil.isEmpty(taxRateList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, BigDecimal> taxRateMap = new HashMap<>();
|
||||
for (Map<String, Object> item : taxRateList) {
|
||||
Object paymentBillCode = item.get("paymentBillCode");
|
||||
Object taxRate = item.get("taxRate");
|
||||
if (paymentBillCode instanceof String) {
|
||||
taxRateMap.put((String) paymentBillCode, taxRate instanceof BigDecimal ? (BigDecimal) taxRate : null);
|
||||
}
|
||||
}
|
||||
return taxRateMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertBatch(List<OmsPayablePaymentDetail> detailList) {
|
||||
omsPayablePaymentDetailMapper.insertBatch(detailList);
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
public OmsPaymentBill selectOmsPaymentBillById(Long id)
|
||||
{
|
||||
OmsPaymentBill omsPaymentBill = omsPaymentBillMapper.selectOmsPaymentBillById(id);
|
||||
fillRefundSummary(Collections.singletonList(omsPaymentBill));
|
||||
if (omsPaymentBill != null && StrUtil.isNotEmpty(omsPaymentBill.getFileId())) {
|
||||
List<Integer> idList = StrUtil.split(omsPaymentBill.getFileId(), ',')
|
||||
.stream()
|
||||
|
|
@ -110,7 +111,24 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
@Override
|
||||
public List<OmsPaymentBill> selectOmsPaymentBillList(OmsPaymentBill omsPaymentBill)
|
||||
{
|
||||
return omsPaymentBillMapper.selectOmsPaymentBillList(omsPaymentBill);
|
||||
List<OmsPaymentBill> paymentBillList = omsPaymentBillMapper.selectOmsPaymentBillList(omsPaymentBill);
|
||||
if (CollUtil.isEmpty(paymentBillList)) {
|
||||
return paymentBillList;
|
||||
}
|
||||
fillRefundSummary(paymentBillList);
|
||||
List<String> paymentBillCodeList = paymentBillList.stream()
|
||||
.map(OmsPaymentBill::getPaymentBillCode)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
Map<String, BigDecimal> taxRateMap = detailService.getPaymentBillTaxRateMap(paymentBillCodeList);
|
||||
if (CollUtil.isEmpty(taxRateMap)) {
|
||||
return paymentBillList;
|
||||
}
|
||||
for (OmsPaymentBill paymentBill : paymentBillList) {
|
||||
paymentBill.setTaxRate(taxRateMap.get(paymentBill.getPaymentBillCode()));
|
||||
}
|
||||
return paymentBillList;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -256,6 +274,95 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
return paymentBillType;
|
||||
}
|
||||
|
||||
private void fillRefundSummary(List<OmsPaymentBill> paymentBillList) {
|
||||
if (CollUtil.isEmpty(paymentBillList)) {
|
||||
return;
|
||||
}
|
||||
List<Long> originalBillIds = paymentBillList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> !OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(item.getPaymentBillType()))
|
||||
.map(OmsPaymentBill::getId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(originalBillIds)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, BigDecimal> refundedAmountMap = getRefundedAmountMap(originalBillIds);
|
||||
for (OmsPaymentBill paymentBill : paymentBillList) {
|
||||
if (paymentBill == null || OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(paymentBill.getPaymentBillType()) || paymentBill.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal totalAmount = defaultAmount(paymentBill.getTotalPriceWithTax());
|
||||
BigDecimal refundedAmount = refundedAmountMap.getOrDefault(paymentBill.getId(), BigDecimal.ZERO);
|
||||
BigDecimal remainingRefundAmount = totalAmount.subtract(refundedAmount);
|
||||
if (remainingRefundAmount.compareTo(BigDecimal.ZERO) < 0) {
|
||||
remainingRefundAmount = BigDecimal.ZERO;
|
||||
}
|
||||
paymentBill.setRefundedAmount(refundedAmount);
|
||||
paymentBill.setRemainingRefundAmount(remainingRefundAmount);
|
||||
paymentBill.setRefundStatus(resolveRefundStatus(totalAmount, refundedAmount));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, BigDecimal> getRefundedAmountMap(List<Long> originalBillIds) {
|
||||
if (CollUtil.isEmpty(originalBillIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<Map<String, Object>> summaryList = omsPaymentBillMapper.listRefundSummaryByOriginalBillIds(
|
||||
originalBillIds, ApproveStatusEnum.APPROVE_REJECT.getCode());
|
||||
if (CollUtil.isEmpty(summaryList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<Long, BigDecimal> refundedAmountMap = new HashMap<>();
|
||||
for (Map<String, Object> summary : summaryList) {
|
||||
Object originalBillId = summary.get("originalBillId");
|
||||
Object refundedAmount = summary.get("refundedAmount");
|
||||
if (originalBillId == null) {
|
||||
continue;
|
||||
}
|
||||
Long billId = Long.valueOf(String.valueOf(originalBillId));
|
||||
BigDecimal amount = refundedAmount instanceof BigDecimal
|
||||
? (BigDecimal) refundedAmount
|
||||
: new BigDecimal(String.valueOf(refundedAmount));
|
||||
refundedAmountMap.put(billId, amount);
|
||||
}
|
||||
return refundedAmountMap;
|
||||
}
|
||||
|
||||
private void refreshOriginalBillRefundStatus(Long originalBillId) {
|
||||
if (originalBillId == null) {
|
||||
return;
|
||||
}
|
||||
OmsPaymentBill originalBill = omsPaymentBillMapper.selectOmsPaymentBillById(originalBillId);
|
||||
if (originalBill == null || OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(originalBill.getPaymentBillType())) {
|
||||
return;
|
||||
}
|
||||
BigDecimal totalAmount = defaultAmount(originalBill.getTotalPriceWithTax());
|
||||
BigDecimal refundedAmount = getRefundedAmountMap(Collections.singletonList(originalBillId))
|
||||
.getOrDefault(originalBillId, BigDecimal.ZERO);
|
||||
OmsPaymentBill updateBill = new OmsPaymentBill();
|
||||
updateBill.setId(originalBillId);
|
||||
updateBill.setRefundStatus(resolveRefundStatus(totalAmount, refundedAmount));
|
||||
omsPaymentBillMapper.updateOmsPaymentBill(updateBill);
|
||||
}
|
||||
|
||||
private BigDecimal defaultAmount(BigDecimal amount) {
|
||||
return Optional.ofNullable(amount).orElse(BigDecimal.ZERO).abs();
|
||||
}
|
||||
|
||||
private String resolveRefundStatus(BigDecimal totalAmount, BigDecimal refundedAmount) {
|
||||
BigDecimal total = defaultAmount(totalAmount);
|
||||
BigDecimal refunded = defaultAmount(refundedAmount);
|
||||
if (refunded.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return OmsPaymentBill.RefundStatusEnum.WAIT_REFUNDED.getCode();
|
||||
}
|
||||
if (refunded.compareTo(total) < 0) {
|
||||
return OmsPaymentBill.RefundStatusEnum.PART_REFUNDED.getCode();
|
||||
}
|
||||
return OmsPaymentBill.RefundStatusEnum.REFUNDED.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增采购付款单
|
||||
*
|
||||
|
|
@ -489,10 +596,14 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
}
|
||||
|
||||
private void handleRejectOrder(String businessKey) {
|
||||
OmsPaymentBill existBill = omsPaymentBillMapper.selectOmsPaymentBillByCode(businessKey);
|
||||
OmsPaymentBill omsPaymentBill = new OmsPaymentBill();
|
||||
omsPaymentBill.setPaymentBillCode(businessKey);
|
||||
omsPaymentBill.setApproveStatus(ApproveStatusEnum.APPROVE_REJECT.getCode());
|
||||
omsPaymentBillMapper.updateOmsPaymentBillByCode(omsPaymentBill);
|
||||
if (existBill != null && OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(existBill.getPaymentBillType())) {
|
||||
refreshOriginalBillRefundStatus(existBill.getOriginalBillId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -554,7 +665,14 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult applyRefund(Long originalPaymentId) {
|
||||
public AjaxResult applyRefund(OmsPaymentBill omsPaymentBill) {
|
||||
if (omsPaymentBill == null || omsPaymentBill.getId() == null) {
|
||||
return AjaxResult.error("原始付款单ID不能为空");
|
||||
}
|
||||
if (omsPaymentBill.getTotalPriceWithTax() == null || omsPaymentBill.getTotalPriceWithTax().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return AjaxResult.error("退款金额必须大于0");
|
||||
}
|
||||
Long originalPaymentId = omsPaymentBill.getId();
|
||||
// 1. 验证原始付款单
|
||||
OmsPaymentBill originalBill = selectOmsPaymentBillById(originalPaymentId);
|
||||
if (originalBill == null) {
|
||||
|
|
@ -563,24 +681,32 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
if (!OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode().equals(originalBill.getPaymentStatus())) {
|
||||
return AjaxResult.error("只有已付款的订单才能申请退款");
|
||||
}
|
||||
if (OmsPaymentBill.RefundStatusEnum.REFUNDED.getCode().equals(originalBill.getRefundStatus())) {
|
||||
return AjaxResult.error("该付款单已申请过退款,请勿重复操作");
|
||||
BigDecimal originalAmount = defaultAmount(originalBill.getTotalPriceWithTax());
|
||||
BigDecimal appliedRefundAmount = getRefundedAmountMap(Collections.singletonList(originalPaymentId))
|
||||
.getOrDefault(originalPaymentId, BigDecimal.ZERO);
|
||||
BigDecimal remainingRefundAmount = originalAmount.subtract(appliedRefundAmount);
|
||||
if (remainingRefundAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return AjaxResult.error("该付款单已无可退款金额");
|
||||
}
|
||||
BigDecimal currentRefundAmount = defaultAmount(omsPaymentBill.getTotalPriceWithTax());
|
||||
if (currentRefundAmount.compareTo(remainingRefundAmount) > 0) {
|
||||
return AjaxResult.error("当前退款金额超出可退款金额,剩余可退款金额:" + remainingRefundAmount);
|
||||
}
|
||||
|
||||
// 2. 创建新的退款单
|
||||
OmsPaymentBill refundBill = new OmsPaymentBill();
|
||||
|
||||
// 复制属性并取反金额
|
||||
refundBill.setTotalPriceWithTax(originalBill.getTotalPriceWithTax().negate());
|
||||
refundBill.setTotalPriceWithoutTax(originalBill.getTotalPriceWithoutTax().negate());
|
||||
refundBill.setTaxAmount(originalBill.getTaxAmount().negate());
|
||||
refundBill.setTotalPriceWithTax(currentRefundAmount.negate());
|
||||
refundBill.setTotalPriceWithoutTax(defaultAmount(omsPaymentBill.getTotalPriceWithoutTax()).negate());
|
||||
refundBill.setTaxAmount(defaultAmount(omsPaymentBill.getTaxAmount()).negate());
|
||||
|
||||
refundBill.setVendorCode(originalBill.getVendorCode());
|
||||
refundBill.setOrderCode(originalBill.getOrderCode());
|
||||
refundBill.setPayName(originalBill.getPayName());
|
||||
refundBill.setPayBankNumber(originalBill.getPayBankNumber());
|
||||
refundBill.setPayBankOpenAddress(originalBill.getPayBankOpenAddress());
|
||||
refundBill.setBankNumber(originalBill.getBankNumber());
|
||||
refundBill.setPayName(StrUtil.isNotBlank(omsPaymentBill.getPayName()) ? omsPaymentBill.getPayName() : originalBill.getPayName());
|
||||
refundBill.setPayBankNumber(StrUtil.isNotBlank(omsPaymentBill.getPayBankNumber()) ? omsPaymentBill.getPayBankNumber() : originalBill.getPayBankNumber());
|
||||
refundBill.setPayBankOpenAddress(StrUtil.isNotBlank(omsPaymentBill.getPayBankOpenAddress()) ? omsPaymentBill.getPayBankOpenAddress() : originalBill.getPayBankOpenAddress());
|
||||
refundBill.setBankNumber(StrUtil.isNotBlank(omsPaymentBill.getBankNumber()) ? omsPaymentBill.getBankNumber() : originalBill.getBankNumber());
|
||||
refundBill.setPaymentBillCode(generatePaymentBillCode());
|
||||
// 设置新属性
|
||||
refundBill.setPaymentBillType(OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode());
|
||||
|
|
@ -588,14 +714,15 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
refundBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
|
||||
refundBill.setOriginalBillId(originalPaymentId);
|
||||
refundBill.setPaymentTime(null);
|
||||
refundBill.setPaymentMethod(originalBill.getPaymentMethod());
|
||||
refundBill.setRemark("退款-关联原付款单:" + originalBill.getPaymentBillCode());
|
||||
refundBill.setPaymentMethod(StrUtil.isNotBlank(omsPaymentBill.getPaymentMethod()) ? omsPaymentBill.getPaymentMethod() : originalBill.getPaymentMethod());
|
||||
refundBill.setRemark(StrUtil.isNotBlank(omsPaymentBill.getRemark())
|
||||
? "退款-关联原付款单:" + originalBill.getPaymentBillCode() + "," + omsPaymentBill.getRemark()
|
||||
: "退款-关联原付款单:" + originalBill.getPaymentBillCode());
|
||||
|
||||
insertOmsPaymentBill(refundBill);
|
||||
|
||||
// 3. 更新原始付款单状态
|
||||
originalBill.setRefundStatus(OmsPaymentBill.RefundStatusEnum.REFUNDED.getCode());
|
||||
updateOmsPaymentBill(originalBill);
|
||||
refreshOriginalBillRefundStatus(originalPaymentId);
|
||||
//4 创建付款明细
|
||||
detailService.applyRefund(originalBill.getPaymentBillCode(),refundBill.getPaymentBillCode());
|
||||
//5. 开始退款审批流程
|
||||
|
|
@ -628,8 +755,8 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
|
||||
// 更新付款单
|
||||
|
||||
// 更新为“已付款”
|
||||
paymentBill.setPaymentStatus(OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode());
|
||||
// 退款单上传退款图后,标记为已退款
|
||||
paymentBill.setPaymentStatus(OmsPaymentBill.PaymentStatusEnum.REFUNDED.getCode());
|
||||
paymentBill.setActualPaymentTime(DateUtils.getNowDate());
|
||||
updateOmsPaymentBill(paymentBill);
|
||||
if (!paymentBill.getPaymentBillType().equals(OmsPaymentBill.PaymentBillTypeEnum.PRE_PAYMENT.getCode())) {
|
||||
|
|
@ -673,10 +800,7 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
// 撤销退款单
|
||||
deleteOmsPaymentBillById(existBill.getId());
|
||||
detailService.deleteByPaymentCode(existBill.getPaymentBillCode());
|
||||
OmsPaymentBill omsPaymentBill = new OmsPaymentBill();
|
||||
omsPaymentBill.setId(existBill.getOriginalBillId());
|
||||
omsPaymentBill.setRefundStatus(OmsPaymentBill.RefundStatusEnum.WAIT_REFUNDED.getCode());
|
||||
updateOmsPaymentBill(omsPaymentBill);
|
||||
refreshOriginalBillRefundStatus(existBill.getOriginalBillId());
|
||||
}else{
|
||||
if (OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode().equals(existBill.getPaymentStatus())){
|
||||
return AjaxResult.error("该退款单已付款成功,无法撤销");
|
||||
|
|
@ -851,8 +975,9 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
|
|||
|
||||
@Override
|
||||
public OmsPaymentBill selectOmsPaymentBillByCode(String paymentBillCode) {
|
||||
|
||||
return omsPaymentBillMapper.selectOmsPaymentBillByCode(paymentBillCode);
|
||||
OmsPaymentBill paymentBill = omsPaymentBillMapper.selectOmsPaymentBillByCode(paymentBillCode);
|
||||
fillRefundSummary(Collections.singletonList(paymentBill));
|
||||
return paymentBill;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -121,6 +121,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</foreach>
|
||||
ORDER BY t1.create_time DESC
|
||||
</select>
|
||||
<select id="listPaymentBillTaxRate" resultType="java.util.HashMap">
|
||||
select
|
||||
t1.payment_bill_code as paymentBillCode,
|
||||
case
|
||||
when count(distinct t2.tax_rate) = 1 then max(t2.tax_rate)
|
||||
else null
|
||||
end as taxRate
|
||||
from oms_payable_payment_detail t1
|
||||
left join oms_payable_bill t2 on t1.payable_bill_id = t2.id
|
||||
where t1.payment_bill_code in
|
||||
<foreach item="item" collection="paymentBillCodeList" separator="," open="(" close=")" index="">
|
||||
#{item}
|
||||
</foreach>
|
||||
group by t1.payment_bill_code
|
||||
</select>
|
||||
<select id="listPayableByPaymentCode" resultType="com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO">
|
||||
select t1.payment_amount, t1.payable_bill_id, t2.payable_bill_code, t3.project_id, t4.project_name, t4.project_code,
|
||||
t2.total_price_with_tax,t2.product_type, t5.product_code, t5.model, t5.product_name
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<result property="payBankOpenAddress" column="pay_bank_open_address" />
|
||||
<result property="bankNumber" column="bank_number" />
|
||||
<result property="fileId" column="file_id" />
|
||||
|
||||
<result property="originalBillId" column="original_bill_id" />
|
||||
<result property="refundStatus" column="refund_status" />
|
||||
</resultMap>
|
||||
|
||||
|
|
@ -103,6 +103,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
pb.pay_bank_open_address,
|
||||
pb.bank_number,
|
||||
pb.file_id,
|
||||
pb.original_bill_id,
|
||||
pb.refund_status,
|
||||
ovi.vendor_name,
|
||||
ovi.pay_type,
|
||||
|
|
@ -272,6 +273,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="payBankOpenAddress != null">pay_bank_open_address,</if>
|
||||
<if test="bankNumber != null">bank_number,</if>
|
||||
<if test="fileId != null">file_id,</if>
|
||||
<if test="originalBillId != null">original_bill_id,</if>
|
||||
<if test="refundStatus != null">refund_status,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
|
|
@ -303,6 +305,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="payBankOpenAddress != null">#{payBankOpenAddress},</if>
|
||||
<if test="bankNumber != null">#{bankNumber},</if>
|
||||
<if test="fileId != null">#{fileId},</if>
|
||||
<if test="originalBillId != null">#{originalBillId},</if>
|
||||
<if test="refundStatus != null">#{refundStatus},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
|
@ -338,7 +341,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="payBankOpenAddress != null">pay_bank_open_address = #{payBankOpenAddress},</if>
|
||||
<if test="bankNumber != null">bank_number = #{bankNumber},</if>
|
||||
<if test="fileId != null">file_id = #{fileId},</if>
|
||||
|
||||
<if test="originalBillId != null">original_bill_id = #{originalBillId},</if>
|
||||
<if test="refundStatus != null">refund_status = #{refundStatus},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
|
|
@ -372,7 +375,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="payBankNumber != null">pay_bank_number = #{payBankNumber},</if>
|
||||
<if test="payBankOpenAddress != null">pay_bank_open_address = #{payBankOpenAddress},</if>
|
||||
<if test="bankNumber != null">bank_number = #{bankNumber},</if>
|
||||
|
||||
<if test="originalBillId != null">original_bill_id = #{originalBillId},</if>
|
||||
<if test="refundStatus != null">refund_status = #{refundStatus},</if>
|
||||
</trim>
|
||||
where payment_bill_code = #{paymentBillCode}
|
||||
|
|
@ -515,5 +518,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
vendor_code
|
||||
</select>
|
||||
|
||||
<select id="listRefundSummaryByOriginalBillIds" resultType="java.util.HashMap">
|
||||
select
|
||||
original_bill_id as originalBillId,
|
||||
ifnull(sum(abs(total_price_with_tax)), 0) as refundedAmount
|
||||
from oms_payment_bill
|
||||
where del_flag = '0'
|
||||
and payment_bill_type = 'REFUND'
|
||||
and original_bill_id in
|
||||
<foreach item="item" collection="originalBillIds" separator="," open="(" close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
<if test="excludeApproveStatus != null and excludeApproveStatus != ''">
|
||||
and approve_status != #{excludeApproveStatus}
|
||||
</if>
|
||||
group by original_bill_id
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
</mapper>
|
||||
|
|
|
|||
Loading…
Reference in New Issue