Browse Source

[feat]财务管理

修改国税发票的物料合计和数量合计的数据类型
国税发票新增 根据销售订单信息填充发票信息后端接口
国税发票新增 通过销售订单新增开票 后端接口
新增 国内开票公司前端页面

[fix] 销售管理
修改销售订单数据库的物料合计和数量合计的数据类型
修改销售订单前端页面:新增是否开票查询条件、新增列表展示是否开票字段;新增开票按钮;新增开票js方法,加上对条件限制:只允许选择一条销售订单、检查是否审核通过、检查是否允许开票
修改销售订单后端查询列表方法:新增是否开票字段
销售订单新增 加载开票弹窗后端接口:通过币种的不同转到不同的开票页面;新增 新增开票后端接口
dev
liuxiaoxu 4 months ago
parent
commit
2291a053f3
  1. 28
      ruoyi-admin/src/main/java/com/ruoyi/financial/domain/FinancialTaxInvoice.java
  2. 15
      ruoyi-admin/src/main/java/com/ruoyi/financial/service/IFinancialTaxInvoiceService.java
  3. 54
      ruoyi-admin/src/main/java/com/ruoyi/financial/service/impl/FinancialTaxInvoiceServiceImpl.java
  4. 36
      ruoyi-admin/src/main/java/com/ruoyi/system/controller/SysSalesOrderController.java
  5. 1
      ruoyi-admin/src/main/resources/mapper/system/SysSalesOrderMapper.xml
  6. 166
      ruoyi-admin/src/main/resources/templates/system/salesOrder/makeInvoiceRMB.html
  7. 52
      ruoyi-admin/src/main/resources/templates/system/salesOrder/salesOrder.html

28
ruoyi-admin/src/main/java/com/ruoyi/financial/domain/FinancialTaxInvoice.java

@ -98,11 +98,11 @@ public class FinancialTaxInvoice extends BaseEntity
/** 物料数合计 */ /** 物料数合计 */
@Excel(name = "物料数合计") @Excel(name = "物料数合计")
private String materialSum; private Long materialSum;
/** 数量合计 */ /** 数量合计 */
@Excel(name = "数量合计") @Excel(name = "数量合计")
private String enterpriseSum; private Long enterpriseSum;
/** 不含税总价(RMB) */ /** 不含税总价(RMB) */
@Excel(name = "不含税总价(RMB)") @Excel(name = "不含税总价(RMB)")
@ -377,25 +377,25 @@ public class FinancialTaxInvoice extends BaseEntity
{ {
return usdTax; return usdTax;
} }
public void setMaterialSum(String materialSum)
{
this.materialSum = materialSum;
}
public String getMaterialSum()
{ public Long getMaterialSum() {
return materialSum; return materialSum;
} }
public void setEnterpriseSum(String enterpriseSum)
{ public void setMaterialSum(Long materialSum) {
this.enterpriseSum = enterpriseSum; this.materialSum = materialSum;
} }
public String getEnterpriseSum() public Long getEnterpriseSum() {
{
return enterpriseSum; return enterpriseSum;
} }
public void setNoRmbSum(BigDecimal noRmbSum)
public void setEnterpriseSum(Long enterpriseSum) {
this.enterpriseSum = enterpriseSum;
}
public void setNoRmbSum(BigDecimal noRmbSum)
{ {
this.noRmbSum = noRmbSum; this.noRmbSum = noRmbSum;
} }

15
ruoyi-admin/src/main/java/com/ruoyi/financial/service/IFinancialTaxInvoiceService.java

@ -2,6 +2,7 @@ package com.ruoyi.financial.service;
import java.util.List; import java.util.List;
import com.ruoyi.financial.domain.FinancialTaxInvoice; import com.ruoyi.financial.domain.FinancialTaxInvoice;
import com.ruoyi.system.domain.SysSalesOrder;
/** /**
* 国税发票Service接口 * 国税发票Service接口
@ -72,4 +73,18 @@ public interface IFinancialTaxInvoiceService
* @return * @return
*/ */
int restoreFinancialTaxInvoiceById(Long taxInvoiceId); int restoreFinancialTaxInvoiceById(Long taxInvoiceId);
/**
* 根据销售订单生成发票
* @param sysSalesOrder
* @return
*/
FinancialTaxInvoice fillInvoiceBySalesOrder(SysSalesOrder sysSalesOrder);
/**
* 销售订单新增开票
* @param financialTaxInvoice
* @return
*/
int makeInvoiceSave(FinancialTaxInvoice financialTaxInvoice);
} }

54
ruoyi-admin/src/main/java/com/ruoyi/financial/service/impl/FinancialTaxInvoiceServiceImpl.java

@ -1,8 +1,13 @@
package com.ruoyi.financial.service.impl; package com.ruoyi.financial.service.impl;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List; import java.util.List;
import com.ruoyi.common.core.redis.RedisCache;
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.system.domain.SysSalesOrder;
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.FinancialTaxInvoiceMapper; import com.ruoyi.financial.mapper.FinancialTaxInvoiceMapper;
@ -22,6 +27,9 @@ public class FinancialTaxInvoiceServiceImpl implements IFinancialTaxInvoiceServi
@Autowired @Autowired
private FinancialTaxInvoiceMapper financialTaxInvoiceMapper; private FinancialTaxInvoiceMapper financialTaxInvoiceMapper;
@Autowired
private RedisCache redisCache;
/** /**
* 查询国税发票 * 查询国税发票
* *
@ -123,4 +131,50 @@ public class FinancialTaxInvoiceServiceImpl implements IFinancialTaxInvoiceServi
{ {
return financialTaxInvoiceMapper.restoreFinancialTaxInvoiceById(taxInvoiceId); return financialTaxInvoiceMapper.restoreFinancialTaxInvoiceById(taxInvoiceId);
} }
/**
* 根据销售订单信息填充发票信息
*
* @param sysSalesOrder 销售订单信息
* @return 结果
*/
@Override
public FinancialTaxInvoice fillInvoiceBySalesOrder(SysSalesOrder sysSalesOrder) {
FinancialTaxInvoice financialTaxInvoice = new FinancialTaxInvoice();
financialTaxInvoice.setSalesOrderCode(sysSalesOrder.getSalesOrderCode());
financialTaxInvoice.setSalesOrderType(sysSalesOrder.getSalesOrderType());
financialTaxInvoice.setCommonCurrency(sysSalesOrder.getCommonCurrency());
financialTaxInvoice.setEnterpriseCode(sysSalesOrder.getEnterpriseCode());
financialTaxInvoice.setEnterpriseName(sysSalesOrder.getEnterpriseName());
financialTaxInvoice.setEnterpriseAddress(sysSalesOrder.getDeliveryAddress());
financialTaxInvoice.setContactNumber(sysSalesOrder.getContactNumber());
financialTaxInvoice.setEnterpriseSum(sysSalesOrder.getEnterpriseSum());
financialTaxInvoice.setMaterialSum(sysSalesOrder.getMaterialSum());
financialTaxInvoice.setRmbTaxSum(BigDecimal.valueOf(sysSalesOrder.getRmbTaxSum()));
financialTaxInvoice.setNoRmbSum(BigDecimal.valueOf(sysSalesOrder.getNoRmbSum()));
financialTaxInvoice.setUsdTaxSum(BigDecimal.valueOf(sysSalesOrder.getUsdTaxSum()));
financialTaxInvoice.setNoUsdSum(BigDecimal.valueOf(sysSalesOrder.getNoUsdSum()));
return financialTaxInvoice;
}
/**
* 销售订单新增开票信息
*
* @param financialTaxInvoice 发票信息
* @return 结果
*/
@Override
public int makeInvoiceSave(FinancialTaxInvoice financialTaxInvoice) {
String loginName = ShiroUtils.getLoginName();
financialTaxInvoice.setCreateBy(loginName);
financialTaxInvoice.setCreateTime(new Date());
String taxInvoiceCode = redisCache.generateBillNo("FP");
financialTaxInvoice.setTaxInvoiceCode(taxInvoiceCode);
financialTaxInvoice.setTaxInvoiceStatus("0");//待审核
financialTaxInvoice.setApplyUser(loginName);
financialTaxInvoice.setBusinessMembers(loginName);
return financialTaxInvoiceMapper.insertFinancialTaxInvoice(financialTaxInvoice);
}
} }

36
ruoyi-admin/src/main/java/com/ruoyi/system/controller/SysSalesOrderController.java

@ -21,7 +21,9 @@ import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.erp.domain.ErpMaterialVo; import com.ruoyi.erp.domain.ErpMaterialVo;
import com.ruoyi.financial.domain.FinancialTaxInvoice;
import com.ruoyi.financial.service.IFinancialReceivablesService; import com.ruoyi.financial.service.IFinancialReceivablesService;
import com.ruoyi.financial.service.IFinancialTaxInvoiceService;
import com.ruoyi.process.general.service.IProcessService; import com.ruoyi.process.general.service.IProcessService;
import com.ruoyi.system.domain.*; import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.exportDto.SysSalesFinishDto; import com.ruoyi.system.domain.exportDto.SysSalesFinishDto;
@ -96,6 +98,9 @@ public class SysSalesOrderController extends BaseController
@Autowired @Autowired
private ISysSalesOrderChildService sysSalesOrderChildService; private ISysSalesOrderChildService sysSalesOrderChildService;
@Autowired
private IFinancialTaxInvoiceService taxInvoiceService;
@RequiresPermissions("system:salesOrder:view") @RequiresPermissions("system:salesOrder:view")
@GetMapping() @GetMapping()
public String salesOrder(ModelMap mmap) public String salesOrder(ModelMap mmap)
@ -583,4 +588,35 @@ public class SysSalesOrderController extends BaseController
return prefix + "/startAftersalesMaterialSelect"; return prefix + "/startAftersalesMaterialSelect";
} }
/**
* 加载开票弹窗
*/
@GetMapping("/makeInvoice/{salesOrderId}")
public String makeInvoice(@PathVariable("salesOrderId") Long salesOrderId, ModelMap mmap)
{
SysSalesOrder sysSalesOrder = sysSalesOrderService.selectSysSalesOrderById(salesOrderId);
String commonCurrency = sysSalesOrder.getCommonCurrency();
FinancialTaxInvoice taxInvoice = taxInvoiceService.fillInvoiceBySalesOrder(sysSalesOrder);
mmap.put("taxInvoice", taxInvoice);
if ("1".equals(commonCurrency)){
return prefix + "/makeInvoiceRMB";
}else {
return prefix + "/makeInvoiceUSD";
}
}
/**
* 新增开票
*/
@RequiresPermissions("system:salesOrder:makeInvoice")
@Log(title = "销售订单", businessType = BusinessType.MakeInvoice)
@PostMapping("/makeInvoice")
@ResponseBody
public AjaxResult makeInvoiceSave(FinancialTaxInvoice financialTaxInvoice)
{
return toAjax(taxInvoiceService.makeInvoiceSave(financialTaxInvoice));
}
} }

1
ruoyi-admin/src/main/resources/mapper/system/SysSalesOrderMapper.xml

@ -123,6 +123,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="makeStatus != null and makeStatus != ''"> and s.make_status = #{makeStatus}</if> <if test="makeStatus != null and makeStatus != ''"> and s.make_status = #{makeStatus}</if>
<if test="deliveryStatus != null and deliveryStatus != ''"> and s.delivery_status = #{deliveryStatus}</if> <if test="deliveryStatus != null and deliveryStatus != ''"> and s.delivery_status = #{deliveryStatus}</if>
<if test="closeStatus != null and closeStatus != ''"> and s.close_status = #{closeStatus}</if> <if test="closeStatus != null and closeStatus != ''"> and s.close_status = #{closeStatus}</if>
<if test="invoice != null and invoice != ''"> and s.invoice = #{invoice}</if>
<if test="instanceType != null and instanceType != ''"> and s.instance_type = #{instanceType}</if> <if test="instanceType != null and instanceType != ''"> and s.instance_type = #{instanceType}</if>
<if test="instanceId != null and instanceId != ''"> and s.instance_id = #{instanceId}</if> <if test="instanceId != null and instanceId != ''"> and s.instance_id = #{instanceId}</if>
<if test="applyUser != null and applyUser != ''"> and s.apply_user = #{applyUser}</if> <if test="applyUser != null and applyUser != ''"> and s.apply_user = #{applyUser}</if>

166
ruoyi-admin/src/main/resources/templates/system/salesOrder/makeInvoiceRMB.html

@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改国税发票')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-taxInvoice-RMBAdd" th:object="${taxInvoice}">
<input name="taxInvoiceId" th:field="*{taxInvoiceId}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">销售订单编号:</label>
<div class="col-sm-8">
<input name="salesOrderCode" th:field="*{salesOrderCode}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">订单类型:</label>
<div class="col-sm-8">
<select name="salesOrderType" class="form-control m-b" th:with="type=${@dict.getType('sys_order_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{salesOrderType}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">报价币种:</label>
<div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('sys_common_currency')}">
<input type="radio" th:id="${'commonCurrency_' + dict.dictCode}" name="commonCurrency" th:value="${dict.dictValue}" th:field="*{commonCurrency}">
<label th:for="${'commonCurrency_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">客户代码/ID:</label>
<div class="col-sm-8">
<input name="enterpriseCode" th:field="*{enterpriseCode}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">客户名称:</label>
<div class="col-sm-8">
<input name="enterpriseName" th:field="*{enterpriseName}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">联系电话:</label>
<div class="col-sm-8">
<input name="contactNumber" th:field="*{contactNumber}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">公司地址:</label>
<div class="col-sm-8">
<input name="enterpriseAddress" th:field="*{enterpriseAddress}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">开票公司名称:</label>
<div class="col-sm-8">
<input name="invoiceCompanyName" th:field="*{invoiceCompanyName}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">开票公司税号:</label>
<div class="col-sm-8">
<input name="invoiceCompanyCode" th:field="*{invoiceCompanyCode}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">公司开户行:</label>
<div class="col-sm-8">
<input name="depositBank" th:field="*{depositBank}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">公司开户账号:</label>
<div class="col-sm-8">
<input name="bankAccount" th:field="*{bankAccount}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">税率:</label>
<div class="col-sm-8">
<input name="taxRate" th:field="*{taxRate}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">发票种类:</label>
<div class="col-sm-8">
<select name="taxInvoiceClass" class="form-control m-b" th:with="type=${@dict.getType('tax_invoice_class')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{taxInvoiceClass}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">发票类型:</label>
<div class="col-sm-8">
<select name="taxInvoiceType" class="form-control m-b" th:with="type=${@dict.getType('tax_invoice_type')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{taxInvoiceType}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">发票抬头:</label>
<div class="col-sm-8">
<select name="taxInvoiceTitle" class="form-control m-b" th:with="type=${@dict.getType('tax_invoice_title')}">
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{taxInvoiceTitle}"></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">业务人员:</label>
<div class="col-sm-8">
<input name="businessMembers" th:field="*{businessMembers}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">申请人:</label>
<div class="col-sm-8">
<input name="applyUser" th:field="*{applyUser}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">邮箱:</label>
<div class="col-sm-8">
<input name="invoiceEmail" th:field="*{invoiceEmail}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">业务备注:</label>
<div class="col-sm-8">
<input name="businessRemark" th:field="*{businessRemark}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "system/salesOrder"
$("#form-taxInvoice-RMBAdd").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/makeInvoice", $('#form-taxInvoice-RMBAdd').serialize());
}
}
$("input[name='invoiceData']").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",
autoclose: true
});
</script>
</body>
</html>

52
ruoyi-admin/src/main/resources/templates/system/salesOrder/salesOrder.html

@ -159,6 +159,14 @@
th:value="${dict.dictValue}"></option> th:value="${dict.dictValue}"></option>
</select> </select>
</li> </li>
<li>
<label>是否开票:</label>
<select name="invoice" th:with="type=${@dict.getType('sys_whether')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}"
th:value="${dict.dictValue}"></option>
</select>
</li>
<li class="select-time"> <li class="select-time">
<label>录入时间: </label> <label>录入时间: </label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/> <input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
@ -180,6 +188,9 @@
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:salesOrder:add"> <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:salesOrder:add">
<i class="fa fa-plus"></i> 添加 <i class="fa fa-plus"></i> 添加
</a> </a>
<a class="btn btn-success" onclick="makeInvoice()" shiro:hasPermission="system:salesOrder:makeInvoice">
<i class="fa fa-plus"></i> 开票
</a>
</div> </div>
<div class="col-sm-12 select-table table-striped"> <div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table" style="white-space:nowrap"></table> <table id="bootstrap-table" style="white-space:nowrap"></table>
@ -208,6 +219,8 @@
var warehouseDeptDatas = [[${@dict.getType('warehouseDept')}]]; var warehouseDeptDatas = [[${@dict.getType('warehouseDept')}]];
var closeStatusDatas = [[${@dict.getType('sys_close_status')}]]; var closeStatusDatas = [[${@dict.getType('sys_close_status')}]];
var confirmTaxDatas = [[${@dict.getType('sys_confirm_tax')}]]; var confirmTaxDatas = [[${@dict.getType('sys_confirm_tax')}]];
var sysWhetherDatas = [[${@dict.getType('sys_whether')}]];
var loginName = [[${@permission.getPrincipalProperty('loginName')}]]; var loginName = [[${@permission.getPrincipalProperty('loginName')}]];
var prefix = ctx + "system/salesOrder"; var prefix = ctx + "system/salesOrder";
$(function () { $(function () {
@ -288,6 +301,10 @@
} }
}, },
{title: '业务人员',field: 'businessMembers',visible: false}, {title: '业务人员',field: 'businessMembers',visible: false},
{title: '是否开票',field:'invoice',formatter:function(value, row, index){
return $.table.selectDictLabel(sysWhetherDatas, value);
}
},
{title: '销售单号',field: 'salesOrderCode'}, {title: '销售单号',field: 'salesOrderCode'},
{title: '订单类型',field: 'salesOrderType',formatter: function(value, row, index) { {title: '订单类型',field: 'salesOrderType',formatter: function(value, row, index) {
return $.table.selectDictLabel(salesOrderTypeDatas, value); return $.table.selectDictLabel(salesOrderTypeDatas, value);
@ -393,6 +410,41 @@
var url = prefix + "/startAftersales/" + salesOrderId; var url = prefix + "/startAftersales/" + salesOrderId;
$.modal.open("售后",url); $.modal.open("售后",url);
} }
//开票
function makeInvoice() {
// 获取选中的行
const selectedRows = $("#bootstrap-table").bootstrapTable('getSelections');
// 定义状态码常量
const AUDIT_STATUS_APPROVED = "1";//审核通过
const INVOICE_ALLOWED = "1";//允许开票
// 检查是否选择了恰好一行数据
if (selectedRows.length === 1) {
const row = selectedRows[0];
// 检查是否已审核
if (row.auditStatus === AUDIT_STATUS_APPROVED) {
// 检查是否允许开票
if (row.invoice === INVOICE_ALLOWED) {
const invoiceUrl = prefix + "/makeInvoice/" + row.salesOrderId;
$.modal.open("开票", invoiceUrl);
} else {
showWarning("该订单不允许开票");
}
} else {
showWarning("请先审核");
}
} else {
showWarning("请先选择一条销售订单");
}
}
// 显示警告消息的通用函数
function showWarning(message) {
$.modal.msgWarning(message);
}
</script> </script>
</body> </body>
</html> </html>

Loading…
Cancel
Save