diff --git a/app/base/lib/db/connections.php b/app/base/lib/db/connections.php index 8b580bba..f1853417 100644 --- a/app/base/lib/db/connections.php +++ b/app/base/lib/db/connections.php @@ -290,7 +290,6 @@ class base_db_connections extends base_db_abstract implements base_interface_db ome_branch_product::delRedisBranchFlow(); material_basic_material_stock::delRedisMaterialFlow(); - ome_branch_product::initRedisBranch(); material_basic_material_stock::initRedisMaterialStock(); diff --git a/app/eccommon/region-mainland.txt b/app/eccommon/region-mainland.txt index cf57c930..8186ee3b 100644 --- a/app/eccommon/region-mainland.txt +++ b/app/eccommon/region-mainland.txt @@ -3700,4 +3700,4 @@ "1266,龙沙区": "" } } -} \ No newline at end of file +} diff --git a/app/erpapi/lib/apiname.php b/app/erpapi/lib/apiname.php index 4864faa8..e365cc68 100644 --- a/app/erpapi/lib/apiname.php +++ b/app/erpapi/lib/apiname.php @@ -146,6 +146,10 @@ define('STORE_WAYBILL_ADRESS', 'store.waybill.i.search'); //抖音订购地址 define('STORE_WAYBILL_GET', 'store.waybill.i.get'); //电子面单获取 define('STORE_STANDARD_DY_TEMPLATE', 'store.waybill.template.get'); //抖音获取模板 define('STORE_WAYBILL_PRINTDATA', 'store.waybill.printdata'); //抖音获取打印数据 +// 爱库存等矩阵取号(method 与 STORE_WAYBILL_GET 相同,语义区分便于检索) +define('STORE_WAYBILL_DY_GET', 'store.waybill.i.get'); +// 矩阵生成打印控件签名 params(爱库存 prepare/sign 的 sign 阶段) +define('STORE_API_SIGN_GET', 'store.api.sign.get'); // 小红书电子面单 define('STORE_STANDARD_XHS_TEMPLATE', 'store.waybill.stdtemplates.get'); //小红书获取模板 diff --git a/app/erpapi/lib/logistics/matrix/aikucun/request/electron.php b/app/erpapi/lib/logistics/matrix/aikucun/request/electron.php index 66667b2d..2b69df2b 100644 --- a/app/erpapi/lib/logistics/matrix/aikucun/request/electron.php +++ b/app/erpapi/lib/logistics/matrix/aikucun/request/electron.php @@ -20,7 +20,7 @@ */ class erpapi_logistics_matrix_aikucun_request_electron extends erpapi_logistics_request_electron { - protected $directNum = 10; + protected $directNum = 1; /** * bufferRequest @@ -32,63 +32,976 @@ class erpapi_logistics_matrix_aikucun_request_electron extends erpapi_logistics_ } /** - * 御城河 + * 直连取号:向矩阵申请电子面单物流单号。 * - * @return void - * @author - **/ - private function __hchsafe($sdf) + * 说明: + * - 该方法只负责“取号”,不负责打印数据签名; + * - 返回结果会回填到 waybill 相关链路,供后续打印/补打使用。 + * + * @param array $sdf 发货与面单业务参数 + * @return array|false + */ + public function directRequest($sdf) { - // 御城河-运单直连 - if ($sdf['order_bns']) { - $hchsafe = array( - 'to_node_id' => $this->__configObj->get_to_node_id(), - 'tradeIds' => $sdf['order_bns'], - ); + $this->title = '爱库存-' . $this->__channelObj->channel['logistics_code'] . '获取物流单号'; + $this->timeOut = 20; + $this->primaryBn = $sdf['primary_bn']; - kernel::single('base_hchsafe')->order_push_log($hchsafe); + $sdf['order_bns'] = array_column($sdf['order'], 'order_bn'); + + $prt_tmpl_id = $sdf['dly_corp']['prt_tmpl_id']; + + $templateMdl = app::get('logisticsmanager')->model('express_template'); + $templateInfo = $templateMdl->db_dump(['template_id' => $prt_tmpl_id]); + + $custom_mark = $mark_text = []; + foreach ($sdf['order'] as $k => $v) { + if ($v['custom_mark']) { + $tmp = unserialize($v['custom_mark']); + $custom_mark[] = str_replace(["\t", "\r\n", "\r", "\n", "'", "\"", "\\"], '', $tmp['op_content']); + } + if ($v['mark_text']) { + $tmp = unserialize($v['mark_text']); + $mark_text[] = str_replace(["\t", "\r\n", "\r", "\n", "'", "\"", "\\"], '', $tmp['op_content']); + } } + + $params = []; + $params['cpCode'] = $this->__channelObj->channel['logistics_code']; + $params['version'] = '2.0'; + + $params['sender'] = json_encode([ + 'address' => [ + 'city' => $sdf['shop']['city'], + 'detail' => $sdf['shop']['address_detail'], + 'district' => $sdf['shop']['area'], + 'province' => $sdf['shop']['province'], + 'town' => $sdf['shop']['street'], + ], + 'mobile' => $sdf['shop']['mobile'], + 'name' => $sdf['shop']['default_sender'], + 'phone' => $sdf['shop']['tel'], + ]); + + $serviceCode = json_decode($this->__channelObj->channel['service_code'], 1); + + $product_type = $customer_code = []; + foreach ($serviceCode as $k => $v) { + // waybill 配置里顺丰/京东等使用 productType,与 PRODUCT-TYPE 等价 + if ($k == 'PRODUCT-TYPE' || $k == 'productType') { + $product_type = is_array($v) && isset($v['value']) ? $v['value'] : $v; + continue; + } + if ($k == 'customerCode') { + $customer_code = is_array($v) && isset($v['value']) ? $v['value'] : $v; + continue; + } + } + + $orderInfo = [ + 'orderChannelsType' => kernel::single('wms_event_trigger_logistics_data_electron_aikucun')->orderChannelsType(), + 'tradeOrderList' => is_array($sdf['order_bns']) ? $sdf['order_bns'] : [$sdf['order_bns']], + ]; + $custom_mark && $orderInfo['buyerMemo'] = $custom_mark; + $mark_text && $orderInfo['sellerMemo'] = $mark_text; + + // 爱库存按 packageInfo.id 识别包裹;若复用历史已取消的 packId,会报 + // “单号已取消,更改packId重新取号”。 + // 仅使用 delivery_id + templateId 在“切走再切回同模板”时仍会复用,因此这里增加时间种子, + // 保证每次取号请求的 packId 都唯一。 + // 同时按接口约束控制 packId 长度:小于 12 位(这里固定为 11 位)。 + $templateId = isset($templateInfo['out_template_id']) ? $templateInfo['out_template_id'] : '0'; + $packSeed = $sdf['delivery']['delivery_id'] . '_' . $templateId . '_' . microtime(true); + $packId = substr(md5($packSeed), 0, 11); + + $params['tradeOrderInfoList'] = []; + $params['tradeOrderInfoList'][0] = [ + 'objectId' => $sdf['primary_bn'], + 'orderInfo' => $orderInfo, + 'packageInfo' => [ + 'id' => $packId, + 'items' => [], + 'volume' => 0, + 'weight' => 0, + 'length' => 0, + 'width' => 0, + 'height' => 0, + 'totalPackagesCount' => 0, + 'packagingDescription' => '', + 'goodsDescription' => '', + 'goodValue' => 0, + ], + 'templateId' => $templateInfo['out_template_id'], + ]; + + $params['tradeOrderInfoList'][0]['recipient'] = [ + 'address' => [ + 'city' => $sdf['delivery']['ship_city'], + 'detail' => $sdf['delivery']['ship_addr'], + 'district' => $sdf['delivery']['ship_district'], + 'province' => $sdf['delivery']['ship_province'], + 'town' => '', + ], + 'mobile' => $sdf['delivery']['ship_mobile'], + 'name' => $sdf['delivery']['ship_name'], + 'phone' => $sdf['delivery']['ship_tel'], + ]; + + foreach ($sdf['delivery_item'] as $k => $v) { + $params['tradeOrderInfoList'][0]['packageInfo']['items'][] = [ + 'count' => $v['number'], + 'name' => $v['product_name'], + ]; + } + $params['tradeOrderInfoList'] = json_encode($params['tradeOrderInfoList']); + + if ($customer_code) { + $params['customerCode'] = $customer_code; + } + if ($product_type) { + $params['productCode'] = $product_type; + } + $params['callDoorPickUp'] = 'false'; + $params['sellerName'] = $sdf['shop']['shop_name']; + + $result = $this->requestCall(STORE_WAYBILL_DY_GET, $params, array()); + + $returnResult = $this->backToResult($result, $sdf['delivery']); + + return $returnResult; } - - public function directRequest($sdf){ - //接口升级,平台已弃用该接口。2022-04-18 - $params = array('tid' => $sdf['order_bn']); - - $back = $this->requestCall(STORE_LOGISTICS_JDALPHA_WAYBILL_RECEIVE, $params, array(), $sdf); - return $this->backToResult($back, $sdf['delivery']); - } - - private function backToResult($ret, $delivery){ - $data = empty($ret['data']) ? array() : json_decode($ret['data'], true); - //$data = '{"status": "error", "message": "\u65b0\u589e\u8fd0\u5355\u6b21\u6570\u8d85\u8fc7\u9650\u5236", "code": -1, "data": {}}'; - if(is_array($data['msg'])){ - $waybill = $data['msg']; - }else{ - return $data; + private function backToResult($ret, $delivery) + { + $waybill = empty($ret['data']) ? array() : json_decode($ret['data'], true); + if (empty($waybill) || $ret['rsp'] == 'fail') { + return $ret['msg'] ? $ret['msg'] : false; } $result = array(); - $result[] = array( - 'succ' => $waybill['deliverNo'] ? true : false, - 'msg' => '', - 'delivery_id' => $delivery['delivery_id'], - 'delivery_bn' => $delivery['delivery_bn'], - 'logi_no' => $waybill['deliverNo'], - 'mailno_barcode' => '', - 'qrcode' => '', - 'position' => $waybill['receiverArea'], - 'position_no' => $waybill['sectionCode'], - 'package_wdjc' => '', - 'package_wd' => '', - 'print_config' => '', - 'json_packet' => '', + $logisticsNoInfoList = isset($waybill['data']['logisticsNoInfoList']) && is_array($waybill['data']['logisticsNoInfoList']) + ? $waybill['data']['logisticsNoInfoList'] + : []; + foreach ($logisticsNoInfoList as $val) { + $deliveryBn = isset($val['orderId']) ? trim($val['orderId']) : ''; + + $result[] = array( + 'succ' => !empty($val['logisticsNo']), + 'msg' => '', + 'delivery_id' => $delivery['delivery_id'], + 'delivery_bn' => $deliveryBn, + 'logi_no' => isset($val['logisticsNo']) ? $val['logisticsNo'] : '', + 'mailno_barcode' => '', + 'qrcode' => '', + 'position' => '', + 'position_no' => '', + 'package_wdjc' => '', + 'package_wd' => '', + 'print_config' => '', + 'json_packet' => is_array($val) ? json_encode($val) : $val, + ); + } + $errorInfoList = isset($waybill['data']['errorInfoList']) && is_array($waybill['data']['errorInfoList']) + ? $waybill['data']['errorInfoList'] + : []; + foreach ($errorInfoList as $error) { + $result[] = array( + 'succ' => false, + 'msg' => isset($error['message']) ? $error['message'] : (isset($error['errorMsg']) ? $error['errorMsg'] : ''), + 'delivery_id' => $delivery['delivery_id'], + 'delivery_bn' => isset($error['orderId']) ? $error['orderId'] : $delivery['delivery_bn'], + ); + } + if (empty($result) && ($ret['err_msg'] || $ret['rsp'] == 'fail')) { + $result[] = array( + 'succ' => false, + 'msg' => $ret['err_msg'], + 'delivery_id' => $delivery['delivery_id'], + 'delivery_bn' => $delivery['delivery_bn'], + ); + } + $this->directDataProcess($result); + return $result; + } + + public function recycleWaybill($waybillNumber, $delivery_bn = '') + { + app::get('logisticsmanager')->model('waybill')->update(array('status' => 2, 'create_time' => time()), array('waybill_number' => $waybillNumber)); + + $this->title = '爱库存_' . $this->__channelObj->channel['logistics_code'] . '取消电子面单'; + $this->primaryBn = $waybillNumber; + + $params = array( + 'waybillCode' => $waybillNumber, + 'cpCode' => $this->__channelObj->channel['logistics_code'], + 'version' => '2.0', + ); + + $callback = array( + 'class' => get_class($this), + 'method' => 'callback', + ); + $this->requestCall(STORE_WAYBILL_CANCEL, $params, $callback); + } + + /** + * 获取爱库存打印数据(两阶段): + * - prepare:仅取 printdata(含 mxEctData 等基础数据) + * - sign:基于 prepare_data + print_name 生成最终 params 和 printData + * + * 出库打印 jsondata 传入的 delivery_id 为 sdb_wms_delivery.delivery_id,只查 WMS 发货单,避免与 OME 主键撞号误判。 + * + * @param array $sdf + * @return array + */ + public function getEncryptPrintData($sdf) + { + $deliveryId = isset($sdf['delivery_id']) ? intval($sdf['delivery_id']) : 0; + if ($deliveryId <= 0) { + return array( + 'rsp' => 'fail', + 'msg' => '缺少发货单 delivery_id', + 'err_msg' => '缺少发货单 delivery_id', + ); + } + + $delivery = app::get('wms')->model('delivery')->db_dump($deliveryId, '*'); + if (empty($delivery)) { + return array( + 'rsp' => 'fail', + 'msg' => '发货单不存在', + 'err_msg' => '发货单不存在', + ); + } + + $mode = isset($sdf['mode']) ? trim((string)$sdf['mode']) : ''; + if ($mode === '') { + $mode = 'prepare'; + } + if (!in_array($mode, array('prepare', 'sign'), true)) { + return array( + 'rsp' => 'fail', + 'msg' => '不支持的打印数据模式', + 'err_msg' => '不支持的打印数据模式', + ); + } + + // prepare:只取基础打印数据(不签名),避免页面加载阶段重复调用签名接口。 + if ($mode === 'prepare') { + return $this->getAikucunPrepareData($sdf); + } + + // sign:用户已选打印机后再签名,输出最终给打印控件的 printData + params。 + return $this->getAikucunSignData($sdf, $delivery); + } + + /** + * prepare 阶段:调用 store.waybill.printdata,返回前端可缓存的 prepareData。 + * + * @param array $sdf + * @return array + */ + private function getAikucunPrepareData($sdf) + { + $params = array( + 'waybillCode' => $sdf['logi_no'], + 'cpCode' => $this->__channelObj->channel['logistics_code'], + 'version' => '2.0', + ); + $title = '获取打印数据'; + $result = $this->__caller->call(STORE_WAYBILL_PRINTDATA, $params, array(), $title, 10, $sdf['logi_no']); + if ($result['rsp'] != 'succ' || empty($result['data'])) { + $result['msg'] = isset($result['err_msg']) ? $result['err_msg'] : '获取打印数据失败'; + return $result; + } + + $payload = json_decode($result['data'], true); + if ( + empty($payload) + || !isset($payload['success']) || $payload['success'] !== true + || !isset($payload['code']) || $payload['code'] !== '00000' + ) { + $result['rsp'] = 'fail'; + $result['msg'] = isset($payload['message']) && $payload['message'] ? $payload['message'] : '获取打印数据失败'; + $result['err_msg'] = $result['msg']; + return $result; + } + + $printInfoList = isset($payload['data']['printInfoList']) && is_array($payload['data']['printInfoList']) + ? $payload['data']['printInfoList'] + : array(); + $printInfo = array(); + foreach ($printInfoList as $row) { + if (!empty($sdf['logi_no']) && isset($row['logisticsNo']) && $row['logisticsNo'] == $sdf['logi_no']) { + $printInfo = $row; + break; + } + } + if (empty($printInfo) && !empty($printInfoList[0])) { + $printInfo = $printInfoList[0]; + } + if (empty($printInfo)) { + $result['rsp'] = 'fail'; + $result['msg'] = '未获取到打印数据'; + $result['err_msg'] = $result['msg']; + return $result; + } + + $result['data'] = array( + 'orderId' => isset($printInfo['orderId']) ? $printInfo['orderId'] : '', + 'logisticsNo' => isset($printInfo['logisticsNo']) ? $printInfo['logisticsNo'] : '', + 'prepareData' => $this->buildAikucunPrepareData($sdf['logi_no'], $printInfo), ); return $result; } + /** + * sign 阶段:消费前端回传的 prepare_data,调用 store.api.sign.get 生成控件 params。 + * + * @param array $sdf + * @param array $delivery sdb_wms_delivery 行 + * @return array + */ + private function getAikucunSignData($sdf, $delivery) + { + $prepareData = $this->parseAikucunPrepareData(isset($sdf['prepare_data']) ? $sdf['prepare_data'] : ''); + if (empty($prepareData)) { + return $this->buildAikucunFailResult('缺少预处理打印数据 prepare_data'); + } + if (empty($prepareData['mxEctData'])) { + return $this->buildAikucunFailResult('预处理打印数据缺少 mxEctData'); + } + $logiNo = !empty($prepareData['logisticsNo']) ? $prepareData['logisticsNo'] : (isset($sdf['logi_no']) ? $sdf['logi_no'] : ''); + if (empty($logiNo)) { + return $this->buildAikucunFailResult('缺少运单号 logisticsNo'); + } + $signBody = $this->buildAikucunSignRequestBody( + $delivery, + $logiNo, + $prepareData, + isset($sdf['print_name']) ? trim((string)$sdf['print_name']) : '' + ); + $signTitle = '获取打印控件params'; + $signBodyJson = json_encode($signBody, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $signParams = array( + 'version' => '2.0', + 'api_method' => 'mengxiang.logistics.lews.getPrintInfoPdf', + 'body' => $signBodyJson, + 'query' => '', + ); + $signRet = $this->__caller->call(STORE_API_SIGN_GET, $signParams, array(), $signTitle, 10, $logiNo); + $printParams = $this->parseStoreApiSignGetParams($signRet); + if ($printParams === false) { + $msg = !empty($signRet['err_msg']) ? $signRet['err_msg'] : (!empty($signRet['msg']) ? $signRet['msg'] : '获取打印控件params失败'); + return $this->buildAikucunFailResult($msg); + } + $printParams = $this->normalizeAikucunControlParams($printParams); + if ($printParams === false) { + return $this->buildAikucunFailResult('打印控件params格式异常'); + } + $printData = $signBody; + $printData['esubrc'] = 'SendPdfToPrint'; + $printData['params'] = $printParams; -} \ No newline at end of file + return array( + 'rsp' => 'succ', + 'msg' => '', + 'data' => array( + 'orderId' => isset($prepareData['orderId']) ? $prepareData['orderId'] : '', + 'logisticsNo' => isset($prepareData['logisticsNo']) ? $prepareData['logisticsNo'] : $logiNo, + 'printData' => $printData, + ), + ); + } + + /** + * 构建前端缓存用的 prepareData(最小必要字段)。 + * + * @param string $logiNo + * @param array $printInfo + * @return array + */ + private function buildAikucunPrepareData($logiNo, $printInfo) + { + return array( + 'orderId' => isset($printInfo['orderId']) ? (string)$printInfo['orderId'] : '', + 'logisticsNo' => isset($printInfo['logisticsNo']) ? (string)$printInfo['logisticsNo'] : (string)$logiNo, + 'mxEctData' => isset($printInfo['mxEctData']) ? (string)$printInfo['mxEctData'] : '', + ); + } + + /** + * 解析前端回传的 prepare_data,兼容数组/JSON 字符串两种输入。 + * + * @param array|string $prepareData + * @return array + */ + private function parseAikucunPrepareData($prepareData) + { + if (is_array($prepareData)) { + return $prepareData; + } + if (is_string($prepareData) && $prepareData !== '') { + $decoded = json_decode($prepareData, true); + if (is_array($decoded)) { + return $decoded; + } + } + + return array(); + } + + /** + * 组装 store.api.sign.get 的 body(与打印控件 mengxiang.logistics.lews.getPrintInfoPdf 业务体一致,不含 params) + * + * @param array $delivery sdb_wms_delivery 行(与 getEncryptPrintData 入参一致) + * @param string $logiNo 运单号 + * @param array $printInfo 矩阵 printInfoList 单项 + * @param string $printName 打印机名称(由前端选择后回传,需参与签名) + * @return array + */ + private function buildAikucunSignRequestBody($delivery, $logiNo, $printInfo, $printName = '') + { + $requestId = date('YmdHis') . mt_rand(1000, 9999); + $taskId = 'oms_' . $delivery['delivery_bn'] . '_' . mt_rand(10000, 99999); + + $body = array( + 'logisticsNo' => (string)$logiNo, + 'requestId' => (string)$requestId, + 'taskId' => (string)$taskId, + 'printName' => $printName, + 'mxEctData' => isset($printInfo['mxEctData']) ? (string)$printInfo['mxEctData'] : '', + ); + // PDF:非必填字段为空则不传,避免签名串含空值导致控件验签不一致 + foreach ($body as $k => $v) { + if ($v === '' && !in_array($k, array('esubrc', 'logisticsNo', 'requestId', 'taskId', 'mxEctData'), true)) { + unset($body[$k]); + } + } + + $templateData = $this->loadAikucunTemplateData($delivery); + $templateUrl = $this->resolveAikucunTemplateUrl($templateData); + if ($templateUrl !== '') { + $body['templateUrl'] = $templateUrl; + } + $customData = $this->buildAikucunCustomData($delivery, $printInfo, $templateData); + if (!empty($customData)) { + $body['customData'] = $customData; + } + + $shop = $this->loadShopForAikucunPrint($delivery); + $senderInfo = $this->buildAikucunSenderInfo($shop); + if (!empty($senderInfo)) { + $body['senderInfo'] = $senderInfo; + } + + return $body; + } + + /** + * 解析矩阵 store.api.sign.get 返回中的 params(矩阵常见为 JSON 字符串;解析后为对象时 params 为数组) + * 失败返回 false + * + * @param array $signRet erpapi_caller 返回 + * @return string|array|false + */ + private function parseStoreApiSignGetParams($signRet) + { + if (empty($signRet) || $signRet['rsp'] != 'succ' || !isset($signRet['data']) || $signRet['data'] === '') { + return false; + } + $payload = $signRet['data']; + if (is_string($payload)) { + $payload = json_decode($payload, true); + } + if (!is_array($payload)) { + return false; + } + $p = $this->extractAikucunParamsValue(isset($payload['data']['params']) ? $payload['data']['params'] : null); + if ($p !== false) { + return $p; + } + $p = $this->extractAikucunParamsValue(isset($payload['params']) ? $payload['params'] : null); + if ($p !== false) { + return $p; + } + + return false; + } + + /** + * 梦饷打印控件文档:params 为「公共参数 query 串」(如 appid=...&sign=...&format=json&...)。 + * 矩阵常返回 JSON 对象数组,需转成 query 字符串;**不要用 json_encode**(那会得到 JSON 文本,与文档不一致)。 + * 已是非空字符串时原样返回(兼容矩阵直接返回 query 串)。 + * + * @param string|array $params + * @return string|false + */ + private function normalizeAikucunControlParams($params) + { + if (is_string($params)) { + $params = trim($params); + if ($params === '') { + return false; + } + $tmp = array(); + parse_str($params, $tmp); + if (!is_array($tmp) || empty($tmp)) { + return false; + } + $params = $tmp; + } + if (!is_array($params) || empty($params)) { + return false; + } + $flat = array(); + foreach ($params as $k => $v) { + if (is_scalar($v) || $v === null) { + $flat[$k] = $v; + } + } + if (empty($flat)) { + return false; + } + // 按文档规则:先对参数名做 ASCII 升序,再将 sign 作为 query 末尾参数附加 + $sign = null; + if (array_key_exists('sign', $flat)) { + $sign = $flat['sign']; + unset($flat['sign']); + } + ksort($flat, SORT_STRING); + if ($sign !== null) { + $flat['sign'] = $sign; + } + + return http_build_query($flat, '', '&', PHP_QUERY_RFC3986); + } + + /** + * 解析打印主模板 URL。 + * + * 规则: + * - 标准模板:使用 templateUrl; + * - 自定义模板:主模板改为 parentTemplateUrl(customTemplateUrl 在 customData 里传)。 + * + * @param array $templateData + * @return string + */ + private function resolveAikucunTemplateUrl($templateData) + { + if (!is_array($templateData) || empty($templateData)) { + return ''; + } + // 标准模板 + if (!empty($templateData['templateUrl'])) { + return (string)$templateData['templateUrl']; + } + // 自定义模板 + if (!empty($templateData['parentTemplateUrl'])) { + return (string)$templateData['parentTemplateUrl']; + } + return ''; + } + + /** + * 按发货单当前物流公司加载模板配置(express_template.template_data)。 + * + * @param array $delivery sdb_wms_delivery 行(含 logi_id→dly_corp) + * @return array + */ + private function loadAikucunTemplateData($delivery) + { + $logiId = isset($delivery['logi_id']) ? $delivery['logi_id'] : 0; + if (!$logiId) { + return array(); + } + $corpRows = app::get('ome')->model('dly_corp')->getList( + 'prt_tmpl_id,channel_id', + array('corp_id' => $logiId), + 0, + 1 + ); + if (empty($corpRows) || empty($corpRows[0]['prt_tmpl_id'])) { + return array(); + } + $corp = $corpRows[0]; + if (!empty($corp['channel_id']) && $corp['channel_id'] != $this->__channelObj->channel['channel_id']) { + $prtTmpl = app::get('ome')->model('dly_corp_channel')->db_dump( + array('channel_id' => $this->__channelObj->channel['channel_id'], 'corp_id' => $logiId), + 'prt_tmpl_id' + ); + if ($prtTmpl) { + $corp['prt_tmpl_id'] = $prtTmpl['prt_tmpl_id']; + } + } + $templateObj = app::get('logisticsmanager')->model('express_template'); + $printTplRows = $templateObj->getList('*', array('template_id' => $corp['prt_tmpl_id']), 0, 1); + $printTpl = !empty($printTplRows[0]) ? $printTplRows[0] : array(); + if (empty($printTpl) || empty($printTpl['template_data'])) { + return array(); + } + $templateData = @json_decode($printTpl['template_data'], 1); + return is_array($templateData) ? $templateData : array(); + } + + /** + * 构建自定义模板节点 customData。 + * + * @param array $delivery + * @param array $printInfo + * @param array $templateData + * @return array + */ + private function buildAikucunCustomData($delivery, $printInfo, $templateData) + { + if (!is_array($templateData) || empty($templateData['customTemplateUrl'])) { + return array(); + } + $customBase = $this->buildAikucunCustomBaseData($delivery); + $orderBn = $customBase['orderBn']; + $productInfo = $customBase['productInfo']; + $itemBn = $customBase['itemBn']; + $barcode = $customBase['barcode']; + $valueMap = $this->buildAikucunCustomValueMap($orderBn, $productInfo, $itemBn, $barcode, $delivery); + + $payload = array(); + $customParams = (isset($templateData['customParams']) && is_array($templateData['customParams'])) + ? $templateData['customParams'] + : array(); + + // 关键说明: + // 打印控件在转发时会对 customData.data 的 key 做重排。 + // 若后端签名时 key 顺序与控件转发顺序不一致,会触发 A0002(签名验证失败)。 + // 因此此处使用固定顺序组装 data,并仅保留 customParams 允许的字段。 + $fieldOrder = array( + 'orderId', 'productInfo', 'remark', + 'data1', 'data2', 'data3', 'data4', 'data5', 'data6', + 'customeBarCode', 'merStyleNo', 'styleNo', 'barcode', + ); + $allowMap = $this->buildAikucunCustomAllowMap($customParams); + foreach ($fieldOrder as $field) { + if (!empty($allowMap) && empty($allowMap[$field])) { + continue; + } + if (isset($valueMap[$field]) && $valueMap[$field] !== '') { + $payload[$field] = $valueMap[$field]; + } + } + + // 控件要求 customData.data 不能全空,至少保留一个可用字段。 + if (empty($payload) && (empty($allowMap) || !empty($allowMap['orderId'])) && $orderBn !== '') { + $payload['orderId'] = $orderBn; + } + if (empty($payload)) { + return array(); + } + + return array( + array( + 'customTemplateUrl' => (string)$templateData['customTemplateUrl'], + 'data' => $payload, + ), + ); + } + + /** + * 构建 customData.data 的字段值映射。 + * + * @param string $orderBn + * @param string $productInfo + * @param string $itemBn + * @param string $barcode + * @param array $delivery + * @return array + */ + private function buildAikucunCustomValueMap($orderBn, $productInfo, $itemBn, $barcode, $delivery) + { + $remark = ''; + if (isset($delivery['memo']) && $delivery['memo'] !== '') { + $remark = (string)$delivery['memo']; + } elseif (isset($delivery['remark']) && $delivery['remark'] !== '') { + $remark = (string)$delivery['remark']; + } + + return array( + 'orderId' => $orderBn, // 订单号(内部变量名使用 orderBn,避免和系统 order_id 混淆) + 'productInfo' => $productInfo, // 商品名称/规格/数量 + 'remark' => $remark, // 备注 + 'data1' => '', // 自定义字段1 + 'data2' => '', // 自定义字段2 + 'data3' => '', // 自定义字段3 + 'data4' => '', // 自定义字段4 + 'data5' => '', // 自定义字段5 + 'data6' => '', // 自定义字段6 + 'customeBarCode' => $barcode, // 条形码(文档字段名即 customeBarCode) + 'merStyleNo' => $itemBn, // 款号(当前无独立字段,先映射 delivery_items.bn) + 'styleNo' => $itemBn, // 货号(delivery_items.bn) + 'barcode' => $barcode, // 条码 + ); + } + + /** + * 将模板 customParams 转成快速判断的 allowMap。 + * + * @param array $customParams + * @return array + */ + private function buildAikucunCustomAllowMap($customParams) + { + $allowMap = array(); + if (empty($customParams)) { + return $allowMap; + } + foreach ($customParams as $field) { + if (is_string($field) && $field !== '') { + $allowMap[$field] = true; + } + } + return $allowMap; + } + + /** + * 聚合 customData 的基础业务字段(订单号、商品信息、款号、条码)。 + * $delivery 为 sdb_wms_delivery 行(与打印页 delivery_id 一致)。 + * + * @param array $delivery + * @return array + */ + private function buildAikucunCustomBaseData($delivery) + { + $deliveryId = isset($delivery['delivery_id']) ? intval($delivery['delivery_id']) : 0; + $defaultOrderBn = isset($delivery['delivery_bn']) ? (string)$delivery['delivery_bn'] : ''; + $result = array( + 'orderBn' => $defaultOrderBn, + 'productInfo' => '', + 'itemBn' => '', + 'barcode' => '', + ); + if ($deliveryId <= 0) { + return $result; + } + // 订单号:delivery_order 挂在 OME 发货单上,用 WMS 已有的 outer→OME 映射,禁止把 WMS 主键当 OME 主键查 + $omeDlyId = app::get('wms')->model('delivery')->getOuterIdById($deliveryId); + if ($omeDlyId) { + $orderRow = app::get('ome')->model('delivery')->getOrderBnbyDeliveryId($omeDlyId); + if (!empty($orderRow['order_bn'])) { + $result['orderBn'] = (string)$orderRow['order_bn']; + } + } + + $rows = app::get('wms')->model('delivery_items')->getList('product_name,number,product_id,bn', array('delivery_id' => $deliveryId)); + if (empty($rows) || !is_array($rows)) { + return $result; + } + + $productIds = array(); + foreach ($rows as $row) { + if (!empty($row['product_id'])) { + $productIds[] = intval($row['product_id']); + } + } + $productIds = array_values(array_unique(array_filter($productIds))); + $productMap = array(); + if (!empty($productIds)) { + $productRows = app::get('ome')->model('products')->getList('product_id,spec_info,barcode', array('product_id' => $productIds)); + foreach ((array)$productRows as $product) { + $pid = intval($product['product_id']); + if ($pid > 0) { + $productMap[$pid] = $product; + } + } + } + + $parts = array(); + foreach ($rows as $row) { + $name = isset($row['product_name']) ? trim((string)$row['product_name']) : ''; + if ($name === '') { + continue; + } + $pid = isset($row['product_id']) ? intval($row['product_id']) : 0; + $spec = ($pid > 0 && !empty($productMap[$pid]['spec_info'])) ? trim((string)$productMap[$pid]['spec_info']) : ''; + $num = isset($row['number']) ? (string)$row['number'] : ''; + $title = $name . ($spec !== '' ? '【' . $spec . '】' : ''); + $parts[] = $title . ($num !== '' ? '/' . $num : ''); + + if ($result['itemBn'] === '' && !empty($row['bn'])) { + $result['itemBn'] = (string)$row['bn']; + } + if ($result['barcode'] === '' && $pid > 0 && !empty($productMap[$pid]['barcode'])) { + $result['barcode'] = (string)$productMap[$pid]['barcode']; + } + } + + $result['productInfo'] = implode(',', $parts); + return $result; + } + + /** + * 发件人信息:与 common 一致优先 channel_extend,否则按 aikucun getDirectSdf 用仓库 + * + * @param array $delivery + * @return array + */ + private function loadShopForAikucunPrint($delivery) + { + $shop = app::get('logisticsmanager')->model('channel_extend')->dump( + array('channel_id' => $this->__channelObj->channel['channel_id']) + ); + if (empty($shop) || (empty($shop['province']) && empty($shop['default_sender']) && empty($shop['mobile']))) { + $shop = array(); + $branch = app::get('ome')->model('branch')->db_dump($delivery['branch_id']); + if (!empty($branch)) { + $mainland = ''; + if (strpos($branch['area'], ':') !== false) { + list(, $mainland) = explode(':', $branch['area'], 2); + } + $province = $city = $area = ''; + if ($mainland !== '') { + $parts = explode('/', $mainland); + $province = isset($parts[0]) ? $parts[0] : ''; + $city = isset($parts[1]) ? $parts[1] : ''; + $area = isset($parts[2]) ? $parts[2] : ''; + } + $shop['province'] = $province; + $shop['city'] = $city; + $shop['area'] = $area; + $shop['street'] = ''; + $shop['address_detail'] = $branch['address']; + $shop['default_sender'] = $branch['uname']; + $shop['mobile'] = $branch['mobile']; + } + } + + return is_array($shop) ? $shop : array(); + } + + /** + * PDF senderInfo 结构 + * + * @param array $shop + * @return array + */ + private function buildAikucunSenderInfo($shop) + { + if (empty($shop)) { + return array(); + } + $province = isset($shop['province']) ? (string)$shop['province'] : ''; + $city = isset($shop['city']) ? (string)$shop['city'] : ''; + $district = isset($shop['area']) ? (string)$shop['area'] : ''; + $street = isset($shop['street']) ? (string)$shop['street'] : ''; + $detail = isset($shop['address_detail']) ? (string)$shop['address_detail'] : ''; + $name = isset($shop['default_sender']) ? (string)$shop['default_sender'] : ''; + $mobile = isset($shop['mobile']) ? (string)$shop['mobile'] : ''; + + if ($province === '' && $city === '' && $district === '' && $detail === '' && $name === '' && $mobile === '') { + return array(); + } + + $address = array( + 'senderProvince' => $province, + 'senderCity' => $city, + 'senderDistrict' => $district, + 'senderAddress' => $detail, + ); + if ($street !== '') { + $address['senderStreet'] = $street; + } + + return array( + array( + 'address' => $address, + 'contact' => array( + 'senderName' => $name, + 'sendermobile' => $mobile, + ), + ), + ); + } + + /** + * 统一构造失败返回,减少重复分支代码。 + * + * @param string $msg + * @return array + */ + private function buildAikucunFailResult($msg) + { + return array( + 'rsp' => 'fail', + 'msg' => $msg, + 'err_msg' => $msg, + ); + } + + /** + * 提取矩阵返回中的 params 值(仅接受非空字符串或非空数组)。 + * + * @param mixed $value + * @return string|array|false + */ + private function extractAikucunParamsValue($value) + { + if (is_string($value) && $value !== '') { + return $value; + } + if (is_array($value) && !empty($value)) { + return $value; + } + return false; + } + + public function getWaybillISearch($sdf = array()) + { + $params = [ + 'cpCode' => $this->__channelObj->channel['logistics_code'], + 'version'=>'2.0', + ]; + + $title = '查询已开通的快递服务'; + + $result = $this->__caller->call(STORE_KS_USER_TEMPLATE, $params, array(), $title, 6, $this->__channelObj->channel['logistics_code']); + + if ($result['rsp'] == 'succ' && $result['data']) { + $data = json_decode($result['data'], 1); + $result['data'] = $data; + } else { + $result['msg'] = $result['err_msg']; + } + $result['request_logistics_code'] = $this->__channelObj->channel['logistics_code']; + $result['channel_type'] = $this->__channelObj->channel['channel_type']; + + $_tmp = []; + $accountId = isset($result['data']['data']['accountId']) ? $result['data']['data']['accountId'] : ''; + if (!empty($result['data']['data']) && is_array($result['data']['data'])) { + foreach ($result['data']['data'] as $row) { + if (empty($row['netSiteList']) || !is_array($row['netSiteList'])) { + continue; + } + foreach ($row['netSiteList'] as $site) { + $_tmp[] = [ + 'acct_id' => $accountId, + 'delivery_id' => isset($row['logisticsCode']) ? $row['logisticsCode'] : '', + 'site_code' => isset($site['netSiteCode']) ? $site['netSiteCode'] : (isset($row['logisticsCode']) ? $row['logisticsCode'] : ''), + 'site_name' => isset($site['netSiteName']) ? $site['netSiteName'] : '', + 'mobile' => isset($site['mobile']) ? $site['mobile'] : '', + 'phone' => isset($site['phone']) ? $site['phone'] : '', + 'name' => isset($site['name']) ? $site['name'] : '', + 'province_name' => isset($site['senderProvince']) ? $site['senderProvince'] : '', + 'city_name' => isset($site['senderCity']) ? $site['senderCity'] : '', + 'district_name' => isset($site['senderDistrict']) ? $site['senderDistrict'] : '', + 'street_name' => isset($site['senderStreet']) ? $site['senderStreet'] : '', + 'detail_address' => isset($site['senderAddress']) ? $site['senderAddress'] : '', + 'customer_code' => isset($site['customerCode']) ? $site['customerCode'] : '', + ]; + } + } + } + $result['data']['account_list'] = $_tmp; + + return $result; + } +} diff --git a/app/erpapi/lib/logistics/matrix/aikucun/request/template.php b/app/erpapi/lib/logistics/matrix/aikucun/request/template.php new file mode 100644 index 00000000..6271317c --- /dev/null +++ b/app/erpapi/lib/logistics/matrix/aikucun/request/template.php @@ -0,0 +1,108 @@ +title = '获取爱库存用户模板'; + $params = ['version' => '2.0']; + + $rs = $this->requestCall(STORE_WAYBILL_USER_TEMPLATE, $params); + + if ($rs['rsp'] == 'succ' && $rs['data']) { + $resData = json_decode($rs['data'], 1); + $rs['data'] = []; + $templateList = $this->extractTemplateList($resData); + foreach ($templateList as $k => $v) { + $outTemplateId = isset($v['customTemplateCode']) ? $v['customTemplateCode'] : ''; + if (!$outTemplateId) { + continue; + } + $tplSelect = isset($v['customParams']) && is_array($v['customParams']) ? array_filter($v['customParams']) : []; + $width = ''; + $height = ''; + $templateCode = isset($v['parentTemplateCode']) ? $v['parentTemplateCode'] : ''; + if ($templateCode && preg_match('/_(\d+)_(\d+)(?:_|$)/', $templateCode, $match)) { + $width = $match[1]; + $height = $match[2]; + } + $rs['data'][] = array( + 'tpl_index' => 'user' . '-' . $outTemplateId, + 'cp_code' => $v['cpCode'], + 'out_template_id' => $outTemplateId, + 'template_name' => $v['customTemplateName'] . '(爱库存)', + 'template_type' => 'aikucun_user', + 'template_select' => $tplSelect, + 'template_data' => json_encode($v), + 'template_width' => $width, + 'template_height' => $height, + ); + } + } else { + $rs['data'] = []; + } + return $rs; + } + + public function syncStandardTpl() + { + $this->title = '获取爱库存标准模板'; + $params = ['version' => '2.0']; + + $rs = $this->requestCall(STORE_WAYBILL_STANDARD_TEMPLATE, $params); + + if ($rs['rsp'] == 'succ' && $rs['data']) { + $resData = json_decode($rs['data'], 1); + $rs['data'] = []; + $templateList = $this->extractTemplateList($resData); + foreach ($templateList as $k => $v) { + $width = ''; + $height = ''; + $templateCode = isset($v['templateCode']) ? $v['templateCode'] : ''; + if ($templateCode && preg_match('/_(\d+)_(\d+)(?:_|$)/', $templateCode, $match)) { + $width = $match[1]; + $height = $match[2]; + } + $rs['data'][] = array( + 'tpl_index' => 'standard' . '-' . $v['templateId'], + 'cp_code' => $v['cpCode'], + 'out_template_id' => $v['templateId'], + 'template_name' => $v['templateName'] . '(爱库存)', + 'template_type' => 'aikucun_standard', + 'template_data' => json_encode($v), + 'template_width' => $width, + 'template_height' => $height, + ); + } + } else { + $rs['data'] = []; + } + return $rs; + } + + private function extractTemplateList($resData) + { + $result = []; + $data = isset($resData['data']) ? $resData['data'] : []; + + // 仅按爱库存当前返回结构解析:data[] -> logisticsCode + templateList[] + if (is_array($data)) { + foreach ($data as $group) { + $cpCode = isset($group['logisticsCode']) ? $group['logisticsCode'] : ''; + if (empty($group['templateList']) || !is_array($group['templateList'])) { + continue; + } + foreach ($group['templateList'] as $tpl) { + $tpl['cpCode'] = $cpCode; + $result[] = $tpl; + } + } + } + + return $result; + } +} diff --git a/app/erpapi/lib/shop/matrix/taobao/request/delivery.php b/app/erpapi/lib/shop/matrix/taobao/request/delivery.php index 9562544a..6ecf32f3 100644 --- a/app/erpapi/lib/shop/matrix/taobao/request/delivery.php +++ b/app/erpapi/lib/shop/matrix/taobao/request/delivery.php @@ -111,8 +111,12 @@ class erpapi_shop_matrix_taobao_request_delivery extends erpapi_shop_request_del // 淘宝直销、分销是否是国补订单的发货回写 $order_id = $sdf['orderinfo']['order_id']; $isGuobu = kernel::single('ome_bill_label')->getBillLabelInfo($order_id, 'order', 'SOMS_GB'); - if ($isGuobu && ($isGuobu['label_value'] & 0x0040 || $isGuobu['label_value'] & 0x0080)) { - if ($sdf['feature'] && !$param['feature']) $param['feature'] = $sdf['feature']; + if ($isGuobu) { + if ($isGuobu['label_value'] & 0x0040 || $isGuobu['label_value'] & 0x0080) { + if ($sdf['feature'] && !$param['feature']) $param['feature'] = $sdf['feature']; + } else { + unset($param['feature']); + } } //同城配场景 diff --git a/app/erpapi/lib/shop/matrix/tmall/request/delivery.php b/app/erpapi/lib/shop/matrix/tmall/request/delivery.php index 44e0152e..bca9946a 100644 --- a/app/erpapi/lib/shop/matrix/tmall/request/delivery.php +++ b/app/erpapi/lib/shop/matrix/tmall/request/delivery.php @@ -116,8 +116,12 @@ class erpapi_shop_matrix_tmall_request_delivery extends erpapi_shop_request_deli // 淘宝直销、分销是否是国补订单的发货回写 $order_id = $sdf['orderinfo']['order_id']; $isGuobu = kernel::single('ome_bill_label')->getBillLabelInfo($order_id, 'order', 'SOMS_GB'); - if ($isGuobu && ($isGuobu['label_value'] & 0x0040 || $isGuobu['label_value'] & 0x0080)) { - if ($sdf['feature'] && !$param['feature']) $param['feature'] = $sdf['feature']; + if ($isGuobu) { + if ($isGuobu['label_value'] & 0x0040 || $isGuobu['label_value'] & 0x0080) { + if ($sdf['feature'] && !$param['feature']) $param['feature'] = $sdf['feature']; + } else { + unset($param['feature']); + } } //同城配场景 diff --git a/app/logisticsmanager/controller/admin/channel.php b/app/logisticsmanager/controller/admin/channel.php index ba8e3891..11943d4f 100644 --- a/app/logisticsmanager/controller/admin/channel.php +++ b/app/logisticsmanager/controller/admin/channel.php @@ -348,7 +348,8 @@ EOF; $data['shop_id'] = $_POST['shop_id']; $is_ome_bind_unionpay = false; - #检测是否已绑定银联 + + //检测是否已绑定银联 base_kvstore::instance('ome/bind/unionpay')->fetch('ome_bind_unionpay', $is_ome_bind_unionpay); if (!$is_ome_bind_unionpay) { $bind_status = kernel::single('erpapi_router_request')->set('unionpay', '1705101437')->unionpay_bind(); @@ -359,7 +360,7 @@ EOF; } } } elseif ($data['channel_type'] == 'jdalpha') { - #编辑的时候,支付方式,不允许改 + //编辑的时候,支付方式,不允许改 if ($_POST['channel_id']) { $channel = $channelObj->dump(array('channel_id' => $_POST['channel_id'])); $sfinfo = explode('|||', $channel['shop_id']); @@ -518,13 +519,11 @@ EOF; kernel::single('wms_event_trigger_logistics_electron')->bufferGetWaybill($data['channel_id']); } if (in_array($data['channel_type'], ['taobao','jdalpha'])) { -//默认获取发货地址 + //默认获取发货地址 $extendObj = app::get('logisticsmanager')->model('channel_extend'); $extend = $extendObj->dump(array('channel_id' => $data['channel_id']), 'id'); if (!$extend) { - kernel::single('erpapi_router_request')->set('logistics', $data['channel_id'])->electron_getWaybillISearch(); - } } echo "SUCC"; @@ -852,11 +851,14 @@ EOF; if ($res['request_logistics_code']!=$v['delivery_id']) { continue; } - $key = $v['acct_id']; - if (isset($v['_unique_acct_id']) && $v['_unique_acct_id']) { - $key = $v['_unique_acct_id']; + // 与云起一致:xhs/美团医药/爱库存等接口可能返回空 acct_id,不能用 acct_id 作数组键,否则单选 value 为空且 POST 校验失败 + $uniqueKey = $v['acct_id']; + if (in_array($res['channel_type'], array('xhs', 'meituan4medicine', 'aikucun'))) { + $uniqueKey = $k + 1; + } elseif (isset($v['_unique_acct_id']) && $v['_unique_acct_id']) { + $uniqueKey = $v['_unique_acct_id']; } - $accountList[$key] = [ + $accountList[$uniqueKey] = [ 'available' => $v['available'], 'status' => $v['status'], 'delivery_id' => $v['delivery_id'], @@ -882,6 +884,7 @@ EOF; 'district_name' => $v['district_name'], 'city_code' => $v['city_code'], 'province_name' => $v['province_name'], + 'bizLine' => isset($v['bizLine']) ? $v['bizLine'] : '', ]; } } @@ -906,7 +909,8 @@ EOF; } $accountList = json_decode($_POST['account_list_json'], 1); - $accountInfo = $accountList[$_POST['_unique_acct_id']]; + $pickKey = (string) $_POST['_unique_acct_id']; + $accountInfo = isset($accountList[$pickKey]) ? $accountList[$pickKey] : null; if (!$accountInfo) { $this->end(false, '电子面单账号id无效'); } @@ -926,8 +930,8 @@ EOF; 'address_detail' => $accountInfo['detail_address'], 'street' => $accountInfo['street_name'], 'default_sender' => $accountInfo['name'], - 'mobile' => $accountInfo['mobile'], - 'tel' => $accountInfo['phone'], + 'mobile' => $accountInfo['mobile'] ? $accountInfo['mobile'] : $accountInfo['phone'], + 'tel' => $accountInfo['phone'] ? $accountInfo['phone'] : $accountInfo['mobile'], 'shop_name' => $accountInfo['site_name'], 'seller_id' => $accountInfo['acct_id'], ); @@ -938,6 +942,7 @@ EOF; 'site_code' => $accountInfo['site_code'], 'acct_id' => $accountInfo['acct_id'], 'shop_id' => $accountInfo['shop_id'], + 'bizLine' => isset($accountInfo['bizLine']) ? $accountInfo['bizLine'] : '', ]; } @@ -1125,10 +1130,6 @@ EOF; $this->end(false, '保存失败:'.$channelMdl->db->errorinfo()); } - - - - $channelExt = [ 'channel_id' => $channel['channel_id'], 'province' => $netsite_address['province_name'], diff --git a/app/logisticsmanager/controller/admin/express/cainiao.php b/app/logisticsmanager/controller/admin/express/cainiao.php index 2118a391..9f7e4658 100644 --- a/app/logisticsmanager/controller/admin/express/cainiao.php +++ b/app/logisticsmanager/controller/admin/express/cainiao.php @@ -40,6 +40,7 @@ class logisticsmanager_ctl_admin_express_cainiao extends desktop_controller { 'dewu'=>'得物品牌直发电子面单', 'meituan4bulkpurchasing'=>'美团电商', 'youzan'=>'有赞电子面单', + 'aikucun'=>'爱库存电子面单', ]; $this->display('admin/express/pre_sync_tpl.html'); } diff --git a/app/logisticsmanager/controller/admin/express/template.php b/app/logisticsmanager/controller/admin/express/template.php index 657e8a4b..f7a95efd 100644 --- a/app/logisticsmanager/controller/admin/express/template.php +++ b/app/logisticsmanager/controller/admin/express/template.php @@ -20,7 +20,7 @@ class logisticsmanager_ctl_admin_express_template extends desktop_controller{ var $workground = "setting_tools"; function index(){ - $base_filter = array('template_type' => array('normal', 'electron' , 'cainiao', 'cainiao_standard', 'cainiao_user', 'pdd_standard', 'pdd_user', 'jd_standard', 'jd_user', 'douyin_standard', 'douyin_user','kuaishou_standard','kuaishou_user','wphvip_standard','wphvip_user', 'sf', 'xhs_standard', 'xhs_user', 'wxshipin_standard', 'wxshipin_user','dewu_ppzf','dewu_ppzf_zy','meituan4bulkpurchasing_user','youzan_standard')); + $base_filter = array('template_type' => array('normal', 'electron' , 'cainiao', 'cainiao_standard', 'cainiao_user', 'pdd_standard', 'pdd_user', 'jd_standard', 'jd_user', 'douyin_standard', 'douyin_user','kuaishou_standard','kuaishou_user','wphvip_standard','wphvip_user', 'sf', 'xhs_standard', 'xhs_user', 'aikucun_standard', 'aikucun_user', 'wxshipin_standard', 'wxshipin_user','dewu_ppzf','dewu_ppzf_zy','meituan4bulkpurchasing_user','youzan_standard')); $params = array( 'title'=>'快递面单管理', 'actions' => array( @@ -78,6 +78,7 @@ class logisticsmanager_ctl_admin_express_template extends desktop_controller{ 'wphvip' => array('label' => app::get('base')->_('唯品会vip'), 'filter' => array('filter_sql' => 'template_type in("wphvip_user","wphvip_standard")', 'status' => 'true'), 'optional' => false), 'sf' => array('label' => app::get('base')->_('顺丰'), 'filter' => array('filter_sql' => 'template_type in("sf")', 'status' => 'true'), 'optional' => false), 'xhs' => array('label' => app::get('base')->_('小红书'), 'filter' => array('filter_sql' => 'template_type in("xhs_standard","xhs_user")', 'status' => 'true'), 'optional' => false), + 'aikucun' => array('label' => app::get('base')->_('爱库存'), 'filter' => array('filter_sql' => 'template_type in("aikucun_standard","aikucun_user")', 'status' => 'true'), 'optional' => false), 'wxshipin' => array('label' => app::get('base')->_('微信视频号'), 'filter' => array('filter_sql' => 'template_type in("wxshipin_standard","wxshipin_user")', 'status' => 'true'), 'optional' => false), 'youzan' => array('label' => app::get('base')->_('有赞'), 'filter' => array('filter_sql' => 'template_type in("youzan_standard")', 'status' => 'true'), 'optional' => false), 'dewu' => array('label' => app::get('base')->_('得物'), 'filter' => array('filter_sql' => 'template_type in("dewu_ppzf","dewu_ppzf_zy")', 'status' => 'true'), 'optional' => false), diff --git a/app/logisticsmanager/controller/admin/waybill.php b/app/logisticsmanager/controller/admin/waybill.php index 3b7cd33a..e903248f 100644 --- a/app/logisticsmanager/controller/admin/waybill.php +++ b/app/logisticsmanager/controller/admin/waybill.php @@ -74,18 +74,32 @@ class logisticsmanager_ctl_admin_waybill extends desktop_controller{ * @return mixed 返回结果 */ public function getEncryptPrintData() { - $logiNo = trim($_POST['logi_no']); - $batchLogiNo = trim($_POST['batch_logi_no']); - $deliveryId = intval($_POST['delivery_id']); - $channelId = trim($_POST['channel_id']); + $logiNo = trim($_POST['logi_no']); + $batchLogiNo = trim($_POST['batch_logi_no']); + $deliveryId = intval($_POST['delivery_id']); + $channelId = trim($_POST['channel_id']); + $requestData = [ + 'logi_no' => $logiNo, + 'batch_logi_no' => $batchLogiNo, + 'delivery_id' => $deliveryId, + ]; + + $channelType = ''; + if ($channelId) { + $channel = app::get('logisticsmanager')->model('channel')->dump(['channel_id' => $channelId], 'channel_type'); + $channelType = isset($channel['channel_type']) ? $channel['channel_type'] : ''; + } + if ($channelType === 'aikucun') { + $requestData['print_name'] = isset($_POST['print_name']) ? trim($_POST['print_name']) : ''; + $requestData['mode'] = isset($_POST['mode']) ? trim($_POST['mode']) : ''; + $requestData['prepare_data'] = isset($_POST['prepare_data']) ? $_POST['prepare_data'] : ''; + } elseif (isset($_POST['custom_data'])) { + $requestData['custom_data'] = $_POST['custom_data']; + } + $rs = kernel::single('erpapi_router_request') - ->set('logistics',$channelId) - ->electron_getEncryptPrintData([ - 'logi_no' =>$logiNo, - 'batch_logi_no' =>$batchLogiNo, - 'delivery_id' =>$deliveryId, - 'custom_data' => $_POST['custom_data'] - ]); + ->set('logistics', $channelId) + ->electron_getEncryptPrintData($requestData); echo json_encode($rs); } } \ No newline at end of file diff --git a/app/logisticsmanager/dbschema/express_template.php b/app/logisticsmanager/dbschema/express_template.php index 4ed98450..4ac70d3a 100644 --- a/app/logisticsmanager/dbschema/express_template.php +++ b/app/logisticsmanager/dbschema/express_template.php @@ -76,6 +76,8 @@ $db['express_template'] = array( 'sf' => '顺丰面单', 'xhs_standard'=>'小红书面单', 'xhs_user'=>'小红书面单', + 'aikucun_standard'=>'爱库存面单', + 'aikucun_user'=>'爱库存自定义面单', 'wxshipin_standard'=>'微信视频号面单', 'wxshipin_user'=>'微信视频号面单', 'meituan4bulkpurchasing_user'=>'美团电商面单', diff --git a/app/logisticsmanager/lib/print/tmpl.php b/app/logisticsmanager/lib/print/tmpl.php index 911d427d..ec8050df 100644 --- a/app/logisticsmanager/lib/print/tmpl.php +++ b/app/logisticsmanager/lib/print/tmpl.php @@ -150,7 +150,7 @@ class logisticsmanager_print_tmpl { } return array('rs'=>'fail', 'msg'=>$title); } - if (!in_array($data['template_type'],array('normal', 'electron', 'delivery', 'stock','cainiao', 'cainiao_standard', 'cainiao_user', 'pdd_standard', 'pdd_user','jd_standard','jd_user', 'douyin_standard', 'douyin_user','kuaishou_standard','kuaishou_user','wphvip_standard','wphvip_user','sf','xhs_standard','xhs_user','wxshipin_standard','wxshipin_user','dewu_ppzf','dewu_ppzf_zy','meituan4bulkpurchasing_user','youzan_standard'))) { + if (!in_array($data['template_type'],array('normal', 'electron', 'delivery', 'stock','cainiao', 'cainiao_standard', 'cainiao_user', 'pdd_standard', 'pdd_user','jd_standard','jd_user', 'douyin_standard', 'douyin_user','kuaishou_standard','kuaishou_user','wphvip_standard','wphvip_user','sf','xhs_standard','xhs_user','aikucun_standard','aikucun_user','wxshipin_standard','wxshipin_user','dewu_ppzf','dewu_ppzf_zy','meituan4bulkpurchasing_user','youzan_standard'))) { return array('rs'=>'fail', 'msg'=>'面单类型不符合规则!'); } if(!$data['template_width'] || !$data['template_height']){ diff --git a/app/logisticsmanager/lib/waybill/aikucun.php b/app/logisticsmanager/lib/waybill/aikucun.php index 880cbd52..69fbb3ea 100644 --- a/app/logisticsmanager/lib/waybill/aikucun.php +++ b/app/logisticsmanager/lib/waybill/aikucun.php @@ -14,29 +14,289 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - class logisticsmanager_waybill_aikucun { - //获取物流公司 - /** - * logistics - * @param mixed $logistics_code logistics_code - * @return mixed 返回值 - */ + + public function service_code($param) + { + $cpCode = $param['logistics']; + $service = array( + 'zhongtong' => array( + ), + 'jtexpress' => array( + ), + 'shunfeng' => array( + 'customerCode' => array( + 'text' => '月结卡号', + 'code' => 'customerCode', + 'input_type' => 'input', + 'require' => 'true', + ), + 'productType' => array( + 'text' => '产品类型', + 'code' => 'productType', + 'input_type' => 'select', + 'options' => array( + '' => '', + '1' => '顺丰特快', + '2' => '顺丰标快', + '6' => '顺丰即日', + '10' => '国际小包', + '23' => '顺丰国际特惠(文件)', + '24' => '顺丰国际特惠(包裹)', + '26' => '国际大件', + '29' => '国际电商专递-标准', + '30' => '三号便利箱(特快)', + '31' => '便利封/袋(特快)', + '32' => '二号便利箱(特快)', + '33' => '岛内件(80CM)', + '35' => '物资配送', + '39' => '岛内件(110CM)', + '40' => '岛内件(140CM)', + '41' => '岛内件(170CM)', + '42' => '岛内件(210CM)', + '43' => '台湾岛内件-批(80CM)', + '44' => '台湾岛内件-批(110CM)', + '45' => '台湾岛内件-批(140CM)', + '46' => '台湾岛内件-批(170CM)', + '47' => '台湾岛内件-批(210CM)', + '48' => '台湾岛内件店取(80CM)', + '49' => '台湾岛内件店取(110CM)', + '50' => '千点取60', + '51' => '千点取80', + '52' => '千点取100', + '53' => '电商盒子F1', + '54' => '电商盒子F2', + '55' => '电商盒子F3', + '56' => '电商盒子F4', + '57' => '电商盒子F5', + '58' => '电商盒子F6', + '59' => 'E顺递', + '60' => '顺丰特快(文件)', + '61' => 'C1类包裹', + '62' => 'C2类包裹', + '63' => 'C3类包裹', + '64' => 'C4类包裹', + '65' => 'C5类包裹', + '66' => '特快D类', + '73' => 'F5超值箱', + '99' => '顺丰国际标快(文件)', + '100' => '顺丰国际标快(包裹)', + '104' => '岛内件(80CM,1kg以内)', + '106' => '国际重货-门到门', + '111' => '顺丰干配', + '113' => '便利封/袋(标快)', + '114' => '二号便利箱(标快)', + '115' => '三号便利箱(标快)', + '116' => '国际标快-BD2', + '117' => '国际标快-BD3', + '118' => '国际标快-BD4', + '119' => '国际标快-BD5', + '120' => '国际标快-BD6', + '121' => '国际标快-BDE', + '126' => '掌柜-大格', + '127' => '掌柜-中格', + '128' => '掌柜-小格', + '129' => '掌柜-柜到柜(单程)', + '130' => '掌柜-柜到柜(双程)', + '132' => '顺丰国际特惠(FBA)', + '136' => '国际集运', + '144' => '当日配-门(80CM/1KG以内)', + '145' => '当日配-门(80CM)', + '146' => '当日配-门(110CM)', + '147' => '当日配-门(140CM)', + '148' => '当日配-门(170CM)', + '149' => '当日配-门(210CM)', + '150' => '标快D类', + '153' => '整车直达', + '160' => '国际重货-港到港', + '178' => '一号便利箱(特快)', + '179' => '一号便利箱(标快)', + '180' => '岛內件-专车普运', + '184' => '顺丰国际标快+(文件)', + '186' => '顺丰国际标快+(包裹)', + '201' => '冷运标快', + '202' => '顺丰微小件', + '207' => '限时寄递', + '215' => '大票直送', + '218' => '国际电商专递-CD', + '221' => '香港冷运到家(≤60厘米)', + '222' => '香港冷运到家(61-80厘米)', + '223' => '香港冷运到家(81-100厘米)', + '224' => '香港冷运到家(101-120厘米)', + '225' => '香港冷运到家(121-150厘米)', + '231' => '陆运包裹', + '235' => '预售当天达', + '236' => '电商退货', + '241' => '国际电商专递-快速', + '244' => '店到店', + '245' => '店到门', + '246' => '门到店', + '247' => '电商标快', + '249' => '丰礼遇', + '252' => '前置小时达', + '253' => '前置当天达', + '255' => '顺丰卡航', + '256' => '顺丰卡航(D类)', + '257' => '医药温控配送', + '258' => '退换自寄', + '259' => '极速配', + '261' => 'O2O店配', + '262' => '前置标快', + '263' => '同城半日达', + '265' => '预售电标', + '266' => '顺丰空配(新)', + '267' => '行李送递-上门', + '268' => '行李送递', + '269' => '酒类配送', + '270' => '行李托运-上门', + '271' => '行李托运', + '272' => '行李送递-上门 (九龙)', + '273' => '温控配送自取', + '274' => '温控配送上门', + '275' => '酒类温控自取', + '276' => '酒类温控上门', + '277' => '跨境FBA空运', + '278' => '跨境FBA海运', + '283' => '填舱标快', + '285' => '填舱电标', + '288' => '冷运大件到港', + '289' => '跨城急件', + '293' => '特快包裹(新)', + '297' => '样本安心递', + '299' => '标快零担', + '303' => '专享急件', + '308' => '国际特快(文件)', + '310' => '国际特快(包裹)', + '316' => '前置次日达', + '318' => '航空港到港', + '323' => '电商微小件', + '325' => '温控包裹', + '329' => '填舱大件', + ), + ), + ), + 'yunda' => array( + ), + 'yuantong' => array( + ), + 'shentong' => array( + ), + 'youzhengguonei' => array( + 'customerCode' => array( + 'text' => '月结卡号', + 'code' => 'customerCode', + 'input_type' => 'input', + 'require' => 'true', + ), + ), + 'ems' => array( + 'customerCode' => array( + 'text' => '月结卡号', + 'code' => 'customerCode', + 'input_type' => 'input', + 'require' => 'true', + ), + ), + 'yzdsbk' => array( + 'customerCode' => array( + 'text' => '月结卡号', + 'code' => 'customerCode', + 'input_type' => 'input', + 'require' => 'true', + ), + ), + 'jd' => array( + 'customerCode' => array( + 'text' => '月结卡号', + 'code' => 'customerCode', + 'input_type' => 'input', + 'require' => 'true', + ), + 'productType' => array( + 'text' => '产品类型', + 'code' => 'productType', + 'input_type' => 'select', + 'options' => array( + '' => '', + 'ed-m-0001' => '京东标快', + 'ed-m-0002' => '京东特快', + 'LL-HD-M' => '生鲜标快', + 'LL-SD-M' => '生鲜特快', + 'ed-m-0017' => '函速达', + 'ed-m-0012' => '特惠包裹', + 'ed-m-0059' => '电商标快', + 'ed-m-0019' => '电商特惠', + 'ed-m-0005' => '同城急送', + 'fr-m-0004' => '特快重货', + 'fr-m-0007' => '航空重货', + 'fr-m-0017' => '特惠专配', + 'fr-m-0018' => '爱宝速递', + 'ed-m-00000' => '智能分单', + ), + ), + ), + 'debangwuliu' => array( + 'customerCode' => array( + 'text' => '月结卡号', + 'code' => 'customerCode', + 'input_type' => 'input', + 'require' => 'true', + ), + 'productType' => array( + 'text' => '产品类型', + 'code' => 'productType', + 'input_type' => 'select', + 'options' => array( + '' => '', + 'RCP' => '大件快递3.60', + 'PACKAGE'=> '标准快递', + 'TZKJC' => '特快专递', + 'HKDJG' => '航空大件隔日达', + 'HKDJC' => '航空大件次日达', + 'NZBRH' => '重包入户', + 'NFLF' => '精准卡航(新)', + 'NJZZH' => '精准重货(新)', + 'NLRF' => '精准汽运(新)', + ), + ), + ), + ); + return isset($service[$cpCode]) ? $service[$cpCode] : []; + } + + public function template_cfg() + { + $arr = array( + 'template_name' => '爱库存', + 'shop_name' => '爱库存', + 'print_url' => 'https://mx-lews-web.aikucun.com/merchant/xiazai', + 'shop_type' => 'aikucun', + 'control_type' => 'aikucun', + 'request_again' => true, + ); + return $arr; + } + public function logistics($logistics_code = '') { $logistics = array( - 'ZTO' => array('code' => 'ZTO', 'name' => '中通速递','mode'=>'join'), - 'YUNDA' => array('code' => 'YUNDA', 'name' => '韵达快递','mode'=>'join'), - 'YTO' => array('code' => 'YTO','name'=>'圆通快递','mode'=>'join'), - 'DBL' => array('code' => 'DBL','name'=>'德邦快递','mode'=>'direct'), - 'UC' => array('code' => 'UC', 'name'=>'优速快递','mode'=>'join'), - 'JD' => array('code' => 'JD', 'name'=>'京东快递'), + 'zhongtong' => array('code' => 'zhongtong', 'name' => '中通速递', 'mode' => 'join'), + 'jtexpress' => array('code' => 'jtexpress', 'name' => '极兔速递', 'mode' => 'join'), + 'shunfeng' => array('code' => 'shunfeng', 'name' => '顺丰速运', 'mode' => 'direct'), + 'yunda' => array('code' => 'yunda', 'name' => '韵达快递', 'mode' => 'join'), + 'yuantong' => array('code' => 'yuantong', 'name' => '圆通快递', 'mode' => 'join'), + 'shentong' => array('code' => 'shentong', 'name' => '申通速递', 'mode' => 'join'), + 'youzhengguonei' => array('code' => 'youzhengguonei', 'name' => '中国邮政', 'mode' => 'direct'), + 'ems' => array('code' => 'ems', 'name' => 'EMS', 'mode' => 'direct'), + 'yzdsbk' => array('code' => 'yzdsbk', 'name' => '邮政电商标快', 'mode' => 'direct'), + 'jd' => array('code' => 'jd', 'name' => '京东快递', 'mode' => 'direct'), + 'debangwuliu' => array('code' => 'debangwuliu', 'name' => '德邦快递', 'mode' => 'direct'), ); - if(!empty($logistics_code)) { + if (!empty($logistics_code)) { return $logistics[$logistics_code]; } return $logistics; } -} \ No newline at end of file +} diff --git a/app/logisticsmanager/model/channel.php b/app/logisticsmanager/model/channel.php index ac9784b9..15990e47 100644 --- a/app/logisticsmanager/model/channel.php +++ b/app/logisticsmanager/model/channel.php @@ -17,7 +17,7 @@ class logisticsmanager_mdl_channel extends dbeav_model { - public $getWaybillAccountFromApi = ['wxshipin', 'xhs', 'meituan4bulkpurchasing']; + public $getWaybillAccountFromApi = ['wxshipin', 'xhs', 'meituan4bulkpurchasing', 'aikucun']; function modifier_status($row){ if ($row == 'false') { diff --git a/app/logisticsmanager/statics/js/printer.js b/app/logisticsmanager/statics/js/printer.js index f19f72af..89cd1cfb 100644 --- a/app/logisticsmanager/statics/js/printer.js +++ b/app/logisticsmanager/statics/js/printer.js @@ -37,6 +37,8 @@ return new SfPrinter(options); case 'xhs': return new XhsPrinter(options); + case 'aikucun': + return new AikucunPrinter(options); case 'wxshipin': return new WxshipinPrinter(options); case 'dewuppzf': // 得物品牌直发 @@ -1829,6 +1831,468 @@ var CaiNiaoPrinter = new Class({ }, }); + var AikucunPrinter = new Class({ + Extends: Printer, + printerInfoQueryResolved: false, + aikucunTaskMap: {}, + aikucunHandledResponseMap: {}, + refreshingEncryptData: false, + signVerifyDialog: null, + initialize: function(options){ + this.parent(options); + this.warmupAikucunPrepareData(); + this.webSocket = new WebSocket('ws://localhost:2750'); + + this.webSocket.onopen = function(event) { + + this.webSocket.onmessage = function(event) + { + console.log('====onmessage:', event); + eval('var data = ' + event.data); + if (this.handleAikucunPrinterInfoQueryResponse(data)) { + return; + } + if (this.handleAikucunPrintResponse(data)) { + return; + } + switch(data.cmd) { + case 'print': + if (data.previewImage) { + this.fireEvent('preview', data);break; + } else { + this.fireEvent('printComplete', data);break; + } + case 'notifyPrintResult': + if(data.taskStatus == 'printed') { + this.fireEvent('printSuccess', data);break; + } else if(data.taskStatus == 'failed') { + this.fireEvent('printFailure', data);break; + } + } + }.bind(this); + + this.webSocket.onclose = function(event) + { + this.fireEvent('close'); + }.bind(this); + + this.fireEvent('open'); + }.bind(this); + + this.webSocket.onerror = function(event) + { + this.fireEvent('error'); + }.bind(this); + }, + isReady:function(){ + if (this.webSocket.readyState == 0) { + this.fireEvent('error',{errmsg:'正在连接爱库存打印组件,请稍后再试!'}); + + return false; + } + + return true; + }, + showAikucunSignVerifyDialog:function(){ + if (this.signVerifyDialog) { + return; + } + this.signVerifyDialog = new Dialog(new Element("div.tableform",{html:'

数据验证中......

正在请求签名参数,请稍等。
'}), + { + title:'打印数据校验', + width:420, + height:120, + resizeable:false, + }); + }, + closeAikucunSignVerifyDialog:function(){ + if (!this.signVerifyDialog) { + return; + } + this.signVerifyDialog.close(); + this.signVerifyDialog = null; + }, + parseAikucunJsonPacket:function(jsonPacket){ + if (typeof jsonPacket === 'string') { + return JSON.decode(jsonPacket.replace(/“/g, '"')); + } + return jsonPacket; + }, + getAikucunOptionData:function(){ + var data = this.options.data; + if (typeof data === 'string'){ + data = JSON.decode(data); + } + return data || []; + }, + requestAikucunPrepareData:function(printRow, callback){ + new Request.JSON({ + url:'index.php?app=logisticsmanager&ctl=admin_waybill&act=getEncryptPrintData', + data:{ + 'logi_no':printRow['logi_no'], + 'batch_logi_no':printRow['batch_logi_no'], + 'delivery_id':printRow['delivery_id'], + 'channel_id':printRow['channel_id'], + 'mode':'prepare' + }, + onComplete:function(rs) { + if (rs && rs.rsp == 'succ' && rs.data) { + callback(true, rs.data); + return; + } + callback(false, null); + } + }).send(); + }, + warmupAikucunPrepareData:function(){ + var data = this.getAikucunOptionData(); + if (!data || !data.length) { + return; + } + var queueNum = 5; + var total = data.length; + var finished = 0; + var _this = this; + var process = function(idx){ + if (idx >= total) { + finished++; + if (finished < queueNum) { + return; + } + _this.options.data = typeof _this.options.data === 'string' ? _this.toUnicode(JSON.encode(data)) : data; + return; + } + if (!data[idx]) { + process(idx + queueNum); + return; + } + var jsonPacket = _this.parseAikucunJsonPacket(data[idx]['json_packet']); + var prepareData = _this.resolveAikucunPrepareData(jsonPacket, data[idx]); + if (prepareData && prepareData.mxEctData) { + process(idx + queueNum); + return; + } + _this.requestAikucunPrepareData(data[idx], function(ok, prepareRsp){ + if (ok) { + data[idx]['json_packet'] = prepareRsp; + } + process(idx + queueNum); + }); + }; + for (var i = 0; i < queueNum; i++) { + process(i); + } + }, + refreshAikucunSignData:function(printName, onComplete){ + var data = this.getAikucunOptionData(); + var iTotal = data.length; + if (!iTotal) { + if (typeOf(onComplete) === 'function') { + onComplete({success: true, failCount: 0, total: 0}); + } + return; + } + var iFail = 0; + var queueNum = 5; + var finishQueueNum = 0; + var _this = this; + var process = function(idx){ + if (idx >= iTotal) { + finishQueueNum++; + if (finishQueueNum < queueNum) { + return; + } + _this.options.data = typeof _this.options.data === 'string' ? _this.toUnicode(JSON.encode(data)) : data; + if (typeOf(onComplete) === 'function') { + onComplete({success: iFail === 0, failCount: iFail, total: iTotal}); + } + return; + } + if (!data[idx]) { + process(idx + queueNum); + return; + } + var jsonPacket = this.parseAikucunJsonPacket(data[idx]['json_packet']); + var prepareData = this.resolveAikucunPrepareData(jsonPacket, data[idx]); + var continueSign = function(currentPrepareData){ + if (!currentPrepareData || !currentPrepareData.mxEctData) { + iFail++; + process(idx + queueNum); + return; + } + new Request.JSON({ + url:'index.php?app=logisticsmanager&ctl=admin_waybill&act=getEncryptPrintData', + data:{ + 'logi_no':data[idx]['logi_no'], + 'batch_logi_no':data[idx]['batch_logi_no'], + 'delivery_id':data[idx]['delivery_id'], + 'channel_id':data[idx]['channel_id'], + 'print_name':printName ? printName : '', + 'mode':'sign', + 'prepare_data':JSON.encode(currentPrepareData) + }, + onComplete:function(rs) { + if(rs.rsp == 'succ') { + rs.data.prepareData = currentPrepareData; + data[idx]['json_packet'] = rs.data; + } else { + iFail++; + } + process(idx + queueNum); + } + }).send(); + }; + if (!prepareData || !prepareData.mxEctData) { + this.requestAikucunPrepareData(data[idx], function(ok, prepareRsp){ + if (!ok) { + iFail++; + process(idx + queueNum); + return; + } + data[idx]['json_packet'] = prepareRsp; + var fallbackPacket = this.parseAikucunJsonPacket(data[idx]['json_packet']); + continueSign(this.resolveAikucunPrepareData(fallbackPacket, data[idx])); + }.bind(this)); + return; + } + continueSign(prepareData); + }.bind(this); + for (var i = 0; i < queueNum; i++) { + process(i); + } + }, + resolveAikucunPrepareData:function(jsonPacket, printData){ + if (!jsonPacket || typeof jsonPacket !== 'object') { + return null; + } + if (jsonPacket.prepareData && typeof jsonPacket.prepareData === 'object' && jsonPacket.prepareData.mxEctData) { + return JSON.decode(JSON.encode(jsonPacket.prepareData)); + } + var pd = jsonPacket.printData && typeof jsonPacket.printData === 'object' ? jsonPacket.printData : null; + if (!pd || !pd.mxEctData) { + return null; + } + return { + orderId: jsonPacket.orderId ? jsonPacket.orderId : '', + logisticsNo: pd.logisticsNo ? pd.logisticsNo : (jsonPacket.logisticsNo ? jsonPacket.logisticsNo : (printData.logi_no ? printData.logi_no : '')), + mxEctData: pd.mxEctData + }; + }, + executeAikucunPrint:function(printer, isPreview){ + if (!this.isReady()) { + return false; + } + if (this.refreshingEncryptData) { + this.fireEvent('error', {errmsg:'正在刷新打印签名数据,请稍后再试'}); + return false; + } + this.refreshingEncryptData = true; + this.showAikucunSignVerifyDialog(); + this.refreshAikucunSignData(printer.name, function(result){ + this.refreshingEncryptData = false; + this.closeAikucunSignVerifyDialog(); + if (!result || result.failCount > 0) { + this.fireEvent('error', {errmsg:'获取打印签名数据失败,请重试'}); + return; + } + var tasks = this.formatData(this.options.data, isPreview); + tasks.each(function(task){ + this.aikucunTaskMap[task.requestId] = { + documentID: task.documentID, + is_preview: isPreview + }; + this.aikucunHandledResponseMap[task.requestId] = false; + console.log( + isPreview + ? '======Aikucun send preview payload json(with params):' + : '======Aikucun send print payload json(with params):', + JSON.stringify(task.payload) + ); + this.webSocket.send(JSON.stringify(task.payload)); + }.bind(this)); + }.bind(this)); + return true; + }, + print:function(printer){ + return this.executeAikucunPrint(printer, false); + }, + preview:function(printer){ + return this.executeAikucunPrint(printer, true); + }, + getPrinters:function(){ + if (!this.isReady()) { + return false; + } + this.printerInfoQueryResolved = false; + var req = {esubrc: 'printerInfoQuery'}; + this.webSocket.send(JSON.stringify(req)); + + return true; + }, + markPrinterInfoQueryResolved:function(){ + this.printerInfoQueryResolved = true; + }, + handleAikucunPrinterInfoQueryResponse:function(data){ + if (!data || data.cmd) { + return false; + } + var isPrinterInfoRsp = data.esubrc === 'printerInfoQuery' || typeof data.printers !== 'undefined'; + if (!isPrinterInfoRsp) { + return false; + } + if (String(data.code || '') !== '' && String(data.code) !== '00000') { + this.markPrinterInfoQueryResolved(); + this.fireEvent('error', {errmsg: data.message ? data.message : '获取打印机列表失败'}); + return true; + } + if (this.printerInfoQueryResolved) { + return true; + } + var normalized = this.normalizeAikucunPrintersResponse(data); + if (!normalized) { + this.markPrinterInfoQueryResolved(); + this.fireEvent('error', {errmsg: data.message ? data.message : '获取打印机列表失败'}); + return true; + } + this.markPrinterInfoQueryResolved(); + this.fireEvent('getPrinters', normalized); + + return true; + }, + normalizeAikucunPrintersResponse:function(data){ + if (!data || !data.printers || !data.printers.length) { + return false; + } + var printers = []; + var defaultPrinter = ''; + data.printers.each(function(item){ + var name = item.printName ? item.printName : item.name; + if (!name) { + return; + } + printers.push({name: name}); + if (!defaultPrinter && String(item.defaultPrinter) === '1') { + defaultPrinter = name; + } + }); + if (!printers.length) { + return false; + } + if (!defaultPrinter) { + defaultPrinter = printers[0].name; + } + + return { + printers: printers, + defaultPrinter: defaultPrinter, + msg: data.message ? data.message : '' + }; + }, + extractAikucunPushMessage:function(data){ + var push = data.pushBackMessage ? data.pushBackMessage : {}; + if (push && push.length && push[0]) { + return push[0]; + } + return push; + }, + resolveAikucunResponseRequestId:function(data, push){ + if (push && push.requestId) { + return String(push.requestId); + } + if (data.requestId) { + return String(data.requestId); + } + return ''; + }, + buildAikucunResponsePayload:function(data, meta, push, isSuccess){ + var logiNo = (push && push.logisticsNo) ? push.logisticsNo : ''; + var documentID = meta && meta.documentID ? meta.documentID : ((meta && meta.is_preview ? '1_' : '0_') + (logiNo || this.getUUID(8, 16))); + var rsp = { + status: isSuccess ? 'success' : 'fail', + msg: data.message ? data.message : '', + printStatus: [{ + documentID: documentID, + status: isSuccess ? 'success' : 'fail', + detail: data.message ? data.message : '' + }], + taskID: documentID + }; + if (data.previewImage) { + rsp.previewImage = data.previewImage; + } + return rsp; + }, + fireAikucunResultEvent:function(meta, isSuccess, rsp){ + if (meta && meta.is_preview) { + this.fireEvent('preview', rsp); + return; + } + this.fireEvent(isSuccess ? 'printSuccess' : 'printFailure', rsp); + }, + formatData:function(data,is_preview){ + var tasks = []; + data.each(function(printData){ + var jsonPacket = this.parseAikucunJsonPacket(printData.json_packet); + if(!jsonPacket) { + alert('数据结构不完整,\n无法打印'); + return; + } + if (typeof jsonPacket.printData === 'string') { + var printDataObj = JSON.decode(jsonPacket.printData.replace(/“/g, '"')) + } else { + var printDataObj = jsonPacket.printData; + } + if (!printDataObj || typeof printDataObj !== 'object') { + return; + } + var payload = JSON.decode(JSON.encode(printDataObj)); + var reqId = payload.requestId ? String(payload.requestId) : this.getUUID(16, 16); + payload.requestId = reqId; + + var logiNo = printData.batch_logi_no ? printData.batch_logi_no : printData.logi_no; + var docId = logiNo ? logiNo : reqId; + tasks.push({ + documentID:(is_preview ? '1_' : '0_') + docId, + requestId: reqId, + payload: payload, + logisticsNo: logiNo + }); + }.bind(this)); + + return tasks; + }, + handleAikucunPrintResponse:function(data){ + if (!data || data.cmd || (typeof data.code === 'undefined' && typeof data.success === 'undefined')) { + return false; + } + var code = String(data.code); + var isSuccess = (code === '00000') || (code === '200') || (data.success === true); + var push = this.extractAikucunPushMessage(data); + var reqId = this.resolveAikucunResponseRequestId(data, push); + if (reqId && this.aikucunHandledResponseMap[reqId]) { + return true; + } + var meta = reqId && this.aikucunTaskMap[reqId] ? this.aikucunTaskMap[reqId] : null; + var rsp = this.buildAikucunResponsePayload(data, meta, push, isSuccess); + if (reqId && this.aikucunTaskMap[reqId]) { + delete this.aikucunTaskMap[reqId]; + } + if (reqId) { + this.aikucunHandledResponseMap[reqId] = true; + } + this.fireAikucunResultEvent(meta, isSuccess, rsp); + + return true; + }, + getRequestObject:function(cmd){ + var request = new Object(); + request.requestID=this.getUUID(8, 16); + request.cmd=cmd; + request.version="1.0"; + return request; + }, + }); + var WxshipinPrinter = new Class({ Extends: Printer, initialize: function(options){ diff --git a/app/o2o/task.php b/app/o2o/task.php index 7fa98b8e..34ab5f2d 100644 --- a/app/o2o/task.php +++ b/app/o2o/task.php @@ -42,7 +42,7 @@ class o2o_task{ ); $save_dlycorp = $dlyCorpLib->save($o2o_ship_data); - #自动插入线下服务端数据 + //自动插入线下服务端数据 $serverObj = app::get('o2o')->model('server'); $type_list = o2o_conf_server::getTypeList('wap'); diff --git a/app/ome/controller/admin/dly/corp.php b/app/ome/controller/admin/dly/corp.php index a1db77e7..5f1aeafe 100644 --- a/app/ome/controller/admin/dly/corp.php +++ b/app/ome/controller/admin/dly/corp.php @@ -117,7 +117,7 @@ class ome_ctl_admin_dly_corp extends desktop_controller //新版控件打印 $templateObj = app::get("logisticsmanager")->model('express_template'); $templates = $templateObj->getList("template_id,template_name,template_type"); - $normalTmpl = $cainiaoTmpl = $electronTmpl = $kuaishouTmpl = $wphvipTmpl = $huaweiTmpl = $xhsTmpl = $wxshipinTmpl = $meituan4bulkpurchasingTmpl = array(); + $normalTmpl = $cainiaoTmpl = $electronTmpl = $kuaishouTmpl = $wphvipTmpl = $huaweiTmpl = $xhsTmpl = $wxshipinTmpl = $meituan4bulkpurchasingTmpl = $akcTmpl = array(); foreach ($templates as $val) { if ($val['template_type'] == 'normal') { $normalTmpl[] = $val; @@ -139,6 +139,8 @@ class ome_ctl_admin_dly_corp extends desktop_controller $sfTmpl[] = $val; }elseif(in_array($val['template_type'], array('xhs_standard','xhs_user'))){ $xhsTmpl[] = $val; + }elseif(in_array($val['template_type'], array('aikucun_standard','aikucun_user'))){ + $akcTmpl[] = $val; }elseif(in_array($val['template_type'], array('wxshipin_standard','wxshipin_user'))){ $wxshipinTmpl[] = $val; }elseif(in_array($val['template_type'], array('youzan_standard'))){ @@ -161,6 +163,7 @@ class ome_ctl_admin_dly_corp extends desktop_controller $this->pagedata['youzanTmpl'] = $youzanTmpl; $this->pagedata['electronTmpl'] = $electronTmpl; $this->pagedata['xhsTmpl'] = $xhsTmpl; + $this->pagedata['akcTmpl'] = $akcTmpl; $this->pagedata['wxshipinTmpl'] = $wxshipinTmpl; $this->pagedata['dewuTmpl'] = $dewuTmpl; $this->pagedata['meituan4bulkpurchasingTmpl'] = $meituan4bulkpurchasingTmpl; @@ -190,7 +193,7 @@ class ome_ctl_admin_dly_corp extends desktop_controller if ($val['channel_type'] == '360buy') { $channelType[$val['channel_id']] = 'JDCOD'; - } elseif (in_array($val['channel_type'], array('taobao', 'unionpay', 'pinjun', 'pdd','douyin','kuaishou','xhs','wxshipin', 'meituan4bulkpurchasing','dewu')) || ($val['channel_type']=='jdalpha' && in_array($val['logistics_code'], ['JDDJ']))) { + } elseif (in_array($val['channel_type'], array('taobao', 'unionpay', 'pinjun', 'pdd','douyin','kuaishou','xhs','wxshipin', 'meituan4bulkpurchasing','dewu','aikucun')) || ($val['channel_type']=='jdalpha' && in_array($val['logistics_code'], ['JDDJ']))) { $channelType[$val['channel_id']] = $val['logistics_code']; } else { @@ -267,7 +270,7 @@ class ome_ctl_admin_dly_corp extends desktop_controller //新版控件打印 $templateObj = app::get("logisticsmanager")->model('express_template'); $templates = $templateObj->getList("template_id,template_name,template_type"); - $canniaoId = $kuaishouTmpl = $wphvipTmpl = $xhsTmpl = $wxshipinTmpl = array(); + $canniaoId = $kuaishouTmpl = $wphvipTmpl = $xhsTmpl = $wxshipinTmpl = $akcTmpl = array(); foreach ($templates as $val) { if ($val['template_type'] == 'normal') { $normalTmpl[] = $val; @@ -290,6 +293,8 @@ class ome_ctl_admin_dly_corp extends desktop_controller $sfTmpl[] = $val; }elseif(in_array($val['template_type'], array('xhs_standard','xhs_user'))){ $xhsTmpl[] = $val; + }elseif(in_array($val['template_type'], array('aikucun_standard','aikucun_user'))){ + $akcTmpl[] = $val; }elseif(in_array($val['template_type'], array('wxshipin_standard','wxshipin_user'))){ $wxshipinTmpl[] = $val; }elseif(in_array($val['template_type'], array('youzan_standard'))){ @@ -313,6 +318,7 @@ class ome_ctl_admin_dly_corp extends desktop_controller $this->pagedata['electronTmpl'] = $electronTmpl; $this->pagedata['canniaoId'] = $canniaoId; $this->pagedata['xhsTmpl'] = $xhsTmpl; + $this->pagedata['akcTmpl'] = $akcTmpl; $this->pagedata['wxshipinTmpl'] = $wxshipinTmpl; $this->pagedata['youzanTmpl'] = $youzanTmpl; $this->pagedata['meituan4bulkpurchasingTmpl'] = $meituan4bulkpurchasingTmpl; @@ -338,7 +344,7 @@ class ome_ctl_admin_dly_corp extends desktop_controller $channelShop[$val['channel_id']]['name'] = $shopList[$val['shop_id']]; $channelShop[$val['channel_id']]['logistics_code'] = $val['logistics_code']; - if (in_array($val['channel_type'], array('taobao','pdd','unionpay','pinjun','jdalpha','hqepay','douyin','kuaishou','xhs','wxshipin'))) { + if (in_array($val['channel_type'], array('taobao','pdd','unionpay','pinjun','jdalpha','hqepay','douyin','kuaishou','xhs','wxshipin','aikucun'))) { if ($val['logistics_code'] == 'JTSD' && !in_array($val['channel_type'],['wxshipin'])) { $val['logistics_code'] = 'jitu'; } @@ -436,6 +442,8 @@ class ome_ctl_admin_dly_corp extends desktop_controller $dlycorp['prt_tmpl_id'] = $dlycorp['sf_tmpl_id']; } elseif ($dlycorp['electron_type'] == 'xhs') { $dlycorp['prt_tmpl_id'] = $dlycorp['xhs_tmpl_id']; + } elseif ($dlycorp['electron_type'] == 'aikucun') { + $dlycorp['prt_tmpl_id'] = $dlycorp['akc_tmpl_id']; } elseif ($dlycorp['electron_type'] == 'wxshipin') { $dlycorp['prt_tmpl_id'] = $dlycorp['wxshipin_tmpl_id']; } elseif ($dlycorp['electron_type'] == 'meituan4bulkpurchasing') { diff --git a/app/ome/controller/admin/shop.php b/app/ome/controller/admin/shop.php index 8a997fd6..5ef312f7 100644 --- a/app/ome/controller/admin/shop.php +++ b/app/ome/controller/admin/shop.php @@ -592,6 +592,8 @@ class ome_ctl_admin_shop extends desktop_controller { $this->pagedata['ent_email'] = $entEmail; $this->pagedata['is_certified'] = $is_certified; $this->pagedata['need_enterprise_auth'] = $need_enterprise_auth; // 是否需要系统节点注册步骤(openapi 不强制) + // 绑定完成页:订单流量购买入口 + $this->pagedata['order_traffic_purchase_url'] = 'https://open-console.shopex.cn/organization/list'; // 渲染模板 $this->display('admin/shop/bind_guide.html'); diff --git a/app/ome/lib/auth/config.php b/app/ome/lib/auth/config.php index d44bd2d9..b1c0c4d3 100644 --- a/app/ome/lib/auth/config.php +++ b/app/ome/lib/auth/config.php @@ -117,6 +117,17 @@ class ome_auth_config 'node_id' => '节点', ), ), + 'b2b' => + array( + 'label' => 'B2B', + 'desc' => 'B2B平台对接', + 'params' => + array( + 'b2b_url' => 'API地址', + 'b2b_response_secret' => 'RESPONSE SECRET', + 'node_id' => '节点', + ), + ), ); foreach (ome_shop_type::get_shop_type() as $key => $value) { diff --git a/app/ome/lib/autotask/timer/autoconfirmorderstockinc.php b/app/ome/lib/autotask/timer/autoconfirmorderstockinc.php index 37b3af4d..e5ddf8e4 100644 --- a/app/ome/lib/autotask/timer/autoconfirmorderstockinc.php +++ b/app/ome/lib/autotask/timer/autoconfirmorderstockinc.php @@ -28,6 +28,10 @@ class ome_autotask_timer_autoconfirmorderstockinc public function process($params, &$error_msg = '') { + + // 标品Saas线不开启此项功能 + return true; + set_time_limit(0); ignore_user_abort(1); @ini_set('memory_limit', '512M'); diff --git a/app/ome/lib/autotask/timer/hour.php b/app/ome/lib/autotask/timer/hour.php index 580147a9..fb5bf128 100644 --- a/app/ome/lib/autotask/timer/hour.php +++ b/app/ome/lib/autotask/timer/hour.php @@ -60,8 +60,8 @@ class ome_autotask_timer_hour //kernel::single('erpapi_misc_task')->hour(); // 每小时触发:库存增加自动审核订单 - kernel::single('ome_autotask_timer_autoconfirmorderstockinc')->process($params, $error_msg); + //kernel::single('ome_autotask_timer_autoconfirmorderstockinc')->process($params, $error_msg); return true; } -} \ No newline at end of file +} diff --git a/app/ome/lib/event/receive/delivery.php b/app/ome/lib/event/receive/delivery.php index b43dd0bd..71d18053 100644 --- a/app/ome/lib/event/receive/delivery.php +++ b/app/ome/lib/event/receive/delivery.php @@ -1004,13 +1004,6 @@ class ome_event_receive_delivery extends ome_event_response $service->after_consign($this->__currDlyId); } } - - // 订单发货完成后,service扩展触发其他服务 - foreach(kernel::servicelist('ome.service.order.finish.after') as $service) { - if(method_exists($service, 'after_order_finish')) { - $service->after_order_finish($orderIds); - } - } } //自动开蓝票处理 diff --git a/app/ome/lib/order.php b/app/ome/lib/order.php index 2442914e..151fb18d 100644 --- a/app/ome/lib/order.php +++ b/app/ome/lib/order.php @@ -33,8 +33,7 @@ class ome_order { $instance = kernel::service('service.order'); return $instance->update_iframe($order_id,$is_request,$ext); } - - + /** * 更新订单同步状态 * @access public @@ -83,7 +82,7 @@ class ome_order { if (empty($oid)) return NULL; if ($this->order_is_exists($oid,$node_id)){ - return $oid;#子订单与订单号相同,直接返回 + return $oid; //子订单与订单号相同,直接返回 } $objModel = app::get('ome')->model('order_objects'); @@ -234,8 +233,8 @@ class ome_order { $orderItemMdl = app::get('ome')->model('order_items'); $branchMdl = app::get('ome')->model('branch'); $branchProductMdl = app::get('ome')->model('branch_product'); - - + + // order $order = $orderMdl->db_dump($order_id, 'auto_status,abnormal_status'); if (!$order) return array(false,'订单不存在'); diff --git a/app/ome/lib/order/import.php b/app/ome/lib/order/import.php index 3ecaf2ee..26b786ea 100644 --- a/app/ome/lib/order/import.php +++ b/app/ome/lib/order/import.php @@ -374,6 +374,8 @@ class ome_order_import implements omecsv_data_split_interface $orderSdf['consignee']['mobile'] = trim($orderSdf['consignee']['mobile']); $orderSdf['shipping']['is_cod'] = $is_code; $orderSdf['shipping']['cost_shipping'] = $orderSdf['shipping']['cost_shipping'] ? $orderSdf['shipping']['cost_shipping'] : '0'; + $orderSdf['shipping']['cost_shipping'] = (float)$orderSdf['shipping']['cost_shipping']; + $orderSdf['is_tax'] = $is_tax; $orderSdf['cost_tax'] = $orderSdf['cost_tax'] ? $orderSdf['cost_tax'] : '0'; $orderSdf['discount'] = $orderSdf['discount'] ? $orderSdf['discount'] : '0'; diff --git a/app/ome/lib/order/importV2.php b/app/ome/lib/order/importV2.php index b003b82f..5014a8ff 100644 --- a/app/ome/lib/order/importV2.php +++ b/app/ome/lib/order/importV2.php @@ -696,6 +696,8 @@ class ome_order_importV2 implements omecsv_data_split_interface $orderSdf['consignee']['mobile'] = trim($orderSdf['ship_mobile']); $orderSdf['shipping'] = []; $orderSdf['shipping']['cost_shipping'] = $orderSdf['cost_freight'] ? $orderSdf['cost_freight'] : '0'; + $orderSdf['shipping']['cost_shipping'] = (float)$orderSdf['shipping']['cost_shipping']; + $orderSdf['shipping']['is_cod'] = $is_code; $orderSdf['is_tax'] = $is_tax; $orderSdf['cost_tax'] = $orderSdf['invoice_amount'] ? $orderSdf['invoice_amount'] : '0'; diff --git a/app/ome/lib/print/tmpl/express.php b/app/ome/lib/print/tmpl/express.php index 33d4aea0..e79a090f 100644 --- a/app/ome/lib/print/tmpl/express.php +++ b/app/ome/lib/print/tmpl/express.php @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - class ome_print_tmpl_express{ public $smarty = null; @@ -24,7 +23,7 @@ class ome_print_tmpl_express{ static $logi_list = array('amazon','dangdang');//需要根据物流公司自定义快递单输入信息列表 /** - * + * * @param String $logi * @param Object $controller * @return ome_print_tmpl_express @@ -105,6 +104,10 @@ class ome_print_tmpl_express{ $this->smarty->singlepage("admin/delivery/express_xhs.html", 'wms'); + }elseif(in_array($template_type, array('aikucun_standard','aikucun_user'))) { + + $this->smarty->singlepage("admin/delivery/express_aikucun.html", 'wms'); + }elseif(in_array($template_type, array('wxshipin_standard','wxshipin_user'))) { $this->smarty->singlepage("admin/delivery/express_wxshipin.html", 'wms'); @@ -163,11 +166,6 @@ class ome_print_tmpl_express{ return $brower; } - /** - * 获取ExpressTpl - * @param mixed $corp corp - * @return mixed 返回结果 - */ public function getExpressTpl($corp) { $prtTmplId = $corp['prt_tmpl_id']; $templateObj = app::get("logisticsmanager")->model('express_template'); @@ -182,7 +180,7 @@ class ome_print_tmpl_express{ $printTmpl['template_select'] = json_encode(unserialize($printTmpl['template_select'])); } $this->printTpl = $printTmpl; - if(in_array($printTmpl['template_type'], array('cainiao', 'cainiao_standard', 'cainiao_user','pdd_standard','pdd_user','jd_standard','jd_user', 'douyin_standard', 'douyin_user','kuaishou_standard','kuaishou_user','sf','xhs_standard','xhs_user','meituan4bulkpurchasing_user','youzan_standard'))) { + if(in_array($printTmpl['template_type'], array('cainiao', 'cainiao_standard', 'cainiao_user','pdd_standard','pdd_user','jd_standard','jd_user', 'douyin_standard', 'douyin_user','kuaishou_standard','kuaishou_user','sf','xhs_standard','xhs_user','aikucun_standard','aikucun_user','meituan4bulkpurchasing_user','youzan_standard'))) { $rs = $this->_dealUnShopexWidgetField($corp['channel_id']); if(!$rs) { return false; @@ -352,6 +350,11 @@ class ome_print_tmpl_express{ // 获取自定义模板url和自定义模板内容 $this->_xhs_custom(); break; + case 'aikucun_standard': + case 'aikucun_user': + $this->printField = array('batch_logi_no','logi_no','print_config','channel_id','delivery_id','json_packet','user_id'); + $this->_xhs_custom(); + break; default : break; } return true; @@ -424,4 +427,4 @@ class ome_print_tmpl_express{ $this->printField = $field; } -} \ No newline at end of file +} diff --git a/app/ome/model/reship.php b/app/ome/model/reship.php index 573ccf05..95ee37d9 100644 --- a/app/ome/model/reship.php +++ b/app/ome/model/reship.php @@ -1168,6 +1168,39 @@ class ome_mdl_reship extends dbeav_model{ $order_sdf['mark_text'] = $mark_text; $tostr=array(); list($actually_amount, $settlement_amount) = $this->getActuallyAmount($reshipinfo['reship_id']); + // 按各行 sale_price(num*price)均摊实付与结算金额,与 ome_order::calculate_part_porth 一致 + $orderLib = kernel::single('ome_order'); + $divideRows = array(); + foreach ($reship_items as $objKey => $row) { + $divideRows[$objKey] = array( + 'sale_price' => bcmul(strval($row['num']), strval($row['price']), 10), + ); + } + $porth_total = '0'; + foreach ($divideRows as $r) { + if (floatval($r['sale_price']) > 0) { + $porth_total = bcadd($porth_total, $r['sale_price'], 10); + } + } + if (floatval($porth_total) > 0) { + $divideRows = $orderLib->calculate_part_porth($divideRows, array( + 'part_total' => $actually_amount, + 'part_field' => 'actually_amount', + 'porth_field' => 'sale_price', + 'minuend_field' => null, + )); + $divideRows = $orderLib->calculate_part_porth($divideRows, array( + 'part_total' => $settlement_amount, + 'part_field' => 'settlement_amount', + 'porth_field' => 'sale_price', + 'minuend_field' => null, + )); + } else { + foreach ($divideRows as $k => $_) { + $divideRows[$k]['actually_amount'] = '0.00'; + $divideRows[$k]['settlement_amount'] = '0.00'; + } + } //[销售物料层]格式化订单明细 $item_cost = 0; foreach ( $reship_items as $objKey => &$items ) @@ -1185,8 +1218,8 @@ class ome_mdl_reship extends dbeav_model{ $items['name'] = $items['product_name']; $items['quantity'] = $items['num']; $items['amount'] = $items['sale_price'] = $items['num'] * $items['price']; - $items['actually_amount'] = $actually_amount; - $items['settlement_amount'] = $settlement_amount; + $items['actually_amount'] = $divideRows[$objKey]['actually_amount']; + $items['settlement_amount'] = $divideRows[$objKey]['settlement_amount']; if($order_sdf['order_type'] == 'platform') { $items['is_sh_ship'] = 'true'; } diff --git a/app/ome/view/admin/order/order_edit.html b/app/ome/view/admin/order/order_edit.html index ba861687..4de785bd 100644 --- a/app/ome/view/admin/order/order_edit.html +++ b/app/ome/view/admin/order/order_edit.html @@ -226,7 +226,6 @@ <{/capture}> - \ No newline at end of file + diff --git a/app/wms/view/admin/delivery/express_aikucun.html b/app/wms/view/admin/delivery/express_aikucun.html new file mode 100644 index 00000000..525411ec --- /dev/null +++ b/app/wms/view/admin/delivery/express_aikucun.html @@ -0,0 +1,105 @@ +<{capture name="header"}> + +<{/capture}> + +<{ if $err=='false' }> +
+ + +
+ + + + +
+

<{$logi_name}> 打印 <{$count}> 份快递单

+ <{if $extend_message}> +

<{$extend_message}>

+ <{/if}> + +
+
+ <{ if $delibery_bill_flag }> + <{button label="打印快递单" id="onlyprint_btn" type="button" class="btn btn-primary"}>     + <{ else }> + <{button label="打印快递单" id="doprint_btn" class="btn-primary" }>     + <{ /if }> + <{button label="打印预览" id="preview_btn" class="btn-primary" style="display:none" }>     + +
+ +
+ +
+
+
+
+
+
+
+ + <{include file="admin/delivery/include/template_aikucun.html" app="wms"}> +<{ /if }> + diff --git a/app/wms/view/admin/delivery/include/template_aikucun.html b/app/wms/view/admin/delivery/include/template_aikucun.html new file mode 100644 index 00000000..1ff70255 --- /dev/null +++ b/app/wms/view/admin/delivery/include/template_aikucun.html @@ -0,0 +1,194 @@ + + + + +