diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/param/PointsMallInvoiceApplyParam.java b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/param/PointsMallInvoiceApplyParam.java index 5240d5b1..e59cdee1 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/param/PointsMallInvoiceApplyParam.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/param/PointsMallInvoiceApplyParam.java @@ -7,6 +7,8 @@ public class PointsMallInvoiceApplyParam { private String supplierId; private String orderIds; + private String queryOrderId; + private String userId; private String startDate; private String endDate; private String invoiceDate; diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java index e9402885..c107e12f 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java @@ -350,7 +350,19 @@ public class PointsMallInvoiceServiceImpl extends BaseServiceImpl orders = dao().query(PointsMallOrderSub.class, invoiceOrderCnd(query, "")); + Cnd cnd = invoiceOrderCnd(query, ""); + if (StrUtil.isNotBlank(param.getQueryOrderId())) { + List queryOrderIds = StrUtil.splitTrim(param.getQueryOrderId(), ","); + if (queryOrderIds.size() > 1) { + cnd.and("orderId", "in", queryOrderIds); + } else { + cnd.and("orderId", "like", "%" + param.getQueryOrderId() + "%"); + } + } + if (StrUtil.isNotBlank(param.getUserId())) { + cnd.and("userId", "like", "%" + param.getUserId() + "%"); + } + List orders = dao().query(PointsMallOrderSub.class, cnd); if (CollUtil.isEmpty(orders)) { throw new IllegalArgumentException("无符合条件的订单数据"); } @@ -464,9 +476,6 @@ public class PointsMallInvoiceServiceImpl extends BaseServiceImpl params = orderParams(order.getSupplierId(), userId, order.getExtJson()); + Map params = orderParams(order.getSupplierId(), userId, order.getExtJson(), + "11111111".equals(templateId), order.getTotalPrice()); if (StrUtil.isNotBlank(order.getUserName())) { params.put("#{userName}", order.getUserName()); } @@ -120,18 +121,26 @@ public class MallCallPMessagePushService { } /** 公共模板变量:用户姓名、供应商名称和订单商品列表。 */ - private Map orderParams(String supplierId, String userId, String extJson) { + private Map orderParams(String supplierId, String userId, String extJson, + boolean paymentMessage, BigDecimal totalPrice) { Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", userId).or("loginname", "=", userId)); PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class, Cnd.where("supplierId", "=", supplierId).and("delFlag", "=", false)); Map params = new HashMap<>(); params.put("#{userName}", user == null ? userId : StrUtil.blankToDefault(user.getUsername(), userId)); params.put("#{supplierName}", supplier == null ? supplierId : StrUtil.blankToDefault(supplier.getSupplierName(), supplierId)); StringBuilder sb = new StringBuilder(); - sb.append("商品列表: ").append(System.lineSeparator()); + sb.append(paymentMessage ? "商品列表:" : "商品列表: ").append(System.lineSeparator()); List products = StrUtil.isBlank(extJson) || "null".equalsIgnoreCase(extJson.trim()) ? Collections.emptyList() : JSONUtil.toList(extJson, OrderProInfoDTO.class); - products.forEach(product -> sb.append(" 商品名称: ").append(product.getName()) - .append(",商品价格:").append(formatMoney(product.getPrice())).append("元").append(System.lineSeparator())); + if (paymentMessage) { + products.forEach(product -> sb.append("商品名称:").append(product.getName()) + .append(" * ").append(product.getNumber() == null ? "-" : product.getNumber()) + .append(",商品单价:").append(formatMoney(product.getPrice())).append("元").append(System.lineSeparator())); + sb.append(System.lineSeparator()).append("订单合计:¥").append(formatMoney(totalPrice)); + } else { + products.forEach(product -> sb.append(" 商品名称: ").append(product.getName()) + .append(",商品价格:").append(formatMoney(product.getPrice())).append("元").append(System.lineSeparator())); + } params.put("#{productList}", sb.toString()); return params; } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInvoiceInfoQueryService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInvoiceInfoQueryService.java index 96536683..ed95e8af 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInvoiceInfoQueryService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInvoiceInfoQueryService.java @@ -37,6 +37,10 @@ public class MallInvoiceInfoQueryService extends AbstractMallBridgeSupport { } public MallPictureOutboundResult queryInvoiceFiles(String supplierId, String settlementId, List fileIds) { + return queryFiles(supplierId, settlementId, "2", fileIds); + } + + public MallPictureOutboundResult queryFiles(String supplierId, String idNumber, String queryType, List fileIds) { PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class, Cnd.where("supplierId", "=", supplierId).and("delFlag", "=", false)); if (supplier == null || StrUtil.isBlank(supplier.getSupplierApiUrl())) { @@ -51,8 +55,8 @@ public class MallInvoiceInfoQueryService extends AbstractMallBridgeSupport { dto.setSupplierId(supplierId); dto.setToken(MallBridgeCryptoUtil.generateSign(supplierId, supplier.getClientId(), timestamp)); dto.setTimestamp(timestamp); - dto.setQueryType("2"); - dto.setIdNumber(settlementId); + dto.setQueryType(queryType); + dto.setIdNumber(idNumber); dto.setFileIdList(fileIds); HashMap body = new HashMap<>(); body.put("Address4", supplier.getSupplierApiUrl() + "/supplierOpenApi/pointOrder/queryFileBase64Info"); @@ -64,8 +68,8 @@ public class MallInvoiceInfoQueryService extends AbstractMallBridgeSupport { String response = HttpUtil.createPost(apiUrl).contentType("application/json;charset=UTF-8") .body(JSONUtil.toJsonStr(body)).execute().body(); JSONObject payload = MallBridgeResponseUtil.parse(response); - if (payload.getInt("resultCode") != 0) { - throw new IllegalArgumentException(StrUtil.blankToDefault(payload.getStr("message"), "获取发票文件失败")); + if (payload.getInt("resultCode", -1) != 0) { + throw new IllegalArgumentException(StrUtil.blankToDefault(payload.getStr("message"), "获取供应商文件失败")); } return JSONUtil.toBean(payload, MallPictureOutboundResult.class); } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderSubHistoryServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderSubHistoryServiceImpl.java index a2e9eef2..dad2fd63 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderSubHistoryServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderSubHistoryServiceImpl.java @@ -2,33 +2,98 @@ package com.budwk.app.zhgh.pointsmall.order.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileTypeUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.enums.SysFileEngineTypeEnum; +import com.budwk.app.sys.services.SysFileService; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoDTO; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallPictureOutboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallInvoiceInfoQueryService; import com.budwk.app.zhgh.pointsmall.order.enums.MallOrderStatusEnum; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSubHistory; import com.budwk.app.zhgh.pointsmall.order.result.SubOrderBuildResult; import com.budwk.app.zhgh.pointsmall.order.service.PointsMallOrderSubHistoryService; import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import java.util.Collections; import java.util.List; +import java.io.ByteArrayInputStream; +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; @IocBean(args = {"refer:dao"}) public class PointsMallOrderSubHistoryServiceImpl extends BaseServiceImpl implements PointsMallOrderSubHistoryService { + @Inject + private MallInvoiceInfoQueryService mallInvoiceInfoQueryService; + @Inject + private SysFileService sysFileService; + public PointsMallOrderSubHistoryServiceImpl(Dao dao) { super(dao); } @Override public List getPictureBase64(String supplierId, String orderId, String queryType, List orderProInfo) { - return CollUtil.isEmpty(orderProInfo) ? Collections.emptyList() : orderProInfo; + if (CollUtil.isEmpty(orderProInfo)) { + return Collections.emptyList(); + } + List fileIds = orderProInfo.stream().map(OrderProInfoDTO::getSku) + .filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList()); + if (fileIds.isEmpty()) { + throw new IllegalArgumentException("商品SKU为空,无法获取商品图片"); + } + try { + // 供应商按子订单和 SKU 返回图片 Base64,订单只保存工会文件服务地址。 + MallPictureOutboundResult result = mallInvoiceInfoQueryService.queryFiles(supplierId, orderId, queryType, fileIds); + Map localUrls = new LinkedHashMap<>(); + for (OrderProInfoDTO product : orderProInfo) { + String sku = product.getSku(); + if (StrUtil.isBlank(sku)) { + throw new IllegalArgumentException("商品SKU为空,无法获取商品图片"); + } + String localUrl = localUrls.get(sku); + if (localUrl == null) { + String base64 = result.getImageEncodeMap() == null ? null : result.getImageEncodeMap().get(sku); + if (StrUtil.isBlank(base64)) { + if (CollUtil.isEmpty(product.getPicInfo()) && StrUtil.isBlank(product.getFilePath()) && StrUtil.isBlank(product.getFileId())) { + continue; + } + throw new IllegalArgumentException("未获取到商品图片Base64:" + sku); + } + if (base64.startsWith("data:")) { + base64 = base64.substring(base64.indexOf(',') + 1); + } + byte[] bytes = Base64.getDecoder().decode(base64.replaceAll("\\s", "")); + String fileType = FileTypeUtil.getType(new ByteArrayInputStream(bytes)); + if (bytes.length == 0 || fileType == null || !fileType.matches("(?i)jpg|jpeg|png|gif|bmp|webp")) { + throw new IllegalArgumentException("商品图片内容为空或格式不支持:" + sku); + } + localUrl = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), + "product-" + UUID.randomUUID() + "." + fileType.toLowerCase(java.util.Locale.ROOT), bytes); + if (StrUtil.isBlank(localUrl)) { + throw new IllegalArgumentException("商品图片上传失败:" + sku); + } + localUrls.put(sku, localUrl); + } + product.setPicInfo(Collections.singletonList(localUrl)); + product.setFilePath(localUrl); + product.setFileId(localUrl); + } + return orderProInfo; + } catch (Exception e) { + throw new IllegalArgumentException("商品图片同步失败:" + e.getMessage(), e); + } } @Override diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliation/service/impl/PointsMallReconciliationServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliation/service/impl/PointsMallReconciliationServiceImpl.java index d5563d73..cd8c9854 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliation/service/impl/PointsMallReconciliationServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliation/service/impl/PointsMallReconciliationServiceImpl.java @@ -98,10 +98,10 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl orderInfoList = dao().query(PointsMallOrderSub.class, reconciliationCnd(reconciliationBO, "")); if (CollUtil.isEmpty(orderInfoList)) { - return Result.error("浦发积分商城没有查询到对账订单数据"); + return Result.error("积分商城没有查询到对账订单数据"); } Set orderIdList = orderInfoList.stream().map(PointsMallOrderSub::getOrderId).collect(Collectors.toSet()); if (StrUtil.isNotBlank(reconciliationBO.getOrderId()) @@ -159,7 +159,7 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl reconciliationList2 = orderNotReturn(pfKeySet, supplierKeySet, pfOrderList); if (CollUtil.isNotEmpty(reconciliationList2)) { reconciliationList1.addAll(reconciliationList2); @@ -171,7 +171,7 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl reconciliationList3 = orderNotExist(supplierKeySet, pfKeySet, supplierOrderList); if (CollUtil.isNotEmpty(reconciliationList3)) { reconciliationList1.addAll(reconciliationList3); @@ -361,7 +361,7 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl !supplierKeySet.contains(key)).forEach(key -> { List pfOrders = pfOrderList.get(key); if (CollUtil.isNotEmpty(pfOrders)) { - reconciliationList.add(buildReconciliationRecord(null, pfOrders.get(0), 1, "浦发积分商城已确认收货,对账接口未返回")); + reconciliationList.add(buildReconciliationRecord(null, pfOrders.get(0), 1, "积分商城已确认收货,对账接口未返回")); } }); return reconciliationList; } /** - * 浦发积分商城不存在此订单,无法对账 + * 积分商城不存在此订单,无法对账 * * @param supplierKeySet 供应商key * @param pfKeySet 浦发key @@ -394,7 +394,7 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl !pfKeySet.contains(key)).forEach(key -> { List supplierOrders = supplierOrderList.get(key); if (CollUtil.isNotEmpty(supplierOrders)) { - reconciliationList.add(buildReconciliationRecord(supplierOrders.get(0), null, 2, "浦发积分商城不存在此订单,无法对账")); + reconciliationList.add(buildReconciliationRecord(supplierOrders.get(0), null, 2, "积分商城不存在此订单,无法对账")); } }); return reconciliationList; diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/PointsMallReconciliationRecordService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/PointsMallReconciliationRecordService.java index 41d80b63..9e49563b 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/PointsMallReconciliationRecordService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/PointsMallReconciliationRecordService.java @@ -5,13 +5,13 @@ import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.pointsmall.reconciliationrecord.models.PointsMallReconciliationRecord; import com.budwk.app.zhgh.pointsmall.reconciliationrecord.param.PointsMallReconciliationRecordPageParam; import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; -import org.nutz.dao.entity.Record; import java.util.List; +import java.util.Map; public interface PointsMallReconciliationRecordService extends BaseService { - Pagination page(PointsMallReconciliationRecordPageParam param); + Pagination> page(PointsMallReconciliationRecordPageParam param); List listSuppliers(); } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/impl/PointsMallReconciliationRecordServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/impl/PointsMallReconciliationRecordServiceImpl.java index f8aabb03..debad93e 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/impl/PointsMallReconciliationRecordServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/reconciliationrecord/service/impl/PointsMallReconciliationRecordServiceImpl.java @@ -3,6 +3,7 @@ package com.budwk.app.zhgh.pointsmall.reconciliationrecord.service.impl; import cn.hutool.core.util.StrUtil; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_user; import com.budwk.app.zhgh.pointsmall.reconciliationrecord.models.PointsMallReconciliationRecord; import com.budwk.app.zhgh.pointsmall.reconciliationrecord.param.PointsMallReconciliationRecordPageParam; import com.budwk.app.zhgh.pointsmall.reconciliationrecord.service.PointsMallReconciliationRecordService; @@ -10,11 +11,14 @@ import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; -import org.nutz.dao.entity.Record; import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.IocBean; import java.util.List; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; @IocBean(args = {"refer:dao"}) public class PointsMallReconciliationRecordServiceImpl extends BaseServiceImpl implements PointsMallReconciliationRecordService { @@ -24,7 +28,7 @@ public class PointsMallReconciliationRecordServiceImpl extends BaseServiceImpl

page(PointsMallReconciliationRecordPageParam param) { + public Pagination> page(PointsMallReconciliationRecordPageParam param) { Cnd cnd = Cnd.where("r.delFlag", "=", false); if (StrUtil.isNotBlank(param.getSupplierId())) { cnd.and("r.supplierId", "=", param.getSupplierId()); @@ -33,7 +37,12 @@ public class PointsMallReconciliationRecordServiceImpl extends BaseServiceImpl

> page = listPageMap(param.getPageNumber(), param.getPageSize(), sql); + if (page.getList() != null && !page.getList().isEmpty()) { + List userIds = page.getList().stream().map(record -> (String) record.get("userId")) + .filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList()); + Map loginNames = new HashMap<>(); + if (!userIds.isEmpty()) { + List users = dao().query(Sys_user.class, Cnd.where("id", "in", userIds).and("delFlag", "=", false)); + users.forEach(user -> loginNames.put(user.getId(), user.getLoginname())); + } + page.getList().forEach(record -> record.put("loginname", loginNames.get(record.get("userId")))); + } + return page; } @Override diff --git a/src/main/resources/views/platform/zhgh/points-mall/invoice/index.html b/src/main/resources/views/platform/zhgh/points-mall/invoice/index.html index a34aa273..38b92b18 100644 --- a/src/main/resources/views/platform/zhgh/points-mall/invoice/index.html +++ b/src/main/resources/views/platform/zhgh/points-mall/invoice/index.html @@ -50,22 +50,23 @@ layout("/layouts/platform.html"){ - - - - - - + + - - + + + + + + @@ -274,6 +276,8 @@ layout("/layouts/platform.html"){ }, applyDialogVisible: false, applyLoading: false, + applyScope: {}, + applySelectionCount: 0, applyForm: { invoiceDate: [new Date().getFullYear(), String(new Date().getMonth() + 1).padStart(2, "0"), String(new Date().getDate()).padStart(2, "0")].join("-"), invoiceTitle: "测试工会(开发测试)", @@ -478,13 +482,24 @@ layout("/layouts/platform.html"){ } }, openApplyDialog() { - if (!this.pageForm.supplierId || !this.pageForm.startDate || !this.pageForm.endDate) { + if (this.tableLoading || !this.lastQuery) { + this.notifyWarning("请先查询订单列表") return } - if (!this.selections.length) { - this.notifyWarning("请先勾选需要开票的订单") + const query = this.lastQuery + if (!query.supplierId || !query.startDate || !query.endDate || query.reconciliationStatus !== 1 || query.invoiceStatus !== 0) { + this.notifyWarning("请查询对账成功且未开票的订单") return } + this.applySelectionCount = this.selections.length + this.applyScope = { + supplierId: query.supplierId, + startDate: query.startDate, + endDate: query.endDate, + queryOrderId: query.orderId, + userId: query.userId, + orderIds: this.selections.map(item => item.orderId).join(",") || null + } this.applyForm = { invoiceDate: [new Date().getFullYear(), String(new Date().getMonth() + 1).padStart(2, "0"), String(new Date().getDate()).padStart(2, "0")].join("-"), invoiceTitle: "测试工会(开发测试)", @@ -497,17 +512,12 @@ layout("/layouts/platform.html"){ }, submitApply() { this.$refs.applyFormRef.validate(async (valid) => { - if (!valid) { + if (!valid || this.applyLoading) { return } this.applyLoading = true try { - const params = Object.assign({}, this.applyForm, { - supplierId: this.pageForm.supplierId, - startDate: this.pageForm.startDate, - endDate: this.pageForm.endDate, - orderIds: this.selections.map((item) => item.orderId).join(",") - }) + const params = Object.assign({}, this.applyForm, this.applyScope) const resp = await this.$axios.post("/platform/zhgh/points-mall/invoice/applyInvoice", params) if (resp.code === 0) { this.notifySuccess(resp.data || "开票申请成功") diff --git a/src/main/resources/views/platform/zhgh/points-mall/reconciliationRecord/index.html b/src/main/resources/views/platform/zhgh/points-mall/reconciliationRecord/index.html index b8f85a22..aac191ce 100644 --- a/src/main/resources/views/platform/zhgh/points-mall/reconciliationRecord/index.html +++ b/src/main/resources/views/platform/zhgh/points-mall/reconciliationRecord/index.html @@ -13,25 +13,6 @@ layout("/layouts/platform.html"){ - - - - - - - - - - - - - - - - - - - @@ -39,11 +20,10 @@ layout("/layouts/platform.html"){ - - + @@ -57,18 +37,7 @@ layout("/layouts/platform.html"){ {{ diffTypeName(row.diffType) }} - - - - - - - {{ currentRecord.batchNo || "-" }} {{ currentRecord.orderId || "-" }} {{ currentRecord.supplierName || currentRecord.supplierId || "-" }} - {{ currentRecord.userId || "-" }} + {{ currentRecord.loginname || "-" }} {{ currentRecord.pTotalPrice || "0" }} {{ currentRecord.sTotalPrice || "0" }} {{ currentRecord.pCashAmount || "0" }} @@ -121,11 +90,7 @@ layout("/layouts/platform.html"){ pageSize: 10, totalCount: 0, supplierId: null, - orderId: null, - userId: null, - diffType: null, - batchNo: null, - noticeStatus: null + orderId: null }, detailDialogVisible: false, currentRecord: null