feat(finance): 实现发票核销功能

- 新增发票核销API接口文件,包含列表查询、详情获取和删除功能
- 添加应收票据核销单服务接口和实现类
- 创建应收票据核销单数据实体和数据库映射
- 实现发票核销相关的数据库操作和业务逻辑
- 添加核销详情处理和批量更新功能
- 实现系统自动收票核销机制
- 更新发票单据服务以支持核销操作
- 添加核销记录的增删改查控制器接口
- 实现核销单据的查询和导出功能
dev_1.0.1
chenhao 2025-12-24 16:35:26 +08:00
parent fb3f3c721e
commit 8ea80a4dbe
20 changed files with 1416 additions and 17 deletions

View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 查询核销记录列表
export function listInvoiceWriteOff(query) {
return request({
url: '/finance/invoice/writeoff/list',
method: 'get',
params: query
})
}
// 查询核销详情
export function getInvoiceWriteoff(id) {
return request({
url: '/finance/invoice/writeoff/' + id,
method: 'get'
})
}
// 删除核销记录
export function delInvoiceWriteoff(ids) {
return request({
url: '/finance/invoice/writeoff/' + ids,
method: 'delete'
})
}

View File

@ -0,0 +1,90 @@
<template>
<el-drawer
title="核销详情"
:visible.sync="visible"
direction="rtl"
size="60%"
@close="handleClose"
>
<div class="drawer-body" v-if="detail">
<div class="section">
<el-divider content-position="left">开票单信息</el-divider>
<el-table :data="[detail]" border stripe>
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="writeOffAmount" label="本次核销含税总价(元)" align="center"></el-table-column>
<el-table-column prop="partnerName" label="进货商名称" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="invoiceBillCode" label="销售-开票单编号" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="createTime" label="开票单生成时间" align="center" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.invoiceBill.createTime) }}</span>
</template>
</el-table-column>
<!-- <el-table-column prop="invoiceBillType" label="开票单类型" align="center">-->
<!-- <template slot-scope="scope">-->
<!-- <dict-tag :options="dict.type.invoice_bill_type" :value="scope.row.invoiceBill.invoiceBillType"/>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table>
</div>
<div class="section">
<el-divider content-position="left">应收单明细</el-divider>
<el-table :data="detail.detailList" border stripe>
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="receiptAmount" label="本次核销金额(元)" align="center"></el-table-column>
<el-table-column prop="partnerName" label="进货商名称" align="center"></el-table-column>
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="createTime" label="应收单生成时间" align="center"></el-table-column>
</el-table>
</div>
</div>
</el-drawer>
</template>
<script>
export default {
name: "WriteOffDetailDrawer",
props: {
visible: {
type: Boolean,
default: false,
},
detail: {
type: Object,
default: () => ({}),
},
},
dicts: ['finance_write_off_type'],
methods: {
handleClose() {
this.$emit("update:visible", false);
},
},
};
</script>
<style scoped>
.drawer-body {
padding: 20px;
height: calc(100vh - 80px);
overflow-y: auto;
}
.details-container {
border: 1px solid #EBEEF5;
padding: 15px;
border-radius: 4px;
background-color: #f8f8f9;
}
.detail-item {
margin-bottom: 12px;
font-size: 14px;
color: #606266;
line-height: 1.5;
}
.section {
margin-bottom: 25px;
}
</style>

View File

@ -0,0 +1,236 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="核销序号" prop="writeOffCode">
<el-input
v-model="queryParams.writeOffCode"
placeholder="请输入核销序号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="销售-应收单编号" prop="receivableBillCode">
<el-input
v-model="queryParams.receivableBillCode"
placeholder="请输入销售应收单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="销售-开票单编号" prop="invoiceBillCode">
<el-input
v-model="queryParams.invoiceBillCode"
placeholder="请输入销售开票单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="进货商名称" prop="partnerName">
<el-input
v-model="queryParams.partnerName"
placeholder="请输入进货商名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="核销类型" prop="writeOffType">
<el-select v-model="queryParams.writeOffType" placeholder="请选择核销类型" clearable>
<el-option
v-for="dict in dict.type.finance_write_off_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="核销时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>反核销</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="writeOffList" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"/>
<el-table-column label="核销序号" align="center" prop="writeOffCode" />
<el-table-column label="核销人" align="center" prop="createByName" >
<template slot-scope="scope">
<span>{{ scope.row.createByName || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="核销时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="销售开票单编号" align="center" prop="invoiceBillCode" />
<el-table-column label="代理商名称" align="center" prop="partnerName" />
<el-table-column label="核销类型" align="center" prop="writeOffType">
<template slot-scope="scope">
<dict-tag :options="dict.type.finance_write_off_type" :value="scope.row.writeOffType"/>
</template>
</el-table-column>
<el-table-column label="核销含税总价(元)" align="center" prop="writeOffAmount" />
<el-table-column label="核销未税总价(元)" align="center" prop="writeOffAmountWithoutTax" />
<el-table-column label="核销税额(元)" align="center" prop="writeOffTaxAmount" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
>查看详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>反核销</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 详情抽屉 -->
<write-off-detail-drawer :visible.sync="open" :detail="form" />
</div>
</template>
<script>
import { listInvoiceWriteOff, getInvoiceWriteoff, delInvoiceWriteoff } from "@/api/finance/invoiceWriteoff";
import { listPartner } from "@/api/system/partner";
import WriteOffDetailDrawer from "./WriteOffDetailDrawer";
export default {
name: "WriteOffInvoiceRecord",
components: {
WriteOffDetailDrawer
},
dicts: ['finance_write_off_type'],
data() {
return {
//
loading: true,
//
ids: [],
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
writeOffList: [],
//
partnerOptions: [],
//
title: "",
//
open: false,
//
dateRange: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
writeOffCode: null,
receivableBillCode: null,
invoiceBillCode: null,
partnerName: null,
writeOffType: null,
},
//
form: {}
};
},
created() {
this.getList();
this.getPartnerList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
listInvoiceWriteOff(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.writeOffList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 查询代理商列表 */
getPartnerList() {
listPartner().then(response => {
this.partnerOptions = response.rows;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 查看详情 */
handleDetail(row) {
this.loading = true;
getInvoiceWriteoff(row.id).then(response => {
this.form = response.data;
this.open = true;
this.title = "核销详情";
this.loading = false;
});
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.multiple = !selection.length
},
/** 反核销按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认反核销核销序号为"' + ids + '"的数据项?').then(function() {
return delInvoiceWriteoff(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("反核销成功");
}).catch(() => {});
}
}
};
</script>

View File

@ -0,0 +1,99 @@
package com.ruoyi.sip.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.sip.service.IOmsInvoiceBillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff;
import com.ruoyi.sip.service.IOmsReceivableInvoiceWriteOffService;
/**
* Controller
*
* @author zghz
* @date 2025-12-24
*/
@RestController
@RequestMapping("/finance/invoice/writeoff")
public class OmsReceivableInvoiceWriteOffController extends BaseController
{
@Autowired
private IOmsReceivableInvoiceWriteOffService omsReceivableInvoiceWriteOffService;
/**
*
*/
@GetMapping("/list")
public TableDataInfo list(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
startPage();
List<OmsReceivableInvoiceWriteOff> list = omsReceivableInvoiceWriteOffService.selectOmsReceivableInvoiceWriteOffList(omsReceivableInvoiceWriteOff);
return getDataTable(list);
}
/**
*
*/
@Log(title = "应收票据核销单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
List<OmsReceivableInvoiceWriteOff> list = omsReceivableInvoiceWriteOffService.selectOmsReceivableInvoiceWriteOffList(omsReceivableInvoiceWriteOff);
ExcelUtil<OmsReceivableInvoiceWriteOff> util = new ExcelUtil<OmsReceivableInvoiceWriteOff>(OmsReceivableInvoiceWriteOff.class);
util.exportExcel(response, list, "应收票据核销单数据");
}
/**
*
*/
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(omsReceivableInvoiceWriteOffService.selectOmsReceivableInvoiceWriteOffById(id));
}
/**
*
*/
@Log(title = "应收票据核销单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
return toAjax(omsReceivableInvoiceWriteOffService.insertOmsReceivableInvoiceWriteOff(omsReceivableInvoiceWriteOff));
}
/**
*
*/
@Log(title = "应收票据核销单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
return toAjax(omsReceivableInvoiceWriteOffService.updateOmsReceivableInvoiceWriteOff(omsReceivableInvoiceWriteOff));
}
/**
*
*/
@Log(title = "应收票据核销单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(omsReceivableInvoiceWriteOffService.deleteOmsReceivableInvoiceWriteOffByIds(ids));
}
}

View File

@ -101,7 +101,6 @@ public class OmsInvoiceBill extends BaseEntity
/** 关联的原始开票单ID */
private Long originalBillId;
private List<PaymentBillPayableDetailDTO> detailList;
private Long approveUser;
private Date applyTime;
private Date todoApproveTime;

View File

@ -67,6 +67,8 @@ public class OmsReceivableInvoiceDetail extends BaseEntity
private Date actualInvoiceTime;
private OmsFinAttachment attachment;
private Long writeOffId;
private List<Long> writeOffIdList;
@Getter
public enum ReceivableDetailTypeEnum {

View File

@ -0,0 +1,93 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* oms_receivable_invoice_write_off
*
* @author zghz
* @date 2025-12-24
*/
@Data
public class OmsReceivableInvoiceWriteOff extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 核销单编号 */
@Excel(name = "核销单编号")
private String writeOffCode;
/** 核销类型 AUTO:系统自动核销 USER:用户手动核销 */
@Excel(name = "核销类型")
private String writeOffType;
/** 开票单编号 */
@Excel(name = "开票单编号")
private String invoiceBillCode;
private String receivableBillCode;
/** 客户编码 */
@Excel(name = "客户编码")
private String partnerCode;
private String partnerName;
/** 本次核销总金额 */
@Excel(name = "本次核销总金额")
private BigDecimal writeOffAmount;
/** 本次核销未税总金额 */
@Excel(name = "本次核销未税总金额")
private BigDecimal writeOffAmountWithoutTax;
/** 本次核销税额 */
@Excel(name = "本次核销税额")
private BigDecimal writeOffTaxAmount;
/** 核销时间 */
@Excel(name = "核销时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date writeOffTime;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 开票单信息(关联查询) */
private OmsInvoiceBill invoiceBill;
/** 核销明细列表 */
private List<ReceiptDetailDTO> detailList;
public enum WriteOffTypeEnum {
AUTO("AUTO", "系统自动核销"),
USER("USER", "用户手动核销");
private final String code;
private final String info;
WriteOffTypeEnum(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() {
return code;
}
public String getInfo() {
return info;
}
}
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.sip.dto;
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* DTO
*
* @author zghz
* @date 2025-12-16
*/
@Data
public class WriteOffInvoiceRequestDto
{
/**
* ID
*/
@NotNull(message = "开票单ID不能为空")
private Long invoiceBillId;
/**
*
*/
private List<OmsReceivableInvoiceDetail> detailList;
/**
*
*/
@NotBlank(message = "供应商代码不能为空")
private String partnerCode;
private String partnerName;
/**
*
*/
private String remark;
}

View File

@ -93,4 +93,6 @@ public interface OmsInvoiceBillMapper
void clearApprove(OmsInvoiceBill invoiceBill);
void updateReturnWriteOffBatch(List<OmsInvoiceBill> updateBills);
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
@ -75,4 +76,10 @@ public interface OmsReceivableInvoiceDetailMapper
List<ReceiptDetailDTO> listReceivableByInvoiceBillCode(List<String> strings);
List<ReceiptDetailDTO> listReceivableByInvoiceWriteOffId(List<Long> lists);
void clearWriteOff(List<Long> writeOffIdList);
void updateWriteOffIdBatch(List<OmsPayableTicketDetail> updateList);
}

View File

@ -0,0 +1,73 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff;
/**
* Mapper
*
* @author zghz
* @date 2025-12-24
*/
public interface OmsReceivableInvoiceWriteOffMapper
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableInvoiceWriteOff selectOmsReceivableInvoiceWriteOffById(Long id);
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
public List<OmsReceivableInvoiceWriteOff> selectOmsReceivableInvoiceWriteOffList(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff);
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
public int insertOmsReceivableInvoiceWriteOff(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff);
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
public int updateOmsReceivableInvoiceWriteOff(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableInvoiceWriteOffById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableInvoiceWriteOffByIds(Long[] ids);
/**
* ID
*
* @param ids
* @return
*/
List<OmsReceivableInvoiceWriteOff> listByIds(Long[] ids);
int selectMaxCodeByPrefix(String codePrefix);
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsInvoiceBill;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
import com.ruoyi.sip.domain.ProjectProductInfo;
import com.ruoyi.sip.domain.dto.InvoiceProductDto;
import org.springframework.web.multipart.MultipartFile;
@ -119,4 +120,6 @@ public interface IOmsInvoiceBillService
AjaxResult revokeInvoice(Long id);
void returnTicketWriteOff(List<String> collect, List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails);
}

View File

@ -78,4 +78,12 @@ public interface IOmsReceivableInvoiceDetailService
void applyRefund(String invoiceBillCode, String invoiceBillCode1);
List<ReceiptDetailDTO> listReceivableByInvoiceBillCode(String invoiceBillCode);
List<ReceiptDetailDTO> listReceivableByInvoiceWriteOffId(List<Long> longs);
List<OmsReceivableInvoiceDetail> listByWriteOffIds(Long[] ids);
void clearWriteOff(List<Long> writeOffIdList);
void updateWriteOffIdBatch(List<OmsPayableTicketDetail> updateList);
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff;
import com.ruoyi.sip.dto.WriteOffInvoiceRequestDto;
import com.ruoyi.sip.dto.WriteOffTicketRequestDto;
/**
* Service
*
* @author zghz
* @date 2025-12-24
*/
public interface IOmsReceivableInvoiceWriteOffService
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableInvoiceWriteOff selectOmsReceivableInvoiceWriteOffById(Long id);
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
public List<OmsReceivableInvoiceWriteOff> selectOmsReceivableInvoiceWriteOffList(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff);
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
public int insertOmsReceivableInvoiceWriteOff(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff);
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
public int updateOmsReceivableInvoiceWriteOff(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableInvoiceWriteOffByIds(Long[] ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableInvoiceWriteOffById(Long id);
/**
*
* @param writeOffRequestDto
*/
public void autoTicketWriteOff(WriteOffInvoiceRequestDto writeOffRequestDto);
}

View File

@ -17,10 +17,12 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.InvoiceProductDto;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import com.ruoyi.sip.dto.WriteOffInvoiceRequestDto;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.service.*;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -60,6 +62,11 @@ public class OmsInvoiceBillServiceImpl implements IOmsInvoiceBillService, TodoCo
private IInventoryOuterService outerService;
@Autowired
private IProjectProductInfoService productInfoService;
@Autowired
@Lazy
private IOmsReceivableInvoiceWriteOffService writeOffService;
/**
*
@ -177,25 +184,32 @@ public class OmsInvoiceBillServiceImpl implements IOmsInvoiceBillService, TodoCo
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult uploadReceipt(OmsInvoiceBill bill, MultipartFile file) throws Exception {
OmsInvoiceBill omsInvoiceBill = selectOmsInvoiceBillById(bill.getId());
if (omsInvoiceBill == null) {
OmsInvoiceBill existBill = selectOmsInvoiceBillById(bill.getId());
if (existBill == null) {
throw new ServiceException("开票单不存在");
}
// 检查开票金额是否与应收单一致
if (omsInvoiceBill.getTotalPriceWithTax().compareTo(bill.getInvoicePriceWithTax()) != 0){
if (existBill.getTotalPriceWithTax().compareTo(bill.getInvoicePriceWithTax()) != 0){
return AjaxResult.error("开票金额与应收单金额不一致");
}
// 这里可以添加上传附件的逻辑
omsFinAttachmentService.uploadAttachment(file, omsInvoiceBill.getId(), OmsFinAttachment.RelatedBillTypeEnum.RECEIVE_INVOICE, bill.getRemark());
omsInvoiceBill.setActualInvoiceTime(DateUtils.getNowDate());
omsInvoiceBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode());
omsInvoiceBill.setInvoicePriceWithTax(bill.getInvoicePriceWithTax());
omsInvoiceBill.setInvoicePriceWithoutTax(bill.getInvoicePriceWithoutTax());
omsInvoiceBill.setInvoiceType(bill.getInvoiceType());
updateOmsInvoiceBill(omsInvoiceBill);
omsFinAttachmentService.uploadAttachment(file, existBill.getId(), OmsFinAttachment.RelatedBillTypeEnum.RECEIVE_INVOICE, bill.getRemark());
existBill.setActualInvoiceTime(DateUtils.getNowDate());
existBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode());
existBill.setInvoicePriceWithTax(bill.getInvoicePriceWithTax());
existBill.setInvoicePriceWithoutTax(bill.getInvoicePriceWithoutTax());
existBill.setInvoiceType(bill.getInvoiceType());
updateOmsInvoiceBill(existBill);
WriteOffInvoiceRequestDto writeOffInvoiceRequestDto = new WriteOffInvoiceRequestDto();
writeOffInvoiceRequestDto.setInvoiceBillId(existBill.getId());
writeOffInvoiceRequestDto.setPartnerCode(existBill.getPartnerCode());
writeOffInvoiceRequestDto.setPartnerName(existBill.getPartnerName());
writeOffInvoiceRequestDto.setRemark("系统自动核销");
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = detailService.listByInvoiceBillCode(existBill.getInvoiceBillCode());
writeOffInvoiceRequestDto.setDetailList(omsReceivableInvoiceDetails);
writeOffService.autoTicketWriteOff(writeOffInvoiceRequestDto);
return AjaxResult.success("上传成功");
}
@ -422,6 +436,88 @@ public class OmsInvoiceBillServiceImpl implements IOmsInvoiceBillService, TodoCo
return AjaxResult.success("撤销成功");
}
@Override
public void returnTicketWriteOff(List<String> collect, List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails) {
OmsInvoiceBill queryBill = new OmsInvoiceBill();
queryBill.setInvoiceBillCodeList(collect);
List<OmsInvoiceBill> existBillList = selectOmsInvoiceBillList(queryBill);
Map<String, List<OmsInvoiceBill>> listMap = existBillList.stream()
.collect(Collectors.groupingBy(OmsInvoiceBill::getInvoiceBillType));
// 处理预付
// // 预付处理逻辑
// // 1:通过omsPayablePaymentDetailService查询对应的详情然后根据paymentBillCode分组
// // 将含税金额总和计算出来,加在预付单的剩余额度上
// if (CollUtil.isNotEmpty(prePaymentBillList)) {
// // 按付款单code分组核销详情
// Map<String, List<OmsPayablePaymentDetail>> groupedDetails =
// omsPayablePaymentDetails.stream()
// .filter(detail -> detail.getPaymentBillCode() != null)
// .collect(Collectors.groupingBy(OmsPayablePaymentDetail::getPaymentBillCode));
//
// // 计算每个付款单的核销金额合计
// Map<String, BigDecimal> paymentBillWriteOffAmountMap = groupedDetails.entrySet().stream()
// .collect(Collectors.toMap(
// Map.Entry::getKey,
// entry -> entry.getValue().stream()
// .map(OmsPayablePaymentDetail::getPaymentAmount)
// .reduce(BigDecimal.ZERO, BigDecimal::add)
// ));
//
// // 更新预付单的剩余额度 - 批量操作
// List<OmsPaymentBill> updateBills = prePaymentBillList.stream()
// .map(prePaymentBill -> {
// BigDecimal increaseAmount = paymentBillWriteOffAmountMap.getOrDefault(
// prePaymentBill.getPaymentBillCode(), BigDecimal.ZERO);
//
// if (increaseAmount.compareTo(BigDecimal.ZERO) > 0) {
// OmsPaymentBill updateBill = new OmsPaymentBill();
// updateBill.setId(prePaymentBill.getId());
// // 在原剩余额度基础上加回本次核销金额
// BigDecimal newResidueAmount = prePaymentBill.getPreResidueAmount()
// .add(increaseAmount);
// updateBill.setPreResidueAmount(newResidueAmount);
// return updateBill;
// }
// return null;
// })
// .filter(Objects::nonNull)
// .collect(Collectors.toList());
//
// if (CollUtil.isNotEmpty(updateBills)) {
// for (OmsPaymentBill bill : updateBills) {
// updateOmsPaymentBill(bill);
// }
// }
// }
//处理其余数据
if (CollUtil.isNotEmpty(listMap.values())) {
List<OmsInvoiceBill> updateBills = new ArrayList<>();
for (List<OmsInvoiceBill> omsPaymentBillList : listMap.values()) {
for (OmsInvoiceBill tempBill : omsPaymentBillList) {
OmsInvoiceBill updateBill = new OmsInvoiceBill();
updateBill.setId(tempBill.getId());
updateBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.WAIT_INVOICE.getCode());
updateBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
updateBill.setApproveTime(null);
updateBill.setActualInvoiceTime(null);
updateBills.add(updateBill);
}
}
if (CollUtil.isNotEmpty(updateBills)) {
omsInvoiceBillMapper.updateReturnWriteOffBatch(updateBills);
omsFinAttachmentService.deleteOmsFinAttachmentByPayment(updateBills.stream().map(OmsInvoiceBill::getId).collect(Collectors.toList()),
OmsFinAttachment.RelatedBillTypeEnum.RECEIVE_INVOICE.getCode());
}
//清理detail数据
detailService.clearWriteOff(omsReceivableInvoiceDetails.stream().map(OmsReceivableInvoiceDetail::getWriteOffId).distinct().filter(Objects::nonNull).collect(Collectors.toList()));
}
}
@Override
public Object todoDetail(String businessKey, String processKey, String todoId) {
return null;

View File

@ -1,10 +1,7 @@
package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -186,4 +183,38 @@ public class OmsReceivableInvoiceDetailServiceImpl implements IOmsReceivableInvo
}
return receiptDetailDTOS;
}
@Override
public List<ReceiptDetailDTO> listReceivableByInvoiceWriteOffId(List<Long> longs) {
List<ReceiptDetailDTO> receiptDetailDTOS = omsReceivableInvoiceDetailMapper.listReceivableByInvoiceWriteOffId(longs);
for (ReceiptDetailDTO detailDTO : receiptDetailDTOS) {
detailDTO.setReceiptRate(detailDTO.getReceiptAmount()
.divide(detailDTO.getTotalPriceWithTax(), 4, java.math.RoundingMode.HALF_UP)
.multiply(new BigDecimal("100")));
}
return receiptDetailDTOS;
}
@Override
public List<OmsReceivableInvoiceDetail> listByWriteOffIds(Long[] ids) {
if (ids == null || ids.length == 0) {
return new ArrayList<>();
}
OmsReceivableInvoiceDetail query = new OmsReceivableInvoiceDetail();
query.setWriteOffIdList(Arrays.asList(ids));
return omsReceivableInvoiceDetailMapper.list(query);
}
@Override
public void clearWriteOff(List<Long> writeOffIdList) {
if (CollUtil.isEmpty(writeOffIdList)) {
return;
}
omsReceivableInvoiceDetailMapper.clearWriteOff(writeOffIdList);
}
@Override
public void updateWriteOffIdBatch(List<OmsPayableTicketDetail> updateList) {
omsReceivableInvoiceDetailMapper.updateWriteOffIdBatch(updateList);
}
}

View File

@ -0,0 +1,227 @@
package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Date;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import com.ruoyi.sip.dto.WriteOffInvoiceRequestDto;
import com.ruoyi.sip.service.IOmsInvoiceBillService;
import com.ruoyi.sip.service.IOmsReceivableBillService;
import com.ruoyi.sip.service.IOmsReceivableInvoiceDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.OmsReceivableInvoiceWriteOffMapper;
import com.ruoyi.sip.service.IOmsReceivableInvoiceWriteOffService;
/**
* Service
*
* @author zghz
* @date 2025-12-24
*/
@Service
public class OmsReceivableInvoiceWriteOffServiceImpl implements IOmsReceivableInvoiceWriteOffService
{
@Autowired
private OmsReceivableInvoiceWriteOffMapper omsReceivableInvoiceWriteOffMapper;
@Autowired
private IOmsInvoiceBillService omsInvoiceBillService;
@Autowired
private IOmsReceivableInvoiceDetailService invoiceDetailService;
@Autowired
private IOmsReceivableBillService receivableBillService;
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableInvoiceWriteOff selectOmsReceivableInvoiceWriteOffById(Long id)
{
OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff = omsReceivableInvoiceWriteOffMapper.selectOmsReceivableInvoiceWriteOffById(id);
// 查询关联的开票单信息
OmsInvoiceBill omsInvoiceBill = omsInvoiceBillService.selectOmsInvoiceBillByCode(omsReceivableInvoiceWriteOff.getInvoiceBillCode());
omsReceivableInvoiceWriteOff.setInvoiceBill(omsInvoiceBill);
List<ReceiptDetailDTO> receiptDetailDTOS = invoiceDetailService.listReceivableByInvoiceWriteOffId(Collections.singletonList(id));
omsReceivableInvoiceWriteOff.setDetailList(receiptDetailDTOS);
return omsReceivableInvoiceWriteOff;
}
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
@Override
public List<OmsReceivableInvoiceWriteOff> selectOmsReceivableInvoiceWriteOffList(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
return omsReceivableInvoiceWriteOffMapper.selectOmsReceivableInvoiceWriteOffList(omsReceivableInvoiceWriteOff);
}
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
@Override
public int insertOmsReceivableInvoiceWriteOff(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
omsReceivableInvoiceWriteOff.setCreateTime(DateUtils.getNowDate());
omsReceivableInvoiceWriteOff.setCreateBy(ShiroUtils.getUserId().toString());
return omsReceivableInvoiceWriteOffMapper.insertOmsReceivableInvoiceWriteOff(omsReceivableInvoiceWriteOff);
}
/**
*
*
* @param omsReceivableInvoiceWriteOff
* @return
*/
@Override
public int updateOmsReceivableInvoiceWriteOff(OmsReceivableInvoiceWriteOff omsReceivableInvoiceWriteOff)
{
omsReceivableInvoiceWriteOff.setUpdateTime(DateUtils.getNowDate());
return omsReceivableInvoiceWriteOffMapper.updateOmsReceivableInvoiceWriteOff(omsReceivableInvoiceWriteOff);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsReceivableInvoiceWriteOffByIds(Long[] ids)
{
if (ids == null || ids.length == 0) {
return 0;
}
List<OmsReceivableInvoiceWriteOff> omsReceivableInvoiceWriteOffs = omsReceivableInvoiceWriteOffMapper.listByIds(ids);
if (CollUtil.isEmpty(omsReceivableInvoiceWriteOffs)) {
return 0;
}
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = invoiceDetailService.listByWriteOffIds(ids);
// 反核销处理:恢复收票单状态
omsInvoiceBillService.returnTicketWriteOff(omsReceivableInvoiceWriteOffs.stream()
.map(OmsReceivableInvoiceWriteOff::getInvoiceBillCode).collect(java.util.stream.Collectors.toList()),
omsReceivableInvoiceDetails);
List<Long> payableBillIds = omsReceivableInvoiceDetails.stream()
.map(OmsReceivableInvoiceDetail::getReceivableBillId)
.distinct()
.collect(java.util.stream.Collectors.toList());
// 更新应付单的收票金额
if (CollUtil.isNotEmpty(payableBillIds)) {
receivableBillService.updateInvoiceAmount(payableBillIds);
}
// 再删除主记录
return omsReceivableInvoiceWriteOffMapper.deleteOmsReceivableInvoiceWriteOffByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsReceivableInvoiceWriteOffById(Long id)
{
return omsReceivableInvoiceWriteOffMapper.deleteOmsReceivableInvoiceWriteOffById(id);
}
@Override
public void autoTicketWriteOff(WriteOffInvoiceRequestDto writeOffRequestDto) {
if (CollUtil.isEmpty(writeOffRequestDto.getDetailList())) {
throw new ServiceException("请选择核销明细");
}
// 获取收票单信息
OmsInvoiceBill invoiceBill = omsInvoiceBillService.selectOmsInvoiceBillById(writeOffRequestDto.getInvoiceBillId());
if (invoiceBill == null) {
throw new ServiceException("开票单不存在");
}
//
// // 创建核销主记录
OmsReceivableInvoiceWriteOff writeOff = new OmsReceivableInvoiceWriteOff();
writeOff.setWriteOffCode(generateWriteOffCode());
writeOff.setWriteOffType(OmsPayableTicketWriteOff.WriteOffTypeEnum.AUTO.getCode());
writeOff.setInvoiceBillCode(invoiceBill.getInvoiceBillCode());
writeOff.setPartnerCode(writeOffRequestDto.getPartnerCode());
writeOff.setPartnerName(writeOffRequestDto.getPartnerName());
writeOff.setWriteOffTime(new Date());
writeOff.setRemark(writeOffRequestDto.getRemark());
//
// // 计算总金额和相关税额
BigDecimal totalAmount = BigDecimal.ZERO;
BigDecimal totalAmountWithoutTax = BigDecimal.ZERO;
BigDecimal totalTaxAmount = BigDecimal.ZERO;
for (OmsReceivableInvoiceDetail item : writeOffRequestDto.getDetailList()) {
totalAmount = totalAmount.add(item.getInvoiceAmount());
if (item.getInvoiceAmountWithoutTax() != null) {
totalAmountWithoutTax = totalAmountWithoutTax.add(item.getInvoiceAmountWithoutTax());
}
if (item.getInvoiceAmountTax() != null) {
totalTaxAmount = totalTaxAmount.add(item.getInvoiceAmountTax());
}
}
writeOff.setWriteOffAmount(totalAmount);
writeOff.setWriteOffAmountWithoutTax(totalAmountWithoutTax);
writeOff.setWriteOffTaxAmount(totalTaxAmount);
// 设置创建时间
writeOff.setCreateTime(new Date());
writeOff.setCreateBy(ShiroUtils.getUserId().toString());
writeOff.setUpdateTime(new Date());
// 保存核销主记录
omsReceivableInvoiceWriteOffMapper.insertOmsReceivableInvoiceWriteOff(writeOff);
List<OmsPayableTicketDetail> updateList = new ArrayList<>();
// 保存核销明细
// 保存核销明细
for (OmsReceivableInvoiceDetail omsReceivableInvoiceDetail : writeOffRequestDto.getDetailList()) {
OmsPayableTicketDetail temp = new OmsPayableTicketDetail();
temp.setId(omsReceivableInvoiceDetail.getId());
temp.setWriteOffId(writeOff.getId());
updateList.add(temp);
}
if (CollUtil.isNotEmpty(updateList)) {
invoiceDetailService.updateWriteOffIdBatch(updateList);
}
// 更新对应应付单的收票金额
receivableBillService.updateInvoiceAmount(writeOffRequestDto.getDetailList().stream()
.map(OmsReceivableInvoiceDetail::getReceivableBillId).distinct()
.collect(java.util.stream.Collectors.toList()));
}
private String generateWriteOffCode() {
String prefix = "HX";
// 查询当天已有的最大序列号
String codePrefix = prefix + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
int maxSequence = omsReceivableInvoiceWriteOffMapper.selectMaxCodeByPrefix(codePrefix);
// 生成新的序列号
int newSequence = maxSequence + 1;
// 序列号补零到4位
String sequenceStr = String.format("%04d", newSequence);
return codePrefix + sequenceStr;
}
}

View File

@ -498,6 +498,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
approve_time=null
where id = #{id}
</update>
<update id="updateReturnWriteOffBatch">
<foreach collection="list" item="item" separator=";">
update oms_invoice_bill
set
invoice_status=#{item.invoiceStatus},
approve_status=#{item.approveStatus},
approve_time=null,
actual_invoice_time=null,
update_time=now()
where id = #{item.id}
</foreach>
</update>
<delete id="deleteOmsInvoiceBillById" parameterType="Long">
delete from oms_invoice_bill where id = #{id}
@ -532,7 +544,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectOmsInvoiceBillByCode" resultType="com.ruoyi.sip.domain.OmsInvoiceBill">
<include refid="selectOmsInvoiceBillVo"/>
where invoice_bill_code = #{invoiceBillCode} and del_flag = '0'
where invoice_bill_code = #{invoiceBillCode}
</select>
<select id="selectMaxCodeByPrefix" resultType="java.lang.Integer">

View File

@ -62,9 +62,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item}
</foreach>
</if>
<if test="writeOffIdList != null and writeOffIdList.size() > 0">
and t1.write_off_id in
<foreach item="item" collection="writeOffIdList" separator="," open="(" close=")" index="index">
#{item}
</foreach>
</if>
<if test="receivableBillId != null ">
and t1.receivable_bill_id =#{receivableBillId}
</if>
<if test="writeOffId != null ">
and t1.write_off_id =#{writeOffId}
</if>
<if test="invoiceBillCode != null ">
and t1.invoice_bill_code =#{invoiceBillCode}
</if>
@ -98,6 +107,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
left join project_info t4 on t3.project_id = t4.id
</select>
<select id="listReceivableByInvoiceWriteOffId" resultType="com.ruoyi.sip.domain.dto.ReceiptDetailDTO">
select t1.receipt_amount, t2.receivable_bill_code, t4.project_name, t4.project_code, t2.total_price_with_tax,t2.partner_code,t2.partner_name,t2.create_time
from (SELECT sum(invoice_amount) receipt_amount,
receivable_bill_id
FROM oms_receivable_invoice_detail
WHERE write_off_id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
#{item}
</foreach>
group by receivable_bill_id) t1
left join oms_receivable_bill t2 on t1.receivable_bill_id = t2.id
left join project_order_info t3 on t2.order_code = t3.order_code
left join project_info t4 on t3.project_id = t4.id
</select>
<insert id="insertOmsReceivableInvoiceDetail" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_invoice_detail
@ -171,6 +194,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</trim>
where id = #{id}
</update>
<update id="clearWriteOff">
update oms_receivable_invoice_detail set write_off_id = null where write_off_id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
#{item}
</foreach>
</update>
<update id="updateWriteOffIdBatch">
<foreach collection="list" item="item" separator=";">
update oms_receivable_invoice_detail set write_off_id = #{item.writeOffId} where id = #{item.id}
</foreach>
</update>
<delete id="deleteOmsReceivableInvoiceDetailById" parameterType="Long">
delete from oms_receivable_invoice_detail where id = #{id}

View File

@ -0,0 +1,249 @@
<?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.OmsReceivableInvoiceWriteOffMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff" id="OmsReceivableInvoiceWriteOffResult">
<result property="id" column="id" />
<result property="writeOffCode" column="write_off_code" />
<result property="writeOffType" column="write_off_type" />
<result property="invoiceBillCode" column="invoice_bill_code" />
<result property="partnerCode" column="partner_code" />
<result property="partnerName" column="partner_name" />
<result property="writeOffAmount" column="write_off_amount" />
<result property="writeOffAmountWithoutTax" column="write_off_amount_without_tax" />
<result property="writeOffTaxAmount" column="write_off_tax_amount" />
<result property="writeOffTime" column="write_off_time" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectOmsReceivableInvoiceWriteOffVo">
select
o.id,
o.write_off_code,
o.write_off_type,
o.invoice_bill_code,
o.partner_code,
o.partner_name,
o.write_off_amount,
o.write_off_amount_without_tax,
o.write_off_tax_amount,
o.write_off_time,
o.remark,
o.create_by,
o.create_time,
o.update_by,
o.update_time,
su.user_name as create_by_name
from oms_receivable_invoice_write_off o
left join sys_user su on o.create_by=su.user_id
</sql>
<select id="selectOmsReceivableInvoiceWriteOffById" parameterType="Long" resultMap="OmsReceivableInvoiceWriteOffResult">
<include refid="selectOmsReceivableInvoiceWriteOffVo"/>
where o.id = #{id}
</select>
<select id="selectOmsReceivableInvoiceWriteOffList" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff" resultMap="OmsReceivableInvoiceWriteOffResult">
<include refid="selectOmsReceivableInvoiceWriteOffVo"/>
<where>
<if test="writeOffCode != null and writeOffCode != ''">
AND o.write_off_code = #{writeOffCode}
</if>
<if test="writeOffType != null and writeOffType != ''">
AND o.write_off_type = #{writeOffType}
</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">
AND o.invoice_bill_code = #{invoiceBillCode}
</if>
<if test="partnerCode != null and partnerCode != ''">
AND o.partner_code = #{partnerCode}
</if>
<if test="writeOffAmount != null">
AND o.write_off_amount = #{writeOffAmount}
</if>
<if test="writeOffAmountWithoutTax != null">
AND o.write_off_amount_without_tax = #{writeOffAmountWithoutTax}
</if>
<if test="writeOffTaxAmount != null">
AND o.write_off_tax_amount = #{writeOffTaxAmount}
</if>
<if test="writeOffTime != null">
AND o.write_off_time = #{writeOffTime}
</if>
<if test="partnerName != null and partnerName != ''"> and o.partner_name like concat('%', #{partnerName}, '%')</if>
<if test="receivableBillCode != null and receivableBillCode != ''"> and o.id in (
select write_off_id from oms_receivable_invoice_detail t1
inner join oms_receivable_bill t2 on t1.receivable_bill_id=t2.id
where t2.receivable_bill_code=#{receivableBillCode}
) </if>
</where>
order by o.create_time desc
</select>
<insert id="insertOmsReceivableInvoiceWriteOff" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_invoice_write_off
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="writeOffCode != null and writeOffCode != ''">
write_off_code,
</if>
<if test="writeOffType != null and writeOffType != ''">
write_off_type,
</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">
invoice_bill_code,
</if>
<if test="partnerCode != null and partnerCode != ''">
partner_code,
</if>
<if test="partnerName != null and partnerName != ''">
partner_name,
</if>
<if test="writeOffAmount != null">
write_off_amount,
</if>
<if test="writeOffAmountWithoutTax != null">
write_off_amount_without_tax,
</if>
<if test="writeOffTaxAmount != null">
write_off_tax_amount,
</if>
<if test="writeOffTime != null">
write_off_time,
</if>
<if test="remark != null and remark != ''">
remark,
</if>
<if test="createBy != null and createBy != ''">
create_by,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateBy != null and updateBy != ''">
update_by,
</if>
<if test="updateTime != null">
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="writeOffCode != null and writeOffCode != ''">
#{writeOffCode},
</if>
<if test="writeOffType != null and writeOffType != ''">
#{writeOffType},
</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">
#{invoiceBillCode},
</if>
<if test="partnerCode != null and partnerCode != ''">
#{partnerCode},
</if>
<if test="partnerName != null and partnerName != ''">
#{partnerName},
</if>
<if test="writeOffAmount != null">
#{writeOffAmount},
</if>
<if test="writeOffAmountWithoutTax != null">
#{writeOffAmountWithoutTax},
</if>
<if test="writeOffTaxAmount != null">
#{writeOffTaxAmount},
</if>
<if test="writeOffTime != null">
#{writeOffTime},
</if>
<if test="remark != null and remark != ''">
#{remark},
</if>
<if test="createBy != null and createBy != ''">
#{createBy},
</if>
<if test="createTime != null">
#{createTime},
</if>
<if test="updateBy != null and updateBy != ''">
#{updateBy},
</if>
<if test="updateTime != null">
#{updateTime},
</if>
</trim>
</insert>
<update id="updateOmsReceivableInvoiceWriteOff" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceWriteOff">
update oms_receivable_invoice_write_off
<trim prefix="SET" suffixOverrides=",">
<if test="writeOffCode != null and writeOffCode != ''">
write_off_code = #{writeOffCode},
</if>
<if test="writeOffType != null and writeOffType != ''">
write_off_type = #{writeOffType},
</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">
invoice_bill_code = #{invoiceBillCode},
</if>
<if test="partnerCode != null and partnerCode != ''">
partner_code = #{partnerCode},
</if>
<if test="writeOffAmount != null">
write_off_amount = #{writeOffAmount},
</if>
<if test="writeOffAmountWithoutTax != null">
write_off_amount_without_tax = #{writeOffAmountWithoutTax},
</if>
<if test="writeOffTaxAmount != null">
write_off_tax_amount = #{writeOffTaxAmount},
</if>
<if test="writeOffTime != null">
write_off_time = #{writeOffTime},
</if>
<if test="remark != null and remark != ''">
remark = #{remark},
</if>
<if test="updateBy != null and updateBy != ''">
update_by = #{updateBy},
</if>
<if test="updateTime != null">
update_time = #{updateTime},
</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsReceivableInvoiceWriteOffById" parameterType="Long">
delete from oms_receivable_invoice_write_off where id = #{id}
</delete>
<delete id="deleteOmsReceivableInvoiceWriteOffByIds" parameterType="String">
delete from oms_receivable_invoice_write_off where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="listByIds" parameterType="String" resultMap="OmsReceivableInvoiceWriteOffResult">
<include refid="selectOmsReceivableInvoiceWriteOffVo"/>
where o.id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
order by o.create_time desc
</select>
<select id="selectMaxCodeByPrefix" resultType="java.lang.Integer">
SELECT COALESCE(MAX(CAST(SUBSTRING(write_off_code, LENGTH(#{codePrefix}) + 1) AS UNSIGNED)), 0)
FROM oms_receivable_invoice_write_off
WHERE write_off_code LIKE CONCAT(#{codePrefix}, '%')
</select>
</mapper>