diff --git a/admin-front/src/api/jysystem/order.js b/admin-front/src/api/jysystem/order.js index 88b3ff2..d2da5e5 100644 --- a/admin-front/src/api/jysystem/order.js +++ b/admin-front/src/api/jysystem/order.js @@ -114,23 +114,6 @@ export function rejectExchangeOrder(data) { }) } -// 拒绝换货申请订单完成 -export function completeExchangeRejectedOrder(data) { - return request({ - url: '/jysystem/order/exchangeRejectedComplete', - method: 'put', - data: data - }) -} - -// 批量将拒绝换货申请订单更新为已完成 -export function completeAllExchangeRejectedOrder() { - return request({ - url: '/jysystem/order/exchangeRejectedCompleteAll', - method: 'put' - }) -} - // 变更订单状态 export function changeOrderStatus(data) { return request({ diff --git a/admin-front/src/views/jysystem/order/index.vue b/admin-front/src/views/jysystem/order/index.vue index 88ef44e..bb11cc0 100644 --- a/admin-front/src/views/jysystem/order/index.vue +++ b/admin-front/src/views/jysystem/order/index.vue @@ -172,15 +172,6 @@ @click="handleQuickFilter('exchangeRejected')" >拒绝换货申请 - - 更新拒绝换货申请为已完成 - @@ -200,17 +191,22 @@ - {{ formatPriceB(scope.row) }} + {{ formatPriceAmount(formatPriceB(scope.row)) }} - {{ formatPriceC(scope.row) }} + {{ formatPriceAmount(formatPriceC(scope.row)) }} + + + + + {{ formatPriceAmount(formatLogisticsFee(scope.row)) }} - {{ formatProgressiveMultifocalPrice(scope.row) }} + {{ formatPriceAmount(formatProgressiveMultifocalPrice(scope.row)) }} @@ -850,21 +846,21 @@ {{ formatPriceAmount(formatPriceTotal(detail, 'priceB')) }} - {{ formatPriceAmount(formatPriceTotal(detail, 'priceB')) }} + >{{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceB')) }} + {{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceB')) }} {{ formatPriceAmount(formatPriceTotal(detail, 'priceC')) }} - {{ formatPriceAmount(formatPriceTotal(detail, 'priceC')) }} + >{{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceC')) }} + {{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceC')) }} @@ -876,26 +872,6 @@ {{ formatPriceAmount(formatLogisticsLogFee(scope.row, detail)) }} - - - - - - - - - - - - - - {{ formatShipDate(scope.row.operateTime) }} @@ -1021,26 +997,6 @@ - - - - - - - - - - - - - - @@ -1124,7 +1080,7 @@ /> 0 && detail.logisticsFee != null) { + if (!hasFee && detail.logisticsFee != null) { const legacyFee = this.parseLogisticsFeeValue(detail.logisticsFee); if (legacyFee != null) return legacyFee; } @@ -1440,24 +1421,6 @@ export default { formatDetailLogisticsFee(detail) { return this.sumDetailLogisticsFee(detail); }, - formatLogSaleSettleStatus(log) { - if (!log || log.expressNo == null || String(log.expressNo).trim() === '') { - return null; - } - if (log.saleSettleStatus != null && log.saleSettleStatus !== '') { - return log.saleSettleStatus; - } - return '0'; - }, - formatLogPurchaseSettleStatus(log) { - if (!log || log.expressNo == null || String(log.expressNo).trim() === '') { - return null; - } - if (log.purchaseSettleStatus != null && log.purchaseSettleStatus !== '') { - return log.purchaseSettleStatus; - } - return '0'; - }, formatShipDate(time) { if (!time) { return '-'; @@ -1730,13 +1693,17 @@ export default { }, canViewLogistics(row) { if (!row || row.orderStatus == null) return false; - const status = Number(row.orderStatus); - return status === Number(this.ORDER_STATUS_SHIPPED) || status === 9; + const status = String(row.orderStatus); + return status === this.ORDER_STATUS_SHIPPED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS + || status === this.ORDER_STATUS_COMPLETED + || status === this.ORDER_STATUS_EXCHANGE_COMPLETED; }, canCompleteOrder(row) { if (!row || row.orderStatus == null) return false; const status = String(row.orderStatus); - return status === this.ORDER_STATUS_SHIPPED || status === this.ORDER_STATUS_EXCHANGE_REJECTED; + return status === this.ORDER_STATUS_SHIPPED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS; }, handleViewLogistics(row) { if (!row || !row.id) return; @@ -1864,28 +1831,13 @@ export default { if (!row || !row.id) { return; } - const isExchangeRejected = String(row.orderStatus) === this.ORDER_STATUS_EXCHANGE_REJECTED; - const confirmMsg = isExchangeRejected - ? `确认将拒绝换货申请订单"${row.orderNo}"标记为已完成吗?` - : `确认完成订单"${row.orderNo}"吗?`; - const requestFn = isExchangeRejected - ? () => completeExchangeRejectedOrder({ orderId: row.id }) - : () => completeOrder({ orderId: row.id }); - this.$modal.confirm(confirmMsg).then(() => { - return requestFn(); + this.$modal.confirm(`确认完成订单"${row.orderNo}"吗?`).then(() => { + return completeOrder({ orderId: row.id }); }).then(() => { this.$modal.msgSuccess('操作成功'); this.getList(); }).catch(() => {}); }, - handleBatchCompleteExchangeRejected() { - this.$modal.confirm('确认将所有拒绝换货申请状态的订单更新为已完成吗?').then(() => { - return completeAllExchangeRejectedOrder(); - }).then((res) => { - this.$modal.msgSuccess((res && res.msg) || '操作成功'); - this.getList(); - }).catch(() => {}); - }, handleAgreeExchange(row) { if (!row || !row.id) { return; diff --git a/back/src/main/java/com/ruoyi/web/util/ExpressQueryUtils.java b/back/src/main/java/com/ruoyi/web/util/ExpressQueryUtils.java index 6eee186..7452a6f 100644 --- a/back/src/main/java/com/ruoyi/web/util/ExpressQueryUtils.java +++ b/back/src/main/java/com/ruoyi/web/util/ExpressQueryUtils.java @@ -55,7 +55,7 @@ public class ExpressQueryUtils { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "APPCODE " + appCode); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.setContentType(MediaType.parseMediaType("application/x-www-form-urlencoded; charset=UTF-8")); MultiValueMap body = new LinkedMultiValueMap<>(); body.add("expressNo", expressNo); @@ -75,21 +75,46 @@ public class ExpressQueryUtils { return result; } catch (HttpStatusCodeException e) { int status = e.getRawStatusCode(); - log.error("调用阿里云物流查询失败 expressNo={} status={}", expressNo, status, e); + String caError = e.getResponseHeaders() != null + ? e.getResponseHeaders().getFirst("X-Ca-Error-Message") : null; + log.warn("调用阿里云物流查询失败 expressNo={} status={} caError={}", expressNo, status, caError); result.put("errorCode", "HTTP_" + status); - if (status == 403) { - result.put("errorMsg", "物流查询服务授权失效(HTTP 403),请在阿里云 API 市场续费快递查询接口并更新 express.ali.app-code"); - } else { + if (status == 403) + { + result.put("errorMsg", buildExpress403Message(caError)); + } + else + { String errorBody = e.getResponseBodyAsString(); result.put("errorMsg", StringUtils.isNotEmpty(errorBody) ? errorBody : ("物流查询请求失败,HTTP状态码:" + status)); } return result; - } catch (Exception e) { + } + catch (Exception e) + { log.error("调用阿里云物流查询失败 expressNo={}", expressNo, e); result.put("errorCode", "EXCEPTION"); result.put("errorMsg", e.getMessage()); return result; } } + + private String buildExpress403Message(String caError) + { + if (StringUtils.isEmpty(caError)) + { + return "物流查询未授权(HTTP 403):请在阿里云 API 市场购买「快递物流查询」接口," + + "并使用该商品对应的 AppCode 配置 express.ali.app-code(不能与实名认证等其它 API 混用)"; + } + if (caError.contains("Quota") || caError.contains("quota") || caError.contains("exhausted")) + { + return "物流查询套餐次数已用完(HTTP 403),请在阿里云 API 市场续费快递查询接口"; + } + if (caError.contains("Unauthorized") || caError.contains("Invalid AppCode") || caError.contains("not exists")) + { + return "物流查询 AppCode 无效或未订阅该 API(HTTP 403),请更新 express.ali.app-code 为快递查询商品的 AppCode"; + } + return "物流查询未授权(HTTP 403):" + caError; + } } diff --git a/developer-front/src/components/DictData/index.js b/developer-front/src/components/DictData/index.js index 7b85d4a..ece270b 100644 --- a/developer-front/src/components/DictData/index.js +++ b/developer-front/src/components/DictData/index.js @@ -3,21 +3,6 @@ import store from '@/store' import DataDict from '@/utils/dict' import { getDicts as getDicts } from '@/api/system/dict/data' -function searchDictByKey(dict, key) { - if (key == null && key == "") { - return null - } - try { - for (let i = 0; i < dict.length; i++) { - if (dict[i].key == key) { - return dict[i].value - } - } - } catch (e) { - return null - } -} - function install() { Vue.use(DataDict, { metas: { @@ -25,19 +10,14 @@ function install() { labelField: 'dictLabel', valueField: 'dictValue', request(dictMeta) { - const storeDict = searchDictByKey(store.getters.dict, dictMeta.type) - if (storeDict) { - return new Promise(resolve => { resolve(storeDict) }) - } else { - return new Promise((resolve, reject) => { - getDicts(dictMeta.type).then(res => { - store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) - resolve(res.data) - }).catch(error => { - reject(error) - }) + return new Promise((resolve, reject) => { + getDicts(dictMeta.type).then(res => { + store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) + resolve(res.data) + }).catch(error => { + reject(error) }) - } + }) }, }, }, diff --git a/developer-front/src/components/DictTag/index.vue b/developer-front/src/components/DictTag/index.vue index 6b5b230..ef09acb 100644 --- a/developer-front/src/components/DictTag/index.vue +++ b/developer-front/src/components/DictTag/index.vue @@ -1,7 +1,7 @@ - + { - if (!this.options.some(v => v.value === item)) { + if (!this.options.some(v => String(v.value) === String(item))) { this.unmatchArray.push(item) unmatch = true // 如果有未匹配项,将标志设置为true } diff --git a/developer-front/src/store/modules/dict.js b/developer-front/src/store/modules/dict.js index 7a1b2f0..3aa6d7c 100644 --- a/developer-front/src/store/modules/dict.js +++ b/developer-front/src/store/modules/dict.js @@ -4,10 +4,15 @@ const state = { const mutations = { SET_DICT: (state, { key, value }) => { if (key !== null && key !== "") { - state.dict.push({ - key: key, - value: value - }) + const index = state.dict.findIndex(item => item.key === key) + if (index >= 0) { + state.dict.splice(index, 1, { key: key, value: value }) + } else { + state.dict.push({ + key: key, + value: value + }) + } } }, REMOVE_DICT: (state, key) => { diff --git a/developer-front/src/views/order/factory-order.vue b/developer-front/src/views/order/factory-order.vue index 780405f..dd3f745 100644 --- a/developer-front/src/views/order/factory-order.vue +++ b/developer-front/src/views/order/factory-order.vue @@ -30,7 +30,16 @@ {{ formatLens(scope.row) }} - + + + {{ formatPriceAmount(formatPriceC(scope.row)) }} + + + + + {{ formatPriceAmount(formatLogisticsFee(scope.row)) }} + + {{ formatProgressiveMultifocalPrice(scope.row) }} @@ -187,11 +196,11 @@ - {{ formatPriceAmount(detail.priceC) }} + {{ formatPriceAmount(formatPriceC(detail)) }} {{ formatPriceAmount(formatDetailLogisticsFee(detail)) }} {{ formatPriceAmount(formatProgressiveMultifocalPrice(detail)) }} - {{ formatPriceAmount(formatPriceTotal(detail, 'priceC')) }} + {{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceC')) }} @@ -203,26 +212,6 @@ {{ formatPriceAmount(formatLogisticsLogFee(scope.row, detail)) }} - - - - - - - - - - - - - - {{ formatShipDate(scope.row.operateTime) }} @@ -311,26 +300,6 @@ - - - - - - - - - - - - - - @@ -574,7 +543,10 @@ export default { ORDER_STATUS_PRODUCING: '7', ORDER_STATUS_SHIPPED: '8', ORDER_STATUS_COMPLETED: '9', + ORDER_STATUS_EXCHANGE_APPLY: '12', ORDER_STATUS_EXCHANGE_AGREED: '13', + ORDER_STATUS_EXCHANGE_LOGISTICS: '15', + ORDER_STATUS_EXCHANGE_COMPLETED: '17', ORDER_STATUS_WITHDRAWN: '20', ORDER_STATUS_SUPPLEMENTED: '19', logisticsDialogVisible: false, @@ -703,8 +675,32 @@ export default { }, formatProgressiveMultifocalPrice(row) { if (!row) return '-' + if (this.isExchangeOrder(row)) return '-' return row.progressiveMultifocalPrice != null ? row.progressiveMultifocalPrice : '-' }, + isExchangeOrder(row) { + if (!row) return false + if (row.orderNo && String(row.orderNo).startsWith('HH')) return true + const status = row.orderStatus != null ? String(row.orderStatus) : '' + return status === this.ORDER_STATUS_EXCHANGE_APPLY || status === this.ORDER_STATUS_EXCHANGE_AGREED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS + || status === this.ORDER_STATUS_EXCHANGE_COMPLETED + }, + formatLogisticsFee(row) { + if (!row) return '-' + if (!this.isExchangeOrder(row)) return '-' + const fee = this.parseLogisticsFeeValue(row.logisticsFee) + return fee != null ? fee : '-' + }, + formatPriceC(row) { + if (!row) return '-' + if (this.isExchangeOrder(row)) return '-' + return row.priceC != null ? row.priceC : '-' + }, + formatDetailPriceTotal(detail, priceKey) { + if (this.isExchangeOrder(detail)) return this.formatDetailLogisticsFee(detail) + return this.formatPriceTotal(detail, priceKey) + }, formatPriceAmount(value) { if (value == null || value === '' || value === '-') return '-' if (value === '未核算') return '未核算' @@ -750,7 +746,7 @@ export default { hasFee = true } }) - if (!hasFee && logs.length > 0 && detail.logisticsFee != null) { + if (!hasFee && detail.logisticsFee != null) { const legacyFee = this.parseLogisticsFeeValue(detail.logisticsFee) if (legacyFee != null) return legacyFee } @@ -760,24 +756,6 @@ export default { formatDetailLogisticsFee(detail) { return this.sumDetailLogisticsFee(detail) }, - formatLogSaleSettleStatus(log) { - if (!log || log.expressNo == null || String(log.expressNo).trim() === '') { - return null - } - if (log.saleSettleStatus != null && log.saleSettleStatus !== '') { - return log.saleSettleStatus - } - return '0' - }, - formatLogPurchaseSettleStatus(log) { - if (!log || log.expressNo == null || String(log.expressNo).trim() === '') { - return null - } - if (log.purchaseSettleStatus != null && log.purchaseSettleStatus !== '') { - return log.purchaseSettleStatus - } - return '0' - }, formatShipDate(time) { if (!time) { return '-' @@ -915,12 +893,17 @@ export default { }, canCompleteOrder(row) { if (!row || row.orderStatus == null) return false - return String(row.orderStatus) === this.ORDER_STATUS_SHIPPED + const status = String(row.orderStatus) + return status === this.ORDER_STATUS_SHIPPED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS }, canViewLogistics(row) { if (!row || row.orderStatus == null) return false - const status = Number(row.orderStatus) - return status === Number(this.ORDER_STATUS_SHIPPED) || status === 9 + const status = String(row.orderStatus) + return status === this.ORDER_STATUS_SHIPPED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS + || status === this.ORDER_STATUS_COMPLETED + || status === this.ORDER_STATUS_EXCHANGE_COMPLETED }, handleViewLogistics(row) { if (!row || !row.id) return diff --git a/developer-front/src/views/order/lens-order.vue b/developer-front/src/views/order/lens-order.vue index 8270fa9..73f3e99 100644 --- a/developer-front/src/views/order/lens-order.vue +++ b/developer-front/src/views/order/lens-order.vue @@ -73,6 +73,11 @@ {{ formatPriceB(scope.row) }} + + + {{ formatPriceAmount(formatLogisticsFee(scope.row)) }} + + {{ formatPriceAmount(formatPriceTotal(detail, 'priceB')) }} - {{ formatPriceAmount(formatPriceTotal(detail, 'priceB')) }} + >{{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceB')) }} + {{ formatPriceAmount(formatDetailPriceTotal(detail, 'priceB')) }} @@ -688,26 +693,6 @@ {{ formatPriceAmount(formatLogisticsLogFee(scope.row, detail)) }} - - - - - - - - - - - - - - {{ formatShipDate(scope.row.operateTime) }} @@ -796,26 +781,6 @@ - - - - - - - - - - - - - - @@ -890,7 +855,7 @@ 01 换货申请说明 - 填写换货申请原因,订单将进入换货申请状态 + 填写换货申请原因,系统将复制当前订单生成新换货申请单,原订单状态不变 @@ -1053,6 +1018,9 @@ export default { ORDER_STATUS_SHIPPED: '8', ORDER_STATUS_COMPLETED: '9', ORDER_STATUS_EXCHANGE_APPLY: '12', + ORDER_STATUS_EXCHANGE_AGREED: '13', + ORDER_STATUS_EXCHANGE_LOGISTICS: '15', + ORDER_STATUS_EXCHANGE_COMPLETED: '17', ORDER_STATUS_EXCHANGE_REJECTED: '21', logisticsDialogVisible: false, logisticsBasic: null, @@ -1162,7 +1130,7 @@ export default { }, exchangeApplyDialogSubtitle() { if (this.exchangeApplyForm && this.exchangeApplyForm.orderNo) { - return `订单编号 ${this.exchangeApplyForm.orderNo} · 填写原因后提交换货申请` + return `订单编号 ${this.exchangeApplyForm.orderNo} · 提交后将生成 HH 前缀的新换货申请单` } return '填写原因后提交换货申请' }, @@ -1315,14 +1283,35 @@ export default { const status = String(row.orderStatus) return status === this.ORDER_STATUS_DRAFT || status === this.ORDER_STATUS_REJECTED }, + isExchangeOrder(row) { + if (!row) return false + if (row.orderNo && String(row.orderNo).startsWith('HH')) return true + const status = row.orderStatus != null ? String(row.orderStatus) : '' + return status === this.ORDER_STATUS_EXCHANGE_APPLY + || status === this.ORDER_STATUS_EXCHANGE_AGREED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS + || status === this.ORDER_STATUS_EXCHANGE_COMPLETED + }, + formatDetailPriceTotal(detail, priceKey) { + if (this.isExchangeOrder(detail)) return this.formatDetailLogisticsFee(detail) + return this.formatPriceTotal(detail, priceKey) + }, + formatLogisticsFee(row) { + if (!row) return '-' + if (!this.isExchangeOrder(row)) return '-' + const fee = this.parseLogisticsFeeValue(row.logisticsFee) + return fee != null ? fee : '-' + }, formatPriceB(row) { if (!row) return '-' + if (this.isExchangeOrder(row)) return '-' if (this.isUnsetPriceStatus(row)) return '-' if (String(row.orderStatus) === this.ORDER_STATUS_SUBMIT) return '未核算' return row.priceB != null ? row.priceB : '-' }, formatProgressiveMultifocalPrice(row) { if (!row) return '-' + if (this.isExchangeOrder(row)) return '-' if (Number(row.progressiveMultifocal) !== 1) return '-' if (this.isUnsetPriceStatus(row)) return '-' if (String(row.orderStatus) === this.ORDER_STATUS_SUBMIT) return '未核算' @@ -1373,7 +1362,7 @@ export default { hasFee = true } }) - if (!hasFee && logs.length > 0 && detail.logisticsFee != null) { + if (!hasFee && detail.logisticsFee != null) { const legacyFee = this.parseLogisticsFeeValue(detail.logisticsFee) if (legacyFee != null) return legacyFee } @@ -1383,24 +1372,6 @@ export default { formatDetailLogisticsFee(detail) { return this.sumDetailLogisticsFee(detail) }, - formatLogSaleSettleStatus(log) { - if (!log || log.expressNo == null || String(log.expressNo).trim() === '') { - return null - } - if (log.saleSettleStatus != null && log.saleSettleStatus !== '') { - return log.saleSettleStatus - } - return '0' - }, - formatLogPurchaseSettleStatus(log) { - if (!log || log.expressNo == null || String(log.expressNo).trim() === '') { - return null - } - if (log.purchaseSettleStatus != null && log.purchaseSettleStatus !== '') { - return log.purchaseSettleStatus - } - return '0' - }, formatShipDate(time) { if (!time) { return '-' @@ -1932,17 +1903,24 @@ export default { }, canViewLogistics(row) { if (!row || row.orderStatus == null) return false - const status = Number(row.orderStatus) - return status === Number(this.ORDER_STATUS_SHIPPED) || status === 9 + const status = String(row.orderStatus) + return status === this.ORDER_STATUS_SHIPPED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS + || status === this.ORDER_STATUS_COMPLETED + || status === this.ORDER_STATUS_EXCHANGE_COMPLETED }, canCompleteOrder(row) { if (!row || row.orderStatus == null) return false - return String(row.orderStatus) === this.ORDER_STATUS_SHIPPED + const status = String(row.orderStatus) + return status === this.ORDER_STATUS_SHIPPED + || status === this.ORDER_STATUS_EXCHANGE_LOGISTICS }, canExchangeApplyOrder(row) { if (!row || row.orderStatus == null) return false const status = String(row.orderStatus) - return status === this.ORDER_STATUS_COMPLETED || status === this.ORDER_STATUS_EXCHANGE_REJECTED + return status === this.ORDER_STATUS_COMPLETED + || status === this.ORDER_STATUS_EXCHANGE_COMPLETED + || status === this.ORDER_STATUS_EXCHANGE_REJECTED }, canReceiveOrder(row) { if (!row || row.orderStatus == null) return false @@ -2037,7 +2015,7 @@ export default { }, handleExchangeApply(row) { if (!row || !row.id || !this.canExchangeApplyOrder(row)) { - this.$message.warning('仅已完成或拒绝换货申请状态订单可申请换货') + this.$message.warning('仅已完成、换货完成或拒绝换货申请状态订单可申请换货') return } this.exchangeApplyForm = { @@ -2061,8 +2039,10 @@ export default { exchangeApplyPortalOrder({ orderId: this.exchangeApplyForm.orderId, reason: this.exchangeApplyForm.reason - }).then(() => { - this.$modal.msgSuccess('换货申请已提交') + }).then((res) => { + const newOrder = res && res.data + const newOrderNo = newOrder && newOrder.orderNo ? newOrder.orderNo : '' + this.$modal.msgSuccess(newOrderNo ? `换货申请已提交,新订单号:${newOrderNo}` : '换货申请已提交') this.exchangeApplyOpen = false this.getList() if (this.detailOpen && this.detail.id === this.exchangeApplyForm.orderId) { diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/config/SmsProperties.java b/jy-system/src/main/java/com/ruoyi/jysystem/config/SmsProperties.java index 0f10b98..4433778 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/config/SmsProperties.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/config/SmsProperties.java @@ -16,7 +16,7 @@ public class SmsProperties /** 配片订单分配至镜片厂(模板变量 code=订单号) */ private SceneConfig assignOrder = new SceneConfig(); - /** 配片订单发货通知(模板变量 code、expressCompany、expressNo) */ + /** 配片订单发货通知(模板变量 code、expressCompany) */ private SceneConfig shipOrder = new SceneConfig(); public String getSignName() diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderController.java b/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderController.java index ef46253..d790ed8 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderController.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderController.java @@ -199,32 +199,6 @@ public class JySysOrderController extends BaseController rejectDTO.getOrderId(), rejectDTO.getReason().trim(), getUsername())); } - @PreAuthorize("@ss.hasPermi('jysystem:order:edit')") - @Log(title = "拒绝换货申请订单完成", businessType = BusinessType.UPDATE) - @PutMapping("/exchangeRejectedComplete") - public AjaxResult exchangeRejectedComplete(@RequestBody OrderCloseDTO completeDTO) - { - if (completeDTO == null || completeDTO.getOrderId() == null) - { - return error("订单ID不能为空"); - } - return toAjax(jySysOrderService.adminCompleteExchangeRejectedOrder( - completeDTO.getOrderId(), getUsername())); - } - - @PreAuthorize("@ss.hasPermi('jysystem:order:edit')") - @Log(title = "批量完成拒绝换货申请订单", businessType = BusinessType.UPDATE) - @PutMapping("/exchangeRejectedCompleteAll") - public AjaxResult exchangeRejectedCompleteAll() - { - int rows = jySysOrderService.adminCompleteAllExchangeRejectedOrders(getUsername()); - if (rows <= 0) - { - return success("没有需要更新的订单"); - } - return success("已成功更新 " + rows + " 条订单"); - } - @PreAuthorize("@ss.hasPermi('jysystem:order:edit')") @Log(title = "订单状态变更", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderPortalController.java b/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderPortalController.java index 3007fb5..1b00294 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderPortalController.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/controller/JySysOrderPortalController.java @@ -210,7 +210,7 @@ public class JySysOrderPortalController extends BaseController { return error("换货申请原因不能为空"); } - return toAjax(jySysOrderPortalService.exchangeApplyPortalOrder( + return success(jySysOrderPortalService.exchangeApplyPortalOrder( exchangeDTO.getOrderId(), exchangeDTO.getReason().trim())); } diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/domain/JySysOrderStatusLog.java b/jy-system/src/main/java/com/ruoyi/jysystem/domain/JySysOrderStatusLog.java index 7b90ac6..3f4dd67 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/domain/JySysOrderStatusLog.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/domain/JySysOrderStatusLog.java @@ -25,12 +25,6 @@ public class JySysOrderStatusLog private BigDecimal logisticsFee; - /** 应收结算状态(0未结算 1已结算) */ - private String saleSettleStatus; - - /** 应付结算状态(0未结算 1已结算) */ - private String purchaseSettleStatus; - private String remark; private String operator; @@ -98,26 +92,6 @@ public class JySysOrderStatusLog this.logisticsFee = logisticsFee; } - public String getSaleSettleStatus() - { - return saleSettleStatus; - } - - public void setSaleSettleStatus(String saleSettleStatus) - { - this.saleSettleStatus = saleSettleStatus; - } - - public String getPurchaseSettleStatus() - { - return purchaseSettleStatus; - } - - public void setPurchaseSettleStatus(String purchaseSettleStatus) - { - this.purchaseSettleStatus = purchaseSettleStatus; - } - public String getRemark() { return remark; @@ -158,8 +132,6 @@ public class JySysOrderStatusLog .append("expressCompany", getExpressCompany()) .append("expressNo", getExpressNo()) .append("logisticsFee", getLogisticsFee()) - .append("saleSettleStatus", getSaleSettleStatus()) - .append("purchaseSettleStatus", getPurchaseSettleStatus()) .append("remark", getRemark()) .append("operator", getOperator()) .append("operateTime", getOperateTime()) diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderMapper.java b/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderMapper.java index 090d80e..398fd99 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderMapper.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderMapper.java @@ -28,6 +28,8 @@ public interface JySysOrderMapper extends BaseMapper int countByTenantId(@Param("tenantId") Long tenantId); + int countByOrderNo(@Param("orderNo") String orderNo); + List selectCompletedOrdersByYearMonth(@Param("settleYearMonth") String settleYearMonth); int updatePurchaseSettleStatusByOrderIds(@Param("orderIds") List orderIds, diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderStatusLogMapper.java b/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderStatusLogMapper.java index 3d0c9c3..33d13a4 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderStatusLogMapper.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/mapper/JySysOrderStatusLogMapper.java @@ -17,10 +17,4 @@ public interface JySysOrderStatusLogMapper List selectUnsettledShipLogsByOrderIdAndType(@Param("orderId") Long orderId, @Param("settlementType") String settlementType); - - int updateSaleSettleStatusByIds(@Param("ids") List ids, @Param("settleStatus") String settleStatus); - - int updatePurchaseSettleStatusByIds(@Param("ids") List ids, @Param("settleStatus") String settleStatus); - - int resetShipLogSettleStatusByOrderIds(@Param("orderIds") List orderIds); } diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderPortalService.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderPortalService.java index b934cb2..128e470 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderPortalService.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderPortalService.java @@ -46,7 +46,7 @@ public interface IJySysOrderPortalService int completePortalOrder(Long orderId); - int exchangeApplyPortalOrder(Long orderId, String reason); + JySysOrder exchangeApplyPortalOrder(Long orderId, String reason); int receivePortalOrder(Long orderId); diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderService.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderService.java index c7d7e11..d3bcda6 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderService.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/IJySysOrderService.java @@ -52,7 +52,7 @@ public interface IJySysOrderService extends IService int brandReceiveExchangeRejectedOrder(Long orderId, Long brandTenantId, String operator); - int brandExchangeApplyOrder(Long orderId, Long brandTenantId, String reason, String operator); + JySysOrder brandExchangeApplyOrder(Long orderId, Long brandTenantId, String reason, String operator); int adminRejectOrder(Long orderId, String reason, String operator); @@ -64,10 +64,6 @@ public interface IJySysOrderService extends IService int adminRejectExchangeOrder(Long orderId, String reason, String operator); - int adminCompleteExchangeRejectedOrder(Long orderId, String operator); - - int adminCompleteAllExchangeRejectedOrders(String operator); - int brandResubmitOrder(Long orderId, Long brandTenantId, String reason, String operator); int changeOrderStatus(Long orderId, String orderStatus, String operator); diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/SmsNotificationService.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/SmsNotificationService.java index 32898d7..02f5382 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/SmsNotificationService.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/SmsNotificationService.java @@ -19,7 +19,6 @@ public interface SmsNotificationService * @param phone 手机号(品牌方租户手机号,或收货人手机号) * @param orderNo 订单号,对应模板变量 code * @param expressCompany 快递公司,对应模板变量 expressCompany - * @param expressNo 快递单号,对应模板变量 expressNo */ - void trySendOrderShippedNotify(String phone, String orderNo, String expressCompany, String expressNo); + void trySendOrderShippedNotify(String phone, String orderNo, String expressCompany); } diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysFeeSettlementServiceImpl.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysFeeSettlementServiceImpl.java index c46c2cd..824bcc8 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysFeeSettlementServiceImpl.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysFeeSettlementServiceImpl.java @@ -37,6 +37,14 @@ import com.ruoyi.jysystem.vo.FeeSettlementDetailVO; @Service public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService { + private static final String ORDER_STATUS_EXCHANGE_APPLY = "12"; + + private static final String ORDER_STATUS_EXCHANGE_AGREED = "13"; + + private static final String ORDER_STATUS_EXCHANGE_LOGISTICS = "15"; + + private static final String ORDER_STATUS_EXCHANGE_COMPLETED = "17"; + @Resource private JySysFeeSettlementMapper feeSettlementMapper; @@ -130,10 +138,6 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService { throw new ServiceException("该年月没有已完成状态的订单,无法生成结算单"); } - if (forceRegenerate && exists) - { - resetShipLogSettleStatusForOrders(orders); - } Map> brandGroups = new LinkedHashMap<>(); Map> factoryGroups = new LinkedHashMap<>(); @@ -210,27 +214,9 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService update.setUpdateTime(DateUtils.getNowDate()); int rows = feeSettlementMapper.updateSettleStatus(update); updateOrderSettleStatusBySettlement(settlement, operator); - updateStatusLogSettleStatusBySettlement(settlement); return rows; } - private void updateStatusLogSettleStatusBySettlement(JySysFeeSettlement settlement) - { - List statusLogIds = collectStatusLogIdsBySettlement(settlement.getId()); - if (statusLogIds.isEmpty()) - { - return; - } - if (JySysFeeSettlement.TYPE_AP.equals(settlement.getSettlementType())) - { - jySysOrderStatusLogMapper.updatePurchaseSettleStatusByIds(statusLogIds, "1"); - } - else if (JySysFeeSettlement.TYPE_AR.equals(settlement.getSettlementType())) - { - jySysOrderStatusLogMapper.updateSaleSettleStatusByIds(statusLogIds, "1"); - } - } - private void updateOrderSettleStatusBySettlement(JySysFeeSettlement settlement, String operator) { List items = feeSettlementItemMapper.selectBySettlementId(settlement.getId()); @@ -314,10 +300,13 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService private JySysFeeSettlementItem buildSettlementItem(Long settlementId, String type, JySysOrder order) { - BigDecimal lensPrice = JySysFeeSettlement.TYPE_AR.equals(type) - ? defaultAmount(order.getPriceC()) : defaultAmount(order.getPriceB()); - BigDecimal progressivePrice = Integer.valueOf(1).equals(order.getProgressiveMultifocal()) - ? defaultAmount(order.getProgressiveMultifocalPrice()) : BigDecimal.ZERO; + boolean exchangeOrder = isExchangeOrder(order); + BigDecimal lensPrice = exchangeOrder ? BigDecimal.ZERO + : (JySysFeeSettlement.TYPE_AR.equals(type) + ? defaultAmount(order.getPriceC()) : defaultAmount(order.getPriceB())); + BigDecimal progressivePrice = exchangeOrder ? BigDecimal.ZERO + : (Integer.valueOf(1).equals(order.getProgressiveMultifocal()) + ? defaultAmount(order.getProgressiveMultifocalPrice()) : BigDecimal.ZERO); List shipLogs = jySysOrderStatusLogMapper .selectUnsettledShipLogsByOrderIdAndType(order.getId(), type); @@ -374,7 +363,6 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService { continue; } - revertLogSettleStatusBySettlement(settlement); if ("1".equals(settlement.getSettleStatus())) { revertOrderSettleStatusBySettlement(settlement); @@ -392,24 +380,6 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService } } - /** 删除结算单时回滚关联发货日志的结算状态,便于重新生成时再次纳入物流费用 */ - private void revertLogSettleStatusBySettlement(JySysFeeSettlement settlement) - { - List statusLogIds = collectStatusLogIdsBySettlement(settlement.getId()); - if (statusLogIds.isEmpty()) - { - return; - } - if (JySysFeeSettlement.TYPE_AP.equals(settlement.getSettlementType())) - { - jySysOrderStatusLogMapper.updatePurchaseSettleStatusByIds(statusLogIds, "0"); - } - else if (JySysFeeSettlement.TYPE_AR.equals(settlement.getSettlementType())) - { - jySysOrderStatusLogMapper.updateSaleSettleStatusByIds(statusLogIds, "0"); - } - } - private void revertOrderSettleStatusBySettlement(JySysFeeSettlement settlement) { List items = feeSettlementItemMapper.selectBySettlementId(settlement.getId()); @@ -433,38 +403,6 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService } } - private void resetShipLogSettleStatusForOrders(List orders) - { - if (orders == null || orders.isEmpty()) - { - return; - } - List orderIds = orders.stream() - .map(JySysOrder::getId) - .filter(orderId -> orderId != null) - .distinct() - .collect(Collectors.toList()); - if (!orderIds.isEmpty()) - { - jySysOrderStatusLogMapper.resetShipLogSettleStatusByOrderIds(orderIds); - } - } - - private List collectStatusLogIdsBySettlement(Long settlementId) - { - List items = feeSettlementItemMapper.selectBySettlementId(settlementId); - if (items == null || items.isEmpty()) - { - return new ArrayList<>(); - } - List itemIds = items.stream().map(JySysFeeSettlementItem::getId).collect(Collectors.toList()); - return feeSettlementLogisticsMapper.selectBySettlementItemIds(itemIds).stream() - .map(JySysFeeSettlementLogistics::getStatusLogId) - .filter(statusLogId -> statusLogId != null) - .distinct() - .collect(Collectors.toList()); - } - private String nextSettlementNo(String type) { String datePart = new SimpleDateFormat("yyyyMMdd").format(new Date()); @@ -496,6 +434,23 @@ public class JySysFeeSettlementServiceImpl implements IJySysFeeSettlementService return value != null ? value : BigDecimal.ZERO; } + private boolean isExchangeOrder(JySysOrder order) + { + if (order == null) + { + return false; + } + if (StringUtils.isNotEmpty(order.getOrderNo()) && order.getOrderNo().startsWith("HH")) + { + return true; + } + String status = order.getOrderStatus(); + return ORDER_STATUS_EXCHANGE_APPLY.equals(status) + || ORDER_STATUS_EXCHANGE_AGREED.equals(status) + || ORDER_STATUS_EXCHANGE_LOGISTICS.equals(status) + || ORDER_STATUS_EXCHANGE_COMPLETED.equals(status); + } + @Override public byte[] exportPdf(Long id) { diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderPortalServiceImpl.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderPortalServiceImpl.java index d60f542..3b14a22 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderPortalServiceImpl.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderPortalServiceImpl.java @@ -229,7 +229,7 @@ public class JySysOrderPortalServiceImpl implements IJySysOrderPortalService } @Override - public int exchangeApplyPortalOrder(Long orderId, String reason) + public JySysOrder exchangeApplyPortalOrder(Long orderId, String reason) { JySysTenant tenant = requireBrandTenant(); return jySysOrderService.brandExchangeApplyOrder( diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderServiceImpl.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderServiceImpl.java index 8f0034c..d9f150d 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderServiceImpl.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysOrderServiceImpl.java @@ -59,6 +59,10 @@ public class JySysOrderServiceImpl extends ServiceImpl orderList = jySysOrderMapper.selectJySysOrderList(query); - if (orderList == null || orderList.isEmpty()) - { - return 0; - } - int count = 0; - for (JySysOrder order : orderList) - { - completeExchangeRejectedToCompleted(order.getId(), operator); - count++; - } - return count; - } - @Override @Transactional(rollbackFor = Exception.class) public int brandResubmitOrder(Long orderId, Long brandTenantId, String reason, String operator) @@ -801,9 +772,10 @@ public class JySysOrderServiceImpl extends ServiceImpl logs = jySysOrderStatusLogMapper.selectJySysOrderStatusLogByOrderId(orderId); + if (logs == null || logs.isEmpty()) + { + return false; + } + for (JySysOrderStatusLog log : logs) + { + if (log != null && ORDER_STATUS_EXCHANGE_APPLY.equals(log.getOrderStatus())) + { + return true; + } + } + return false; + } + private void saveOptometryList(JySysOrder jySysOrder) { if (jySysOrder.getId() == null) @@ -1200,12 +1180,6 @@ public class JySysOrderServiceImpl extends ServiceImpl copyOptometryList(List sourceList) + { + List copiedList = new ArrayList<>(); + if (sourceList == null || sourceList.isEmpty()) + { + return copiedList; + } + for (JySysOrderOptometry source : sourceList) + { + if (source == null || StringUtils.isEmpty(source.getEyeSide())) + { + continue; + } + JySysOrderOptometry copy = new JySysOrderOptometry(); + copy.setEyeSide(source.getEyeSide()); + copy.setSphereS(source.getSphereS()); + copy.setCylinderC(source.getCylinderC()); + copy.setAxisA(source.getAxisA()); + copy.setPd(source.getPd()); + copy.setDualPd(source.getDualPd()); + copy.setPdType(source.getPdType()); + copy.setPupilHeight(source.getPupilHeight()); + copy.setDistanceVa(source.getDistanceVa()); + copy.setNearAdd(source.getNearAdd()); + copiedList.add(copy); + } + return copiedList; + } + + private String buildExchangeOrderNo(String sourceOrderNo) + { + String numericPart = StringUtils.isEmpty(sourceOrderNo) + ? new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + + ThreadLocalRandom.current().nextInt(1000, 10000) + : sourceOrderNo.replaceAll("\\D", ""); + if (StringUtils.isEmpty(numericPart)) + { + numericPart = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + + ThreadLocalRandom.current().nextInt(1000, 10000); + } + String orderNo = "HH" + numericPart; + int retry = 0; + while (jySysOrderMapper.countByOrderNo(orderNo) > 0 && retry < 10) + { + orderNo = "HH" + numericPart + ThreadLocalRandom.current().nextInt(1000, 10000); + retry++; + } + if (jySysOrderMapper.countByOrderNo(orderNo) > 0) + { + throw new ServiceException("生成换货订单号失败,请稍后重试"); + } + return orderNo; + } } diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysTenantMessageServiceImpl.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysTenantMessageServiceImpl.java index 88b300b..23785af 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysTenantMessageServiceImpl.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/JySysTenantMessageServiceImpl.java @@ -2,6 +2,8 @@ package com.ruoyi.jysystem.service.impl; import java.util.List; import javax.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; @@ -23,12 +25,16 @@ import com.ruoyi.jysystem.utils.TenantTypeHelper; @Service public class JySysTenantMessageServiceImpl implements IJySysTenantMessageService { + private static final Logger log = LoggerFactory.getLogger(JySysTenantMessageServiceImpl.class); + private static final String ORDER_STATUS_DRAFT = "1"; private static final String ORDER_STATUS_ASSIGNED = "3"; private static final String ORDER_STATUS_SHIPPED = "8"; + private static final String ORDER_STATUS_EXCHANGE_LOGISTICS = "15"; + @Resource private JySysTenantMessageMapper jySysTenantMessageMapper; @@ -102,18 +108,30 @@ public class JySysTenantMessageServiceImpl implements IJySysTenantMessageService } insertMessage(order.getBrandTenantId(), order.getId(), orderNo, JySysTenantMessage.TYPE_STATUS_CHANGE, "订单状态变更", content, orderStatus); - if (ORDER_STATUS_SHIPPED.equals(orderStatus)) + if (ORDER_STATUS_SHIPPED.equals(orderStatus) + || ORDER_STATUS_EXCHANGE_LOGISTICS.equals(orderStatus)) { - // 模板「您的配片单…」通知配片单所属品牌方;无租户手机号时回退收货人手机号 - String smsPhone = StringUtils.isNotEmpty(brandTenant.getPhone()) - ? brandTenant.getPhone() - : order.getReceiverPhone(); + log.info("[发货短信] 触发检查: orderId={}, orderNo={}, orderStatus={}, expressCompany={}, brandTenantId={}, brandPhone={}, receiverPhone={}", + orderId, orderNo, orderStatus, expressCompany, brandTenant.getId(), brandTenant.getPhone(), order.getReceiverPhone()); + String smsPhone = resolveShipNotifyPhone(brandTenant.getPhone(), order.getReceiverPhone()); if (StringUtils.isNotEmpty(smsPhone)) { - smsNotificationService.trySendOrderShippedNotify(smsPhone, orderNo, expressCompany, expressNo); + log.info("[发货短信] 准备发送: orderNo={}, smsPhone={}, expressCompany={}", orderNo, smsPhone, expressCompany); + smsNotificationService.trySendOrderShippedNotify( + smsPhone, orderNo, expressCompany); + } + else + { + log.warn("[发货短信] 跳过: 无有效手机号, orderNo={}, brandPhone={}, receiverPhone={}", + orderNo, brandTenant.getPhone(), order.getReceiverPhone()); } } } + else + { + log.warn("[发货短信] 跳过: 品牌方租户无效, orderId={}, brandTenantId={}, tenantType={}", + orderId, order.getBrandTenantId(), brandTenant != null ? brandTenant.getTenantType() : null); + } } if (order.getLensFactoryTenantId() != null) @@ -171,4 +189,41 @@ public class JySysTenantMessageServiceImpl implements IJySysTenantMessageService } return tenant; } + + private String resolveShipNotifyPhone(String brandPhone, String receiverPhone) + { + if (isValidMobile(brandPhone)) + { + return normalizeMobile(brandPhone); + } + if (isValidMobile(receiverPhone)) + { + return normalizeMobile(receiverPhone); + } + return null; + } + + private boolean isValidMobile(String phone) + { + return normalizeMobile(phone) != null; + } + + private String normalizeMobile(String phone) + { + if (StringUtils.isEmpty(phone)) + { + return null; + } + String digits = phone.replaceAll("\\D", ""); + if (digits.length() >= 11) + { + String mobile = digits.substring(digits.length() - 11); + if (mobile.matches("^1[3-9]\\d{9}$")) + { + return mobile; + } + } + String trimmed = phone.trim(); + return trimmed.matches("^1[3-9]\\d{9}$") ? trimmed : null; + } } diff --git a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/SmsNotificationServiceImpl.java b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/SmsNotificationServiceImpl.java index 74dbb1a..ef7c323 100644 --- a/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/SmsNotificationServiceImpl.java +++ b/jy-system/src/main/java/com/ruoyi/jysystem/service/impl/SmsNotificationServiceImpl.java @@ -35,56 +35,67 @@ public class SmsNotificationServiceImpl implements SmsNotificationService } @Override - public void trySendOrderShippedNotify(String phone, String orderNo, String expressCompany, String expressNo) + public void trySendOrderShippedNotify(String phone, String orderNo, String expressCompany) { - Map params = new HashMap<>(3); + Map params = new HashMap<>(2); params.put("code", nullToEmpty(orderNo)); params.put("expressCompany", nullToEmpty(expressCompany)); - params.put("expressNo", nullToEmpty(expressNo)); trySendScene("配片订单发货", smsProperties.getShipOrder(), phone, params); } private void trySendScene(String sceneLabel, SmsProperties.SceneConfig scene, String phone, Map templateParams) { - if (scene == null || !scene.isEnabled()) + if (scene == null) { + log.warn("[发货短信] 跳过: {}场景配置为空", sceneLabel); + return; + } + if (!scene.isEnabled()) + { + log.warn("[发货短信] 跳过: {}短信未启用, enabled=false", sceneLabel); return; } if (StringUtils.isEmpty(phone)) { + log.warn("[发货短信] 跳过: {}手机号为空", sceneLabel); return; } String templateCode = StringUtils.isNotEmpty(scene.getTemplate()) ? scene.getTemplate().trim() : null; if (StringUtils.isEmpty(templateCode)) { - log.warn("未配置{}短信模板,请在 application.yml 的 sms.{} 中填写 template", + log.warn("[发货短信] 跳过: 未配置{}短信模板, 请在 application.yml 的 sms.{} 中填写 template", sceneLabel, sceneLabel.contains("分配") ? "assign-order" : "ship-order"); return; } - String mobile = phone.trim(); - if (!MOBILE_PATTERN.matcher(mobile).matches()) + String mobile = normalizeMobile(phone); + if (mobile == null) { - log.warn("{}短信手机号格式无效,跳过通知: {}", sceneLabel, phone); + log.warn("[发货短信] 跳过: {}手机号格式无效, rawPhone={}", sceneLabel, phone); return; } + String signName = smsProperties.getSignName(); + String templateParam = JSON.toJSONString(templateParams); + log.info("[发货短信] 调用阿里云: scene={}, phone={}, signName={}, template={}, params={}", + sceneLabel, mobile, signName, templateCode, templateParam); try { - String templateParam = JSON.toJSONString(templateParams); - Map result = SmsUtils.sendNotifyMsg(mobile, smsProperties.getSignName(), - templateCode, templateParam); + Map result = SmsUtils.sendNotifyMsg(mobile, signName, templateCode, templateParam); Integer statusCode = (Integer) result.get("statusCode"); String bodyCode = (String) result.get("bodyCode"); + String bodyMessage = (String) result.get("bodyMessage"); + String bizId = (String) result.get("bizId"); + String requestId = (String) result.get("requestId"); if (statusCode == null || statusCode != 200 || !"OK".equalsIgnoreCase(bodyCode)) { - log.warn("{}短信发送失败: phone={}, template={}, params={}, statusCode={}, bodyCode={}", - sceneLabel, mobile, templateCode, templateParam, statusCode, bodyCode); + log.warn("[发货短信] 发送失败: scene={}, phone={}, template={}, params={}, statusCode={}, bodyCode={}, bodyMessage={}, bizId={}, requestId={}", + sceneLabel, mobile, templateCode, templateParam, statusCode, bodyCode, bodyMessage, bizId, requestId); return; } - log.info("{}短信已发送: {}", sceneLabel, mobile); + log.info("[发货短信] 发送成功: scene={}, phone={}, bizId={}, requestId={}", sceneLabel, mobile, bizId, requestId); } catch (Exception e) { - log.warn("{}短信发送异常: phone={}, err={}", sceneLabel, mobile, e.getMessage()); + log.warn("[发货短信] 发送异常: scene={}, phone={}, err={}", sceneLabel, mobile, e.getMessage(), e); } } @@ -92,4 +103,22 @@ public class SmsNotificationServiceImpl implements SmsNotificationService { return value != null ? value : ""; } + + private String normalizeMobile(String phone) + { + if (StringUtils.isEmpty(phone)) + { + return null; + } + String digits = phone.replaceAll("\\D", ""); + if (digits.length() >= 11) + { + String mobile = digits.substring(digits.length() - 11); + if (MOBILE_PATTERN.matcher(mobile).matches()) + { + return mobile; + } + } + return MOBILE_PATTERN.matcher(phone.trim()).matches() ? phone.trim() : null; + } } diff --git a/jy-system/src/main/resources/mapper/jysystem/JySysOrderMapper.xml b/jy-system/src/main/resources/mapper/jysystem/JySysOrderMapper.xml index 93de31a..2932bff 100644 --- a/jy-system/src/main/resources/mapper/jysystem/JySysOrderMapper.xml +++ b/jy-system/src/main/resources/mapper/jysystem/JySysOrderMapper.xml @@ -185,6 +185,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and (brand_tenant_id = #{tenantId} or lens_factory_tenant_id = #{tenantId}) + + select count(1) + from jy_sys_order + where del_flag = '0' + and order_no = #{orderNo} + + select o.id, o.order_no, o.brand_tenant_id, bt.name as brand_tenant_name, o.lens_factory_tenant_id, lf.name as lens_factory_tenant_name, @@ -197,11 +204,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" left join jy_sys_tenant bt on o.brand_tenant_id = bt.id left join jy_sys_tenant lf on o.lens_factory_tenant_id = lf.id where o.del_flag = '0' - and o.order_status = '9' + and o.order_status in ('9', '17') and exists ( select 1 from jy_sys_order_status_log sl where sl.order_id = o.id - and sl.order_status = '9' + and sl.order_status in ('9', '17') and DATE_FORMAT(sl.operate_time, '%Y-%m') = #{settleYearMonth} ) order by o.id asc diff --git a/jy-system/src/main/resources/mapper/jysystem/JySysOrderStatusLogMapper.xml b/jy-system/src/main/resources/mapper/jysystem/JySysOrderStatusLogMapper.xml index 9af5f29..7396851 100644 --- a/jy-system/src/main/resources/mapper/jysystem/JySysOrderStatusLogMapper.xml +++ b/jy-system/src/main/resources/mapper/jysystem/JySysOrderStatusLogMapper.xml @@ -11,8 +11,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - @@ -20,7 +18,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" select id, order_id, order_status, express_company, express_no, logistics_fee, - sale_settle_status, purchase_settle_status, remark, operator, operate_time + remark, operator, operate_time from jy_sys_order_status_log where order_id = #{orderId} order by operate_time desc, id desc @@ -43,8 +41,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" express_company, express_no, logistics_fee, - sale_settle_status, - purchase_settle_status, remark, operator, operate_time, @@ -55,8 +51,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{expressCompany}, #{expressNo}, #{logisticsFee}, - #{saleSettleStatus}, - #{purchaseSettleStatus}, #{remark}, #{operator}, #{operateTime}, @@ -64,52 +58,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select id, order_id, order_status, express_company, express_no, logistics_fee, - sale_settle_status, purchase_settle_status, remark, operator, operate_time - from jy_sys_order_status_log - where order_id = #{orderId} - and order_status = '8' - and express_no is not null - and TRIM(express_no) != '' - - - and (sale_settle_status is null or sale_settle_status = '0') - - - and (purchase_settle_status is null or purchase_settle_status = '0') - - - order by operate_time asc, id asc + select l.id, l.order_id, l.order_status, l.express_company, l.express_no, l.logistics_fee, + l.remark, l.operator, l.operate_time + from jy_sys_order_status_log l + where l.order_id = #{orderId} + and l.order_status in ('8', '15') + and l.express_no is not null + and TRIM(l.express_no) != '' + and l.id not in ( + select fl.status_log_id + from jy_sys_fee_settlement_logistics fl + inner join jy_sys_fee_settlement_item fi on fl.settlement_item_id = fi.id + inner join jy_sys_fee_settlement fs on fi.settlement_id = fs.id + where fl.status_log_id is not null + and fs.settlement_type = #{settlementType} + ) + order by l.operate_time asc, l.id asc - - - update jy_sys_order_status_log - set sale_settle_status = #{settleStatus} - where id in - - #{id} - - - - - update jy_sys_order_status_log - set purchase_settle_status = #{settleStatus} - where id in - - #{id} - - - - - update jy_sys_order_status_log - set sale_settle_status = '0', - purchase_settle_status = '0' - where order_id in - - #{orderId} - - and order_status = '8' - and express_no is not null - and TRIM(express_no) != '' - diff --git a/jy-system/src/main/resources/sql/jy_sys_order_dict.sql b/jy-system/src/main/resources/sql/jy_sys_order_dict.sql index d53d8cd..f817851 100644 --- a/jy-system/src/main/resources/sql/jy_sys_order_dict.sql +++ b/jy-system/src/main/resources/sql/jy_sys_order_dict.sql @@ -51,7 +51,7 @@ INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value SELECT 166, 14, '退货物流', '14', 'jy_order_status', NULL, 'primary', 'N', '0', 'admin', NOW(), NULL FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `dict_type` = 'jy_order_status' AND `dict_value` = '14'); INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `remark`) -SELECT 167, 15, '换货已发货', '15', 'jy_order_status', NULL, 'primary', 'N', '0', 'admin', NOW(), NULL +SELECT 167, 15, '换货物流', '15', 'jy_order_status', NULL, 'primary', 'N', '0', 'admin', NOW(), NULL FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `dict_type` = 'jy_order_status' AND `dict_value` = '15'); INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `remark`) SELECT 168, 16, '退货完成', '16', 'jy_order_status', NULL, 'success', 'N', '0', 'admin', NOW(), NULL diff --git a/jy-system/src/main/resources/sql/jy_sys_order_restore_exchange_status_labels.sql b/jy-system/src/main/resources/sql/jy_sys_order_restore_exchange_status_labels.sql new file mode 100644 index 0000000..6f284fd --- /dev/null +++ b/jy-system/src/main/resources/sql/jy_sys_order_restore_exchange_status_labels.sql @@ -0,0 +1,16 @@ +-- 订单状态字典:恢复/确保换货物流、换货完成标签 +UPDATE `sys_dict_data` +SET `dict_label` = '换货物流' +WHERE `dict_type` = 'jy_order_status' AND `dict_value` = '15'; + +UPDATE `sys_dict_data` +SET `dict_label` = '换货完成' +WHERE `dict_type` = 'jy_order_status' AND `dict_value` = '17'; + +INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `remark`) +SELECT 167, 15, '换货物流', '15', 'jy_order_status', NULL, 'primary', 'N', '0', 'admin', NOW(), NULL +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `dict_type` = 'jy_order_status' AND `dict_value` = '15'); + +INSERT INTO `sys_dict_data` (`dict_code`, `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `remark`) +SELECT 169, 17, '换货完成', '17', 'jy_order_status', NULL, 'success', 'N', '0', 'admin', NOW(), NULL +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `dict_type` = 'jy_order_status' AND `dict_value` = '17'); diff --git a/jy-system/src/main/resources/sql/jy_sys_order_status_log_drop_settle_status.sql b/jy-system/src/main/resources/sql/jy_sys_order_status_log_drop_settle_status.sql new file mode 100644 index 0000000..65e440c --- /dev/null +++ b/jy-system/src/main/resources/sql/jy_sys_order_status_log_drop_settle_status.sql @@ -0,0 +1,4 @@ +-- 订单状态日志:移除物流应收/应付结算状态字段(改由费用结算单物流明细关联发货日志) +ALTER TABLE `jy_sys_order_status_log` + DROP COLUMN `sale_settle_status`, + DROP COLUMN `purchase_settle_status`; diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java index aba8058..22723f0 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SmsUtils.java @@ -3,16 +3,16 @@ package com.ruoyi.common.utils; import com.aliyun.dysmsapi20170525.Client; import com.aliyun.dysmsapi20170525.models.SendSmsRequest; import com.aliyun.dysmsapi20170525.models.SendSmsResponse; -import com.aliyun.tea.*; import com.aliyun.teaopenapi.models.Config; import com.aliyun.teautil.models.RuntimeOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; -import static com.aliyun.teautil.Common.assertAsString; - public class SmsUtils { + private static final Logger log = LoggerFactory.getLogger(SmsUtils.class); public static Client createClient() throws Exception { Config config = new Config() // 配置 AccessKey ID,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 @@ -43,6 +43,8 @@ public class SmsUtils { */ public static Map sendNotifyMsg(String phone, String signName, String templateCode, String templateParam) throws Exception { HashMap sendSmsResponseMap = new HashMap<>(); + log.info("[发货短信] SmsUtils 请求: phone={}, signName={}, templateCode={}, templateParam={}", + phone, signName, templateCode, templateParam); try { Client client = SmsUtils.createClient(); SendSmsRequest sendSmsRequest = new SendSmsRequest() @@ -54,19 +56,26 @@ public class SmsUtils { SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions()); Integer statusCode = sendSmsResponse.getStatusCode(); - String responseCode = sendSmsResponse.getBody().getCode(); + String responseCode = sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getCode() : null; + String responseMessage = sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getMessage() : null; + String bizId = sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getBizId() : null; + String requestId = sendSmsResponse.getBody() != null ? sendSmsResponse.getBody().getRequestId() : null; sendSmsResponseMap.put("statusCode", statusCode); sendSmsResponseMap.put("bodyCode", responseCode); - } catch (TeaException error) { - System.out.println(error.getMessage()); - System.out.println(error.getData().get("Recommend")); - assertAsString(error.message); + sendSmsResponseMap.put("bodyMessage", responseMessage); + sendSmsResponseMap.put("bizId", bizId); + sendSmsResponseMap.put("requestId", requestId); + log.info("[发货短信] SmsUtils 响应: phone={}, statusCode={}, bodyCode={}, bodyMessage={}, bizId={}, requestId={}", + phone, statusCode, responseCode, responseMessage, bizId, requestId); + } catch (com.aliyun.tea.TeaException error) { + log.warn("[发货短信] SmsUtils TeaException: phone={}, code={}, message={}", + phone, error.getCode(), error.getMessage()); + sendSmsResponseMap.put("bodyCode", error.getCode()); + sendSmsResponseMap.put("bodyMessage", error.getMessage()); } catch (Exception _error) { - TeaException error = new TeaException(_error.getMessage(), _error); - System.out.println(error.getMessage()); - System.out.println("诊断地址" + error.getData().get("Recommend")); - assertAsString(error.message); + log.warn("[发货短信] SmsUtils 异常: phone={}, err={}", phone, _error.getMessage(), _error); + sendSmsResponseMap.put("bodyMessage", _error.getMessage()); } return sendSmsResponseMap; }
填写换货申请原因,订单将进入换货申请状态
填写换货申请原因,系统将复制当前订单生成新换货申请单,原订单状态不变