src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java
@@ -676,4 +676,21 @@ return new FebsResponse().success().data(data); } /** * 发票列表-订单子表 */ @GetMapping(value = "/invoiceItemList") public FebsResponse invoiceItemList() { return new FebsResponse().success().data(mallInvoiceService.invoiceItemList()); } /** * 发票列表-上传发票 */ @PostMapping("addInvoiceUrl") @ControllerEndpoint(operation = " 发票列表-上传发票", exceptionMessage = "操作失败") public FebsResponse addInvoiceUrl(@Valid MallInvoice mallInvoice) { return mallInvoiceService.addInvoiceUrl(mallInvoice); } } src/main/java/cc/mrbird/febs/mall/controller/ViewMallOrderController.java
@@ -8,8 +8,10 @@ import cc.mrbird.febs.mall.entity.MallExpressInfo; import cc.mrbird.febs.mall.entity.MallOrderRefund; import cc.mrbird.febs.mall.mapper.MallExpressInfoMapper; import cc.mrbird.febs.mall.mapper.MallInvoiceMapper; import cc.mrbird.febs.mall.mapper.MallOrderRefundMapper; import cc.mrbird.febs.mall.service.IAdminMallOrderService; import cc.mrbird.febs.mall.service.MallInvoiceService; import cc.mrbird.febs.mall.vo.*; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; @@ -29,6 +31,7 @@ public class ViewMallOrderController extends BaseController { private final IAdminMallOrderService adminMallOrderService; private final MallInvoiceMapper mallInvoiceMapper; private final MallOrderRefundMapper mallOrderRefundMapper; @@ -266,4 +269,26 @@ return FebsUtil.view("modules/order/invoiceList"); } /** * 发票列表-详情 * @param id * @param model * @return */ @GetMapping("invoiceDetail/{id}") @RequiresPermissions("invoiceDetail:view") public String invoiceDetail(@PathVariable long id, Model model) { String existToken = redisUtils.getString("ADMIN_INVOICE_ID"); if (StrUtil.isNotBlank(existToken)) { Object o = redisUtils.get(existToken); if (ObjectUtil.isNotEmpty(o)) { redisUtils.del(existToken); } } redisUtils.set("ADMIN_INVOICE_ID", id, -1); AdminInvoiceDetailVo data = mallInvoiceMapper.getAdminInvoiceDetailVoById(id); model.addAttribute("invoiceDetail", data); return FebsUtil.view("modules/order/invoiceDetail"); } } src/main/java/cc/mrbird/febs/mall/entity/MallOrderItem.java
@@ -52,4 +52,7 @@ @TableField(exist = false) private long[] orderIdsStr; @TableField(exist = false) private String unit; } src/main/java/cc/mrbird/febs/mall/mapper/MallInvoiceMapper.java
@@ -3,6 +3,8 @@ import cc.mrbird.febs.mall.dto.AdminMallInvoiceDto; import cc.mrbird.febs.mall.dto.ApiMallInvoiceDto; import cc.mrbird.febs.mall.entity.MallInvoice; import cc.mrbird.febs.mall.entity.MallOrderItem; import cc.mrbird.febs.mall.vo.AdminInvoiceDetailVo; import cc.mrbird.febs.mall.vo.ApiMallInvoiceVo; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -18,4 +20,7 @@ List<MallInvoice> selectByFapiaoApplyIdAndMemberId(@Param("fapiaoApplyId")String fapiaoApplyId, @Param("memberId")Long memberId); IPage<MallInvoice> getInvoiceListInPage(Page<MallInvoice> page, @Param("record")AdminMallInvoiceDto mallInvoiceDto); AdminInvoiceDetailVo getAdminInvoiceDetailVoById(@Param("id")long id); List<MallOrderItem> getInvoiceItemList(@Param("record")MallInvoice mallInvoice); } src/main/java/cc/mrbird/febs/mall/service/MallInvoiceService.java
@@ -5,7 +5,10 @@ import cc.mrbird.febs.mall.dto.AdminMallInvoiceDto; import cc.mrbird.febs.mall.dto.ApiMallInvoiceDto; import cc.mrbird.febs.mall.entity.MallInvoice; import cc.mrbird.febs.mall.entity.MallOrderItem; import com.baomidou.mybatisplus.core.metadata.IPage; import java.util.List; public interface MallInvoiceService { @@ -19,4 +22,8 @@ void mallInvoiceJob(); IPage<MallInvoice> getInvoiceList(AdminMallInvoiceDto mallInvoiceDto, QueryRequest request); List<MallOrderItem> invoiceItemList(); FebsResponse addInvoiceUrl(MallInvoice mallInvoice); } src/main/java/cc/mrbird/febs/mall/service/impl/MallInvoiceServiceImpl.java
@@ -4,6 +4,7 @@ import cc.mrbird.febs.common.entity.QueryRequest; import cc.mrbird.febs.common.enumerates.OrderStatusEnum; import cc.mrbird.febs.common.utils.LoginUserUtil; import cc.mrbird.febs.common.utils.RedisUtils; import cc.mrbird.febs.mall.dto.AdminMallInvoiceDto; import cc.mrbird.febs.mall.dto.ApiMallInvoiceDto; import cc.mrbird.febs.mall.entity.MallInvoice; @@ -34,6 +35,7 @@ private final MallOrderInfoMapper mallOrderInfoMapper; private final MallOrderItemMapper mallOrderItemMapper; private final RedisUtils redisUtils; @Override public FebsResponse getInvoices(ApiMallInvoiceDto apiMallInvoiceDto) { MallMember member = LoginUserUtil.getLoginUser(); @@ -65,8 +67,10 @@ String payOrderNo = mallOrderInfo.getPayOrderNo(); List<MallInvoice> mallInvoices = this.baseMapper.selectByFapiaoApplyIdAndMemberId(payOrderNo, memberId); if(CollUtil.isNotEmpty(mallInvoices)){ continue; } MallInvoice mallInvoice = mallInvoices.get(0); mallInvoice.setStatus(mallOrderInfo.getStatus()); this.baseMapper.updateById(mallInvoice); }else{ MallInvoice mallInvoice = new MallInvoice(); mallInvoice.setMemberId(memberId); mallInvoice.setFapiaoApplyId(payOrderNo); @@ -78,13 +82,13 @@ mallInvoice.setGoodsImg(mallOrderItemList.get(0).getSkuImage()); mallInvoice.setState(0); this.baseMapper.insert(mallInvoice); } /** * 更新订单为已开票 */ mallOrderInfo.setIsInvoice(1); mallOrderInfoMapper.updateById(mallOrderInfo); } } @@ -94,4 +98,31 @@ Page<MallInvoice> page = new Page<>(request.getPageNum(), request.getPageSize()); return this.baseMapper.getInvoiceListInPage(page, mallInvoiceDto); } @Override public List<MallOrderItem> invoiceItemList() { Long existToken = Long.parseLong(redisUtils.getString("ADMIN_INVOICE_ID")); MallInvoice mallInvoice = this.baseMapper.selectById(existToken); if(ObjectUtil.isEmpty(mallInvoice)){ return null; } return this.baseMapper.getInvoiceItemList(mallInvoice); } @Override public FebsResponse addInvoiceUrl(MallInvoice mallInvoice) { Long id = mallInvoice.getId(); MallInvoice mallInvoiceOld = this.baseMapper.selectById(id); if(ObjectUtil.isEmpty(mallInvoiceOld)){ return new FebsResponse().fail().message("开票信息异常。"); } Integer status = mallInvoiceOld.getStatus(); if(OrderStatusEnum.FINISH.getValue() != status){ return new FebsResponse().fail().message("订单还未完成,请勿开发票。"); } mallInvoiceOld.setInvoiceUrl(mallInvoice.getInvoiceUrl()); mallInvoiceOld.setState(2); this.baseMapper.updateById(mallInvoiceOld); return new FebsResponse().success(); } } src/main/java/cc/mrbird/febs/mall/vo/AdminInvoiceDetailVo.java
New file @@ -0,0 +1,47 @@ package cc.mrbird.febs.mall.vo; import lombok.Data; import java.math.BigDecimal; @Data public class AdminInvoiceDetailVo { private Long id; /** *【购买方类型】 购买方类型 * 可选取值: * INDIVIDUAL: 个人 * ORGANIZATION: 单位 */ private String type; /** *【名称】 购买方名称 */ private String name; /** *【纳税人识别号】 购买方纳税人识别号,购买方类型为ORGANIZATION时必须存在 */ private String taxpayerId; /** *【地址】 购买方地址 */ private String address; /** *【电话】 购买方电话 */ private String telephone; /** *【开户银行】 购买方开户银行 */ private String bankName; /** *【银行账号】 购买方银行账号 */ private String bankAccount; private String orderNo;//订单编号 private BigDecimal amount;//订单金额 private String invoiceUrl;//订单编号 } src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java
@@ -361,8 +361,8 @@ if(ObjectUtil.isNotEmpty(mallOrderInfo)){ //更新订单状态 mallOrderInfo.setIsInvoice(1); mallOrderInfoMapper.updateById(mallOrderInfo); // mallOrderInfo.setIsInvoice(1); // mallOrderInfoMapper.updateById(mallOrderInfo); //获取用户的抬头信息 String userInvoiceInfo = getUserInvoiceInfo(fapiao_apply_id); JSONObject userInvoiceInfoJson = JSONUtil.parseObj(userInvoiceInfo); src/main/resources/mapper/modules/MallInvoiceMapper.xml
@@ -38,14 +38,30 @@ <if test="record.state != null"> and a.state = #{record.state} </if> <if test="record.orderNo != null"> <if test="record.orderNo != null and record.orderNo != ''"> and a.order_no = #{record.orderNo} </if> <if test="record.payOrderNo != null"> <if test="record.payOrderNo != null and record.payOrderNo != ''"> and a.fapiao_apply_id = #{record.payOrderNo} </if> </where> order by a.created_time desc </select> <select id="getAdminInvoiceDetailVoById" resultType="cc.mrbird.febs.mall.vo.AdminInvoiceDetailVo"> select a.* from mall_invoice a where id = #{id} </select> <select id="getInvoiceItemList" resultType="cc.mrbird.febs.mall.entity.MallOrderItem"> select a.*, b.unit from mall_order_item a left join mall_goods b on a.goods_id = b.id where order_id = #{record.orderId} </select> </mapper> src/main/resources/templates/febs/views/modules/order/invoiceDetail.html
New file @@ -0,0 +1,248 @@ <style> #invoice-info { padding: 20px 25px 25px 0; } #invoice-info .layui-treeSelect .ztree li a, .ztree li span { margin: 0 0 2px 3px !important; } #invoice-info #data-permission-tree-block { border: 1px solid #eee; border-radius: 2px; padding: 3px 0; } #invoice-info .layui-treeSelect .ztree li span.button.switch { top: 1px; left: 3px; } </style> <div class="layui-fluid" id="invoice-info"> <blockquote class="layui-elem-quote blue-border">抬头信息</blockquote> <form class="layui-form" action="" lay-filter="invoice-info-form"> <div class="layui-card"> <div class="layui-form-item febs-hide"> <label class="layui-form-label febs-form-item-require">id:</label> <div class="layui-input-block"> <input type="text" name="id"> </div> </div> <div class="layui-row layui-col-space10 layui-form-item"> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">开票类型:</label> <div class="layui-input-block"> <input type="radio" name="type" value="INDIVIDUAL" title="个人" checked="" readonly> <input type="radio" name="type" value="ORGANIZATION" title="单位" readonly> </div> </div> </div> <div class="layui-row layui-col-space10 layui-form-item"> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">名称:</label> <div class="layui-input-block"> <input type="text" name="name" autocomplete="off" class="layui-input" readonly> </div> </div> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">识别号:</label> <div class="layui-input-block"> <input type="text" name="taxpayerId" autocomplete="off" class="layui-input" readonly> </div> </div> </div> <div class="layui-row layui-col-space10 layui-form-item"> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">地址:</label> <div class="layui-input-block"> <input type="text" name="address" autocomplete="off" class="layui-input" readonly> </div> </div> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">电话:</label> <div class="layui-input-block"> <input type="text" name="telephone" autocomplete="off" class="layui-input" readonly> </div> </div> </div> <div class="layui-row layui-col-space10 layui-form-item"> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">开户银行:</label> <div class="layui-input-block"> <input type="text" name="bankName" autocomplete="off" class="layui-input" readonly> </div> </div> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">银行账号:</label> <div class="layui-input-block"> <input type="text" name="bankAccount" autocomplete="off" class="layui-input" readonly> </div> </div> </div> <div class="layui-row layui-col-space10 layui-form-item"> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">订单编号:</label> <div class="layui-input-block"> <input type="text" name="orderNo" autocomplete="off" class="layui-input" readonly> </div> </div> <div class="layui-col-lg6"> <label class="layui-form-label febs-form-item-require">订单金额:</label> <div class="layui-input-block"> <input type="text" name="amount" autocomplete="off" class="layui-input" readonly> </div> </div> </div> <div class="layui-form-item"> <label class="layui-form-label febs-form-item-require">发票:</label> <div class="layui-input-block"> <div class="layui-upload"> <button type="button" class="layui-btn layui-btn-normal layui-btn" id="test2">上传发票</button> <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;"> <div class="layui-upload-list" id="demo2"></div> </blockquote> <div class="layui-word-aux">双击图片删除</div> </div> </div> </div> <div class="layui-form-item febs-hide"> <label class="layui-form-label">发票链接:</label> <div class="layui-input-block"> <input type="text" id="invoiceUrl" lay-verify="required" name="invoiceUrl" autocomplete="off" class="layui-input" readonly> </div> </div> <div class="layui-row layui-col-space10 layui-form-item" style="text-align: center;"> <button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="invoice-detail-form-submit" id="submit">保存</button> </div> </div> </form> </div> <blockquote class="layui-elem-quote blue-border">订单详情</blockquote> <div class="layui-card-body febs-table-full"> <table id="invoiceOrderItemTable" lay-filter="invoiceOrderItemTable"></table> </div> <script data-th-inline="javascript"> layui.use(['upload','febs', 'form', 'formSelects', 'validate', 'treeSelect', 'table','eleTree'], function () { var $ = layui.$, febs = layui.febs, layer = layui.layer, table = layui.table, formSelects = layui.formSelects, treeSelect = layui.treeSelect, form = layui.form, eleTree = layui.eleTree, invoiceDetail = [[${invoiceDetail}]], $view = $('#invoice-info'), validate = layui.validate, upload = layui.upload, _deptTree; form.render(); table.render({ elem: '#invoiceOrderItemTable' ,cols: [[ //表头 {field: 'skuName', title: '货物、应税劳务、服务名称', minWidth: 300,align:'left'}, {field: 'skuName', title: '规格型号', minWidth: 150,align:'left'}, {field: 'unit', title: '单位', minWidth: 100,align:'left'}, {field: 'cnt', title: '数量', minWidth: 100,align:'left'}, {field: 'price', title: '单价', minWidth: 100,align:'left'}, {field: 'amount', title: '金额', minWidth: 150,align:'left'} ]] ,data: [] }); dicDataReq("invoiceOrderItemTable"); function dicDataReq(type) { $.get(ctx + 'admin/order/invoiceItemList/', function (r) { if (r.code === 200) { var data = r.data; table.reload('invoiceOrderItemTable', { data : data }); } }); } // 表格初始化 initInvoiceDetailValue(); function initInvoiceDetailValue() { if(invoiceDetail.invoiceUrl != null || invoiceDetail.invoiceUrl != ''){ $('#demo2').append('<img src="'+ invoiceDetail.invoiceUrl +'" class="layui-upload-img" style="width: 100px">') $("#invoiceUrl").val(invoiceDetail.invoiceUrl); } form.val("invoice-info-form", { "id": invoiceDetail.id, "type": invoiceDetail.type, "name": invoiceDetail.name, "taxpayerId": invoiceDetail.taxpayerId, "address": invoiceDetail.address, "telephone": invoiceDetail.telephone, "bankName": invoiceDetail.bankName, "bankAccount": invoiceDetail.bankAccount, "orderNo": invoiceDetail.orderNo, "invoiceUrl": invoiceDetail.invoiceUrl, "amount": invoiceDetail.amount }); } //图片上传 upload.render({ elem: '#test2' ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口 // ,multiple: true ,accept: 'file' ,before: function(obj){ //预读本地文件示例,不支持ie8 obj.preview(function(index, file, result){ if ($("#invoiceUrl").val()) { $('#demo2').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img single-image" style="width: 130px">') } else { $('#demo2').append('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img single-image" style="width: 130px">') } }); } ,done: function(res){ var item = this.item; //如果上传失败 if(res.code !== 0){ return layer.msg('上传失败'); } $("#invoiceUrl").val(res.data.src); layer.msg('上传完毕', {icon: 1}); imgUnBind(".single-image"); imgSingleBind(); } ,error: function(err){ return layer.msg('上传失败'); } }); function imgUnBind(className) { $(className).each(function() { $(this).unbind('dblclick'); }) } function imgSingleBind() { $(".single-image").each(function(index, element) { $(this).on("dblclick", function() { var imgThumb = $(".single-image")[index]; $(imgThumb).remove(); $("#invoiceUrl").val(""); imgUnBind(".single-image"); imgSingleBind(); }); }) } form.on('submit(invoice-detail-form-submit)', function (data) { febs.post(ctx + 'admin/order/addInvoiceUrl', data.field, function () { layer.closeAll(); febs.alert.success('操作成功'); $('#febs-invoice').find('#query').click(); }); return false; }); }); </script> src/main/resources/templates/febs/views/modules/order/invoiceList.html
@@ -23,8 +23,8 @@ <div class="layui-input-inline"> <select name="state"> <option value="">请选择</option> <option value="0">未开票</option> <option value="1">开票中</option> <option value="0">待申请</option> <option value="1">待开票</option> <option value="2">已开票</option> </select> </div> @@ -102,68 +102,13 @@ // 表格初始化 initInvoiceTable(); upload.render({ elem: '#importDeliver' ,url: 'admin/order/importDeliver' //此处配置你自己的上传接口即可 ,accept: 'file' //普通文件 ,done: function(res){ console.log("123"); febs.alert.success('操作成功'); $query.click(); } }); // 初始化表格操作栏各个按钮功能 table.on('tool(invoiceTable)', function (obj) { var data = obj.data, layEvent = obj.event; if (layEvent === 'deliverGoods') { febs.modal.open('发货', 'modules/order/deliverGoods/' + data.id, { btn: ['确认','取消'], yes: function (index, layero) { $('#deliver-update').find('#submit').trigger('click'); // $query.click(); }, btn2: function () { layer.closeAll(); } }); } if (layEvent === 'updateDeliver') { febs.modal.open('修改物流信息', 'modules/order/deliverGoods/' + data.id, { btn: ['确认','取消'], yes: function (index, layero) { $('#deliver-update').find('#deliverInfoSubmit').trigger('click'); // $query.click(); }, btn2: function () { layer.closeAll(); } }); } if (layEvent === 'seeOrder') { febs.modal.open( '订单详情', 'modules/order/orderDetail/' + data.id, { maxmin: true, }); } if (layEvent === 'cancelOrder') { febs.modal.confirm('取消订单', '确认取消订单?', function () { cancelOrder(data.id); }); } if (layEvent === 'seePayImage') { var t = $view.find('#seePayImage'+data.id+''); //页面层 layer.open({ type: 1, title: "支付凭证", skin: 'layui-layer-rim', //加上边框 area: ['80%', '80%'], //宽高 shadeClose: true, //开启遮罩关闭 end: function (index, layero) { return false; }, content: '<div style="text-align:center"><img src="' + $(t).attr('src') + '" /></div>' if (layEvent === 'seeInvoiceDetail') { febs.modal.open('开票信息', 'modules/order/invoiceDetail/'+ data.id, { area:['100%','100%'], }); } }); @@ -203,7 +148,7 @@ templet: function (d) { if (d.type === 'INDIVIDUAL') { return '<span style="color:red;">个人</span>' } else if (d.status === 'ORGANIZATION') { } else if (d.type === 'ORGANIZATION') { return '<span style="color:green;">单位</span>' }else{ return '' @@ -249,17 +194,12 @@ }, minWidth: 100,align:'center'}, {title: '操作', templet: function (d) { if(d.status === 2){ return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="seeOrder" shiro:hasPermission="user:update">详情</button>' +'<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="deliverGoods" shiro:hasPermission="user:update">发货</button>' }else if(d.status === 3){ return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="seeOrder" shiro:hasPermission="user:update">详情</button>' +'<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="updateDeliver" shiro:hasPermission="user:update">修改物流信息</button>' if(d.status === 4){ return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="seeInvoiceDetail" shiro:hasPermission="user:update">开票信息</button>' }else{ return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="seeOrder" shiro:hasPermission="user:update">详情</button>' return '' } },minWidth: 200,align:'center', fixed:'right'} },minWidth: 300,align:'center', fixed:'right'} ]] }); }