diff --git a/doc/source/const/class.AfterSaleConst.php b/doc/source/const/class.AfterSaleConst.php new file mode 100644 index 00000000..ae3f1478 --- /dev/null +++ b/doc/source/const/class.AfterSaleConst.php @@ -0,0 +1,288 @@ + self::aftersaleStatusAfterSaleAudit, + self::tabWaitProcessedDeliveredAndOnlyRefund => self::aftersaleStatusAfterSaleAudit, + self::tabWaitProcessReturnGoods => self::aftersaleStatusAfterSaleAudit, + self::tabWaitSellerReceivingGoods => self::aftersaleStatusReturnReceive, + self::tabWaitSellerExchangeAudit => self::aftersaleStatusAfterSaleAudit, + self::tabWaitSellerResendAudit => self::aftersaleStatusAfterSaleAudit, + self::tabAll => '', + ]; + } + + public static function getTabTypeAndAftersaleTypeMap() { + return [ + self::tabWaitProcessRefund => self::aftersaleTypeRefundOnlyBeforeSale, + self::tabWaitProcessedDeliveredAndOnlyRefund => self::aftersaleTypeAfterSaleOnlyRefund, + self::tabWaitProcessReturnGoods => self::aftersaleTypeReturnGoodsAndRefund, + self::tabPriceProtection => self::aftersaleTypePriceProtection, + self::tabWaitSellerExchangeAudit => self::aftersaleTypeExchangeGoods, + self::tabWaitSellerResendAudit => self::aftersaleTypeResend, + self::tabWaitSellerReceivingGoods => '', + self::tabAll => '', + ]; + } + + public static function getTabTypeAndRefundTypeMap() { + return [ + self::tabFastRefund => self::refundTypeFastRefund, + ]; + } + + public static function getAftersaleTypeMap() { + return [ + self::aftersaleTypeReturnGoodsAndRefund => '退货退款', + self::aftersaleTypeAfterSaleOnlyRefund => '已发货仅退款', + self::aftersaleTypeRefundOnlyBeforeSale => '未发货仅退款', + self::aftersaleTypeExchangeGoods => '换货', + self::aftersaleTypePriceProtection => '价保', + self::aftersaleTypeResend => '补寄', + ]; + } + + public static function getAftersaleStatusMap() { + return [ + self::aftersaleStatusPreSaleAllAudit => '发货前退款待处理', + self::aftersaleStatusRefundAudit => '发货后仅退款待处理', + self::aftersaleStatusReturnAudit => '退货待处理', + self::aftersaleStatusExchangeAudit => '换货待处理', + self::aftersaleStatusWaitBuyerReturnGoods => '待买家退货', + self::aftersaleStatusAfterSaleAudit => '待商家处理', + self::aftersaleStatusReturnReceive => '待商家收货', + self::aftersaleStatusAuditRefunding => '同意退款,退款中', + self::aftersaleStatusRefundSuccess => '同意退款,退款成功', + self::aftersaleStatusClose => '售后关闭', + self::aftersaleStatusReturnShip => '待买家收货', + self::aftersaleStatusWaitBuyerReceive => '换货成功', + self::aftersaleStatusExchangeSuccess => '换货成功', + self::aftersaleStatusRefuse => '拒绝售后', + self::aftersaleStatusReceiveRefuse => '退货后拒绝退款', + self::aftersaleStatusUploadRefund => '待商家上传退款凭证', + self::aftersaleStatusRefuseAfterSaleApply => '拒绝售后申请', + self::aftersaleStatusSellerRefuseToReturnGoodsAfter => '退货后商家拒绝', + self::aftersaleStatusWaitSellerSendGoods => '补寄待商家发货', + ]; + } + + public static function getSellerRefuseReceiveReturnGoodsCommentMap() { + return [ + 1 => '未收到货(未填写退货单号)', + 2 => '退货与原订单不符(商品不符、退货地址不符)', + 3 => '退回商品影响二次销售/订单超出售后时效(订单完成超7天)', + 4 => '买家误操作/取消申请', + 5 => '已与买家协商补偿,包括差价、赠品、额外补偿', + 6 => '已与买家协商补发商品/已与买家协商换货', + ]; + } + + public static function getSellerRefuseReturnGoodsApplyCommentMap() { + return [ + 1 => '未收到货(未填写退货单号)', + 2 => '退货与原订单不符(商品不符、退货地址不符)', + 3 => '退回商品影响二次销售, 订单超出售后时效(订单完成超7天)', + 4 => '买家误操作/取消申请', + 5 => '已与买家协商补偿,包括差价、赠品、额外补偿', + 6 => '已与买家协商补发商品, 已与买家协商换货', + ]; + } + + public static function getSellerRefuseExchangeApplyCommentMap() { + return [ + 1 => '买家误操作/取消申请', + 2 => '已与买家协商补偿,包括差价、赠品、额外补偿', + 3 => '已与买家协商补发商品', + 4 => '已与买家协商换货', + 5 => '运费未协商—致', + 6 => '商品没问题,买家未举证或举证无效', + 7 => '已在约定时间发货', + 8 => '发票没问题,买家未举证', + 9 => '发票已补寄', + 10 => '买家发票信息不完整', + 11 => '申请时间已超7天无理由退换货时间', + ]; + } + + public static function getSellerRefuseExchangeConfirmCommentMap() { + return [ + 1 => '买家上传的单号有误,商家尚未收到货,请核实正确物流单号后重新上传', + 2 => '退货与原订单不符(商品不符、退货地址不符)', + 3 => '退回商品影响二次销售', + 4 => '运费未协商一致', + ]; + } + + public static function getSellerRefuseAfterDeliveryAndOnlyRefundApplyCommentMap() { + return [ + self::commentTypeNoReceived => [ + self::aftersaleStatusAfterSaleAudit => [ + OrderConst::orderTypeRealGoods => [ + 1 => '商品退回后才能退款', + 2 => '买家已签收', + 3 => '买家误操作/取消申请', + 4 => '问题已解决,待用户收货', + ], + OrderConst::orderTypeGeneralVirtual => [ + 14 => '买家误操作/取消申请', + 15 => '协商一致,用户取消退款', + ], + ], + ], + self::commentTypeReceived => [ + self::aftersaleStatusAfterSaleAudit => [ + OrderConst::orderTypeRealGoods => [ + 5 => '商品退回后才能退款', + 6 => '买家误操作/取消申请', + 7 => '协商一致,用户取消退款', + 8 => '已与买家协商补偿,包括差价、赠品、额外补偿', + 9 => '已与买家协商补发商品', + 10 => '已与买家协商换货', + ], + OrderConst::orderTypeGeneralVirtual => [ + 16 => '买家误操作/取消申请', + 17 => '协商一致,用户取消退款', + 18 => '商品影响二次销售', + 19 => '定制商品不支持七天无理由退货,定制商品不接受质量问题以外的退货', + ], + ], + self::aftersaleStatusReturnReceive => [ + OrderConst::orderTypeRealGoods => [ + 11 => '未收到货/退货单号有误', + 12 => '退货与原订单不符(商品不符、退货地址不符)', + 13 => '退回商品影响二次销售', + 20 => '定制商品不支持七天无理由退货,定制商品不接受质量问题以外的退货', + ], + ], + ], + ]; + } + + public static function getWaitShopProcessAftersaleStatus() { + return [ + self::aftersaleStatusPreSaleAllAudit, + self::aftersaleStatusRefundAudit, + self::aftersaleStatusReturnAudit, + self::aftersaleStatusExchangeAudit, + self::aftersaleStatusWaitBuyerReturnGoods, + self::aftersaleStatusAfterSaleAudit, + self::aftersaleStatusReturnReceive, + ]; + } + + public static function getAfterSaleCloseOrCancelStatusList() { + return [ + self::aftersaleStatusClose, + self::aftersaleStatusRefuseAfterSaleApply, + ]; + } + + public static function getIsPurchaseFilterAndTextMap() { + return [ + 1 => '已采购', + 2 => '未采购', + ]; + } + + public static function getOrderSortTypeMap() { + return array( + 'orderApplyTimeDesc' => '按申请时间↓', + 'orderApplyTimeAsc' => '按申请时间↑', + 'orderUserAsc' => '按收件人排序', + ); + } + + public static function getIsPrintFilterAndTextMap() { + return [ + OrderPrintConst::pExpressStatusPrinted => '已打印', + OrderPrintConst::pExpressStatusNoPrinted => '未打印', +// OrderPrintConst::pExpressRecycled => '已回收', + ]; + } +} \ No newline at end of file diff --git a/doc/source/const/class.AppConst.php b/doc/source/const/class.AppConst.php new file mode 100644 index 00000000..a69d91b4 --- /dev/null +++ b/doc/source/const/class.AppConst.php @@ -0,0 +1,12 @@ + self::jd, + '顺丰速运' => self::shunfeng, + '中通快递' => self::zhongtong, + '韵达速递' => self::yunda, + '圆通速递' => self::yuantong, + '百世汇通' => self::huitongkuaidi, + '申通快递' => self::shentong, + '德邦物流' => self::debangwuliu, + '德邦快运' => self::debangkuaiyun, + '邮政国内小包' => self::youzhengguonei, + 'EMS' => self::ems, + '天天快递' => self::tiantian, + '优速物流' => self::youshuwuliu, + '宅急送' => self::zhaijisong, + '芝麻开门' => self::zhimakaimen, + '国通快递' => self::guotongkuaidi, + '品骏快递' => self::pjbest, + '全峰快递' => self::quanfengkuaidi, + '百事亨通' => self::bsht, + '安能物流' => self::annengwuliu, + '九曳供应链' => self::jiuyescm, + '南方传媒物流' => self::ndwl, + '中通(带电话)' => self::zhongtongphone, + '京广速递' => self::jinguangsudikuaijian, + '当当' => self::dangdangorder, + '运通中港快递' => self::ytkd, + '万象物流' => self::wanxiangwuliu, + '快捷快递' => self::kuaijiesudi, + '速尔快递' => self::suer, + '苏宁物流' => self::suning, + '微特派' => self::weitepai, + '加运美速递' => self::jym56, + '佳怡物流' => self::jiayiwuliu, + '如风达' => self::rufengda, + '中邮速递' => self::wondersyd, + '增益速递' => self::zengyisudi, + '跨越速运' => self::kuayue, + '特急送' => self::lntjs, + '百世物流' => self::baishiwuliu, + '中通快运' => self::zhongtongkuaiyun, + '圆通快运' => self::yuantongkuaiyun, + '日日顺物流' => self::rrs, + '安鲜达' => self::exfresh, + '丹鸟' => self::danniao, + 'D速快递' => self::dsukuaidi, + '当当物流' => self::dangdang, + '极兔速递' => self::jtexpress, + '安迅物流' => self::anxl, + '韵达快运' => self::yundakuaiyun, + '东风快递' => self::dfkuaidi, + '众邮快递' => self::zhongyouex, + '丰网速运' => self::fengwang, + '顺丰快运' => self::shunfengkuaiyun, + '安得物流' => self::annto, + '海信物流' => self::savor, + '黄马甲' => self::huangmajia, + '加运美' => self::jiayunmeiwuliu, + '山西建华' => self::shanxijianhua, + '盛丰物流' => self::sfwl, + '盛辉物流' => self::shenghuiwuliu, + '顺心捷达' => self::sxjdfreight, + '速必达' => self::subida, + '泰进物流' => self::taijin, + '天地华宇' => self::tiandihuayu, + '信丰物流' => self::xinfengwuliu, + '信天翁同城速配' => self::xintianweng, + '壹米滴答' => self::yimidida, + '紫乐工贸' => self::zilegongmao, + '中铁快运' => self::ztky, + '邮政国内' => self::yzguonei, + ]; + } + + public static function getDdLogisticsIdAndCompanyCodeMap() { + return [ + self::jd => 30, + self::shunfeng => 12, + self::zhongtong => 15, + self::yunda => 9, + self::yuantong => 7, + self::huitongkuaidi => 20, + self::shentong => 8, + self::debangwuliu => 13, + self::youzhengguonei => 19, + self::ems => 17, + self::tiantian => 14, + self::youshuwuliu => 11, + self::zhaijisong => 21, + self::zhimakaimen => 440, + self::guotongkuaidi => 25, + self::pjbest => 447, + self::quanfengkuaidi => 16, + self::bsht => 221, + self::annengwuliu => 32, + self::jiuyescm => 191, + self::ndwl => 317, + self::zhongtongphone => 424, + self::jinguangsudikuaijian => 517, + self::dangdangorder => 192, + self::ytkd => 321, + self::wanxiangwuliu => 31, + self::kuaijiesudi => 26, + self::suer => 243, + self::suning => 202, + self::weitepai => 18, + self::jym56 => 158, + self::jiayiwuliu => 10, + self::rufengda => 22, + self::wondersyd => 151, + self::zengyisudi => 23, + self::kuayue => 397, + self::lntjs => 289, + self::baishiwuliu => 637, + self::zhongtongkuaiyun => 846, + self::yuantongkuaiyun => 909, + self::rrs => 641, + self::exfresh => 284, + self::danniao => 1017, + self::dsukuaidi => 1018, + self::dangdang => 1016, + self::jtexpress => 1021, + self::anxl => 631, + self::yundakuaiyun => 952, + self::dfkuaidi => 1019, + self::zhongyouex => 1022, + self::fengwang => 1033, + self::savor => 1025, + self::huangmajia => 37, + self::jiayunmeiwuliu => 327, + self::shanxijianhua => 1037, + self::sfwl => 1026, + self::shenghuiwuliu => 244, + self::sxjdfreight => 1024, + self::shunfengkuaiyun => 1035, + self::subida => 716, + self::taijin => 1032, + self::tiandihuayu => 518, + self::xinfengwuliu => 36, + self::xintianweng => 1039, + self::yimidida => 897, + self::ztky => 140, + self::zilegongmao => 1038, + self::yzguonei => 854, + ]; + } + + public static function getDdCompanyIdAndCompanyInfoMap() { + $jsonStr = << 90, + self::tagTradeSuccess => 99, + self::tagTradeLogisticsChanged => 95, + self::tagTradeAddressChanged => 90, + self::tagTradeCanceled => 90, + self::tagTradePartlySellerShip => 90, + self::tagTradeAmountChanged => 90, + self::tagTradePending => 95, + self::tagTradeAddressChangeApplied => 90, + self::tagTradeAppointment => 95, + self::tagTradeMemoModify => 90, + self::tagTradeLogisticsOrderTagPush => 90, + ]; + } + + const tagRefundArbitrateApplied = 212;//买家发起客服仲裁消息 + const tagRefundArbitrateAudited = 216;//客服仲裁结果消息 + const tagRefundArbitrateCancelled = 215;//买家取消仲裁消息 + const tagRefundArbitrateSubmited = 214;//商家上传仲裁凭证消息 + const tagRefundArbitrateSubmiting = 213;//客服要求商家上传凭证消息 + const tagRefundBuyerReturnGoods = 203;//买家退货给卖家消息 + const tagRefundExchangeComfirmed = 211;//确认收货并二次发货成功 + const tagRefundExpirationChange = 209;//售后超时时长变更消息 + const tagRefundRefundAgreed = 201;//同意退款消息 + const tagRefundRefundClosed = 207;//售后关闭消息 + const tagRefundRefundCreated = 200;//买家发起售后申请消息 + const tagRefundRefundModified = 208;//买家修改售后申请消息 + const tagRefundRefundRefused = 204;//拒绝退款消息 + const tagRefundRefundSuccess = 206;//退款成功消息 + const tagRefundReturnApplyAgreed = 202;//同意退货申请消息 + const tagRefundReturnApplyRefused = 205;//拒绝退货申请消息 + const tagRefundReturnSpecialRefund = 224;//特殊权益售后消息 + const tagRefundReturnSpecialRefundSuccess = 225;//特殊权益售后退款成功消息 + const tagRefundResendConfirmed = 226;//补寄单商家补寄消息 + const tagRefundResendAgree = 227;//商家同意补寄消息 + + public static function getAllAftersaleTags() { + return [ + self::tagRefundArbitrateApplied, + self::tagRefundArbitrateAudited, + self::tagRefundArbitrateCancelled, + self::tagRefundArbitrateSubmited, + self::tagRefundArbitrateSubmiting, + self::tagRefundBuyerReturnGoods, + self::tagRefundExchangeComfirmed, + self::tagRefundExpirationChange, + self::tagRefundRefundAgreed, + self::tagRefundRefundClosed, + self::tagRefundRefundCreated, + self::tagRefundRefundModified, + self::tagRefundRefundRefused, + self::tagRefundRefundSuccess, + self::tagRefundReturnApplyAgreed, + self::tagRefundReturnApplyRefused, + self::tagRefundReturnSpecialRefund, + self::tagRefundReturnSpecialRefundSuccess, + self::tagRefundResendConfirmed, + self::tagRefundResendAgree, + ]; + } + + const spiCodeSuccess = 0;//业务处理成功 + const spiCodeCheckSignFail = 100001;//验签失败 + const spiCodeParamError = 100002;// 参数错误 + const spiCodeSystemError = 100003;//系统错误 + const spiCodeChangeFail = 200023;//系统异常,地址修改失败建议联系商家修改 + const spiCodeOrderAlreadyDelivery = 200015;//订单已经发货无法修改地址 + const spiCodeOrderFinish = 200021;//订单已经签收无法修改地址 + const spiCodeOrderNotExist = 200022;//订单不存在,请稍后重试 + const spiCodeOrderInAfterSale = 200002;//订单进入审单不支持改地址 + + public static function getSpiCodeMap() { + return [ + self::spiCodeSuccess => '业务处理成功', + self::spiCodeCheckSignFail => '验签失败', + self::spiCodeParamError => '参数错误', + self::spiCodeSystemError => '系统错误', + self::spiCodeOrderAlreadyDelivery => '订单已经发货无法修改地址', + self::spiCodeOrderFinish => '订单已经签收无法修改地址', + self::spiCodeOrderNotExist => '订单不存在,请稍后重试', + self::spiCodeOrderInAfterSale => '订单进入审单不支持改地址', + self::spiCodeChangeFail => '系统异常,地址修改失败建议联系商家修改', + ]; + } + + public static function getSpiSkuChangeCodeAndTextMap() { + return [ + self::spiCodeSuccess => '业务处理成功', + self::spiCodeCheckSignFail => '验签失败', + self::spiCodeParamError => '参数错误', + self::spiCodeSystemError => '系统错误', + self::spiCodeOrderAlreadyDelivery => '订单已经发货不支持修改sku', + self::spiCodeOrderFinish => '订单已经签收不支持修改sku', + self::spiCodeOrderNotExist => '订单不存在,请稍后重试', + self::spiCodeOrderInAfterSale => '订单进入审单不支持改sku', + ]; + } + + public static function getSpiCodeByOrderStatus($orderStatus) { + if (empty($orderStatus)) { + return self::spiCodeParamError; + } + + $orderStatusAndSpiCodeMap = [ + OrderConst::orderStatusWaitBuyerConfirmGoods => self::spiCodeOrderAlreadyDelivery,//发货 + OrderConst::orderStatusPartDelivery => self::spiCodeOrderAlreadyDelivery,//部分发货 + OrderConst::orderStatusFinish => self::spiCodeOrderFinish,//订单结束 + ]; + + return $orderStatusAndSpiCodeMap[$orderStatus] ?: self::spiCodeChangeFail; + } + + /** + * 代打代发:商家修改备注消息 + */ + const tagIopTradeUpdateRemark = 500; + + /** + * 代打代发:商家订单分配消息 + */ + const tagIopTradeDistribution = 501; + + /** + * 代打代发:商家取消分配订单消息 + */ + const tagIopTradeDistributionCancel = 503; + + /** + * 代打代发:修改收件人信息消息 + */ + const tagIopTradeUpdateReceiver = 504; + + /** + * 代打代发:代打运单回传状态变更消息 + */ + const tagIopTradeStatusReturn = 505; + + public static function getAllIopTradeTags() { + return [ + self::tagIopTradeUpdateRemark, + self::tagIopTradeDistribution, + self::tagIopTradeDistributionCancel, + self::tagIopTradeUpdateReceiver, + self::tagIopTradeStatusReturn, + ]; + } + +} \ No newline at end of file diff --git a/doc/source/const/class.DsAppTool.php b/doc/source/const/class.DsAppTool.php new file mode 100644 index 00000000..e0806773 --- /dev/null +++ b/doc/source/const/class.DsAppTool.php @@ -0,0 +1,46 @@ +立即授权', DsConst::getDsAppChineseName(), $memberAuthUrl); + } + + if (stripos($reason, '已下架') !== false) { + $newReason = '1688商品已下架,请更换货源后采购'; + } + + if (stripos($reason, '已删除') !== false) { + $newReason = '1688商品已删除,请更换货源后采购'; + } + + return $newReason; + } + + + public static function rebuildCheckDsAppAuthExpireRet($ret, $loginUserId) { + $ret['loginUserId'] = $loginUserId; + $memberAuthUrl = $ret['memberAuthUrl']; + + foreach ($ret['userIdAndCheckRetMap'] as $userId => &$checkRet) { + if (CommonTool::isSuccessRet($checkRet)) { + continue; + } + if ($checkRet['code'] == DsConst::authExpireTypeOrderExpire) { + $checkRet['solution'] = sprintf('1688%s已过期,为了避免影响正常发货和使用,请重新订购', DsConst::getDsAppChineseName(), DsConst::getDsAppServiceMarketUrl()); + $checkRet['tip'] = sprintf('1688%s订购过期,为了避免影响正常发货和使用,请先去订购', DsConst::getDsAppChineseName(), DsConst::getDsAppServiceMarketUrl()); + } elseif ($checkRet['code'] == DsConst::authExpireTypeAuthExpire) { + $checkRet['solution'] = sprintf('1688%s授权失效,为了避免影响正常发货和使用,请重新授权', DsConst::getDsAppChineseName(), $memberAuthUrl); + $checkRet['tip'] = sprintf('1688%s授权失效,为了避免影响正常发货和使用,请重新授权', DsConst::getDsAppChineseName(), $memberAuthUrl); + } else { + $checkRet['solution'] = $checkRet['reason']; + } + } + unset($checkRet); + + return $ret; + } +} \ No newline at end of file diff --git a/doc/source/const/class.DsMessageConst.php b/doc/source/const/class.DsMessageConst.php new file mode 100644 index 00000000..6604fc83 --- /dev/null +++ b/doc/source/const/class.DsMessageConst.php @@ -0,0 +1,16 @@ + [ + OrderConst::orderStatusWaitSellerSendGoods, + OrderConst::orderStatusPartDelivery, + ], + self::orderStatusWaitSellerSendGoods => [ + OrderConst::orderStatusWaitSellerSendGoods, + OrderConst::orderStatusPartDelivery, + ], + self::orderStatusWaitBuyerConfirmGoods => [OrderConst::orderStatusWaitBuyerConfirmGoods], + self::orderStatusFinish => [OrderConst::orderStatusFinish], + self::orderStatusClose => OrderConst::getPurchaseOrderTabCanceledAllOrderStatus(), + ]; + } + + public static function getDdOrderStatusByPlatformOrderStatus($appOrderStatus) { + if (empty($appOrderStatus)) { + return []; + } + $platformOrderStatusAndDdOrderStatusMap = self::getDdOrderStatusAndPlatformOrderStatusMap(); + + $appOrderStatusArr = is_array($appOrderStatus) ? $appOrderStatus : [$appOrderStatus]; + $ddOrderStatusArr = $ddAfterSaleStatusArr = []; + if (in_array('all', $appOrderStatusArr)) { + return $ddOrderStatusArr; + } + foreach ($appOrderStatusArr as $tmpAppOrderStatus) { + if ($tmpAppOrderStatus == self::orderStatusRefunding) { + $ddAfterSaleStatusArr = self::getAppOrderStatusRefundingAfterSaleOrderStatus(); + } + if (!isset($platformOrderStatusAndDdOrderStatusMap[$tmpAppOrderStatus])) { + continue; + } + $ddOrderStatusArr = array_merge($ddOrderStatusArr, $platformOrderStatusAndDdOrderStatusMap[$tmpAppOrderStatus]); + } + + return [$ddOrderStatusArr, $ddAfterSaleStatusArr]; + } + + public static function getAppOrderStatusByOrderStatus($orderStatus) { + $map = self::getDdOrderStatusAndPlatformOrderStatusMap(); + + $returnAppOrderStatus = null; + foreach ($map as $appOrderStatus => $orderStatusArr) { + if (!in_array($orderStatus, $orderStatusArr)) { + continue; + } + $returnAppOrderStatus = $appOrderStatus; + } + + return $returnAppOrderStatus; + } + + public static function getDsRefundStatusName($refundStatus) { + $map = [ + self::refundStatusRefunding => '售后中', + self::refundStatusClose => '售后关闭', + self::refundStatusFinish => '售后完成', + ]; + + return $map[$refundStatus] ?: null; + } + + public static function getAppOrderStatusRefundingAfterSaleOrderStatus() { + return [ + AfterSaleConst::aftersaleStatusAfterSaleAudit, + AfterSaleConst::aftersaleStatusWaitBuyerReturnGoods, + AfterSaleConst::aftersaleStatusAuditRefunding, + AfterSaleConst::aftersaleStatusPreSaleAllAudit, + AfterSaleConst::aftersaleStatusRefundAudit, + AfterSaleConst::aftersaleStatusReturnAudit, + AfterSaleConst::aftersaleStatusExchangeAudit, + AfterSaleConst::aftersaleStatusWaitSellerSendGoods, + AfterSaleConst::aftersaleStatusReturnReceive, + AfterSaleConst::aftersaleStatusReturnShip, + ]; + } + + public static function getActionTypeAndNameMap () { + return [ + self::autoAfsActionTypeWaitSendRefund => '1688订单申请退款', + self::autoAfsActionTypeCloseOrder => '关闭1688订单', + self::autoAfsActionTypeException => '自动售后异常', + ]; + } + + public static function getActionTypeName($actionType) { + $actionTypeAndNameMap = self::getActionTypeAndNameMap(); + return $actionTypeAndNameMap[$actionType] ?: ''; + } +} \ No newline at end of file diff --git a/doc/source/const/class.FrequencyConst.php b/doc/source/const/class.FrequencyConst.php new file mode 100644 index 00000000..c7397efe --- /dev/null +++ b/doc/source/const/class.FrequencyConst.php @@ -0,0 +1,24 @@ + 10, + 'purchase' => 30, + ]; + } + +} \ No newline at end of file diff --git a/doc/source/const/class.OrderChildTagConst.php b/doc/source/const/class.OrderChildTagConst.php new file mode 100644 index 00000000..0b1a6e4c --- /dev/null +++ b/doc/source/const/class.OrderChildTagConst.php @@ -0,0 +1,16 @@ + '精选联盟', + self::cBizValueShopSelf => '小店自卖', + ]; + } +} \ No newline at end of file diff --git a/doc/source/const/class.OrderConst.php b/doc/source/const/class.OrderConst.php new file mode 100644 index 00000000..6dac32e4 --- /dev/null +++ b/doc/source/const/class.OrderConst.php @@ -0,0 +1,349 @@ + '全部', + self::orderStatusWaitSellerSendGoods => '待发货', + self::orderStatusWaitBuyerConfirmGoods => '已发货', + self::orderStatusCancel => '已关闭', + self::orderStatusFinish => '已完成', + ]; + } + + public static function getDistributeOrderAfterSaleStatusMap() { + return [ + '' => '全部', + 2 => '有售后', + 1 => '无售后', + ]; + } + + public static function getPayTypeMap() { + return [ + self::payTypeHdhk => '货到付款', + self::payTypeWechat => '微信', + self::payTypeAlipay => '支付宝', + self::payTypeApplets => '小程序', + self::payTypeBankCard => '银行卡', + self::payTypeBalance => '余额', + self::payTypeNoNeedPayment => '无需支付', + self::payTypeCreditPayment => '放心花(信用支付)', + self::payTypeNewCardPayment => '新卡支付', + ]; + } + + public static function getPayTypeText($payType) { + return self::getPayTypeMap()[$payType]; + } + + public static function getOrderStatusMap() { + return [ + self::orderStatusWaitPay => '待付款', + self::orderStatusWaitSellerSendGoods => '待发货', + self::orderStatusWaitBuyerConfirmGoods => '已发货', + self::orderStatusCancel => '已取消', + self::orderStatusFinish => '已完成', + ]; + } + + public static function checkCacheReceiveMobileDecryptSource($decryptSource) { + $noCacheDecryptSourceArr = [ + self::decryptSourceCustomPrint, + self::decryptSourceAddCustomOrder, + self::decryptSourcePrint, + self::decryptSourceOrderAddressHistory, + self::decryptSourceAddressAudit, + self::decryptSourceLogisticsReachable, + ]; + return !in_array($decryptSource, $noCacheDecryptSourceArr); + } + + public static function getPriorityOrderStatus() { + return [ + OrderConst::orderStatusPartDelivery, + OrderConst::orderStatusWaitSellerSendGoods, + OrderConst::orderStatusWaitBuyerConfirmGoods, + OrderConst::orderStatusFinish, + OrderConst::orderStatusCancel, + OrderConst::orderStatusRisk, + ]; + } + + public static function getOrderStatusName($orderStatus) { + return self::getAllOrderStatusMap()[$orderStatus]; + } + + public static function getPurchaseOrderTabCanceledAllOrderStatus() { + return [ + self::orderStatusCancel, + self::returnGoodsSuccessAndSellerAgree, + self::refundSuccessAndWaitSendGoods, + self::refundSuccessAndWaitBuyerConfirmGoods, + self::returnGoodsSuccessAndSellerAgreeAndCashOnDelivery, + self::refundSuccessAndAfterSales, + self::refundSuccess, + ]; + } + + public static function getAllOrderStatusMap() { + return [ + self::orderStatusWaitPay => '待支付', + self::orderStatusWaitSellerSendGoods => '待发货', + self::orderStatusWaitBuyerConfirmGoods => '已发货', + self::orderStatusCancel => '已取消', + self::orderStatusFinish => '已完成', + self::returningAndUserApply => '退货中-用户申请', + self::returningAndSellerAgree => '退货中-商家同意退货', + self::returningAndCustomerServiceArbitration => '退货中-客服仲裁', + self::closeAndReturnGoodsFail => '已关闭-退货失败', + self::returningAndCustomerServiceAgree => '退货中-客服同意', + self::returningAndUserFilledInLogistics => '退货中-用户已填物流', + self::returnGoodsSuccessAndSellerAgree => '退货成功-商户同意', + self::returningAndAgainCustomerServiceArbitration => '退货中-再次客服仲裁', + self::returningAndCustomerServiceAgreesToRefund => '退货中-客服同意退款', + self::returnGoodsAndUserCancel => '退货-用户取消', + self::refundingAndUserApply => '退款中-用户申请', + self::refundingAndSellerAgreeAndWaitSendGoods => '退款中-商家同意', + self::refundSuccessAndWaitSendGoods => '退款成功-订单退款', + self::refundSuccessAndWaitBuyerConfirmGoods => '退款成功-订单退款', + self::returnGoodsSuccessAndSellerAgreeAndCashOnDelivery => '退货成功-商户已退款', + self::refundingAndUserCancel => '退款中-用户取消', + self::refundingAndSellerRefused => '退款中-商家拒绝', + self::returningAndWaitBuyerProcessing => '退货中-等待买家处理', + self::returnGoodsFail => '退货失败', + self::returningAndWaitBuyerProcessingAndUserFilledInLogistics => '退货中-等待买家处理', + self::refundingAndRefundApply => '退款中-退款申请', + self::refundApplyCancel => '退款申请取消', + self::refundingAndSellerAgreeAndWaitBuyerConfirmGoods => '退款中-商家同意', + self::refundingAndSellerRefusedAndWaitBuyerConfirmGoods => '退款中-商家拒绝', + self::refundingAndCustomerServiceArbitration => '退款中-客服仲裁', + self::refundingAndCustomerServiceAgree => '退款中-客服同意', + self::refundingAndSupportSeller => '退款中-支持商家', + self::closeAndRefundFail => '已关闭-退款失败', + self::refundSuccessAndAfterSales => '退款成功-售后退款', + self::refundSuccess => '退款成功-订单退款', + self::orderStatusRisk => '订单支付成功,风控处理中或待成团', + self::orderStatusPartDelivery => '部分发货', + ]; + } + + public static function getOrderStatusText($orderStatus) { + $map = self::getAllOrderStatusMap(); + return $map[$orderStatus] ?: null; + } + + public static function checkStatusEqual($status1, $status2) { + if ($status1 == $status2) { + return true; + } + if (in_array($status1, [self::orderStatusWaitSellerSendGoods]) && in_array($status2, [self::orderStatusWaitSellerSendGoods])) { + return true; + } + if (in_array($status1, [self::orderStatusWaitBuyerConfirmGoods]) && in_array($status2, [self::orderStatusWaitBuyerConfirmGoods])) { + return true; + } + if (in_array($status1, [self::orderStatusFinish]) && in_array($status2, [self::orderStatusFinish])) { + return true; + } + + return false; + } + + public static function getCancelOrderReasons() { + return [ + '用户重复下单' => '用户重复下单', + '用户不想买了' => '用户不想买了', + '用户买错了/信息填错了,重新下单' => '用户买错了/信息填错了,重新下单', + '联系不上用户' => '联系不上用户', + '快递无法配送至用户地址' => '快递无法配送至用户地址', + '其他' => '其他', + ]; + } + + public static function getOrderOutstorageHistoryTagMap() { + return [ + 'deliveryTimeType' => [ + 'right_now' => '上游订单发货时立即自动发货', + 'logistics_accept' => '上游订单揽收后发货', + 'disabled' => '不自动发货', + ], + 'isPurchaseLogisticsUpdateToPlatform' => [ + 0 => '不更新物流到下游', + 1 => '更新物流到下游', + ], + 'nearExpShipTime' => [ + 1 => '物流一直未揽收,系统自动发货,防止发货超时' + ], + ]; + } +} diff --git a/doc/source/const/class.PlatformMsgConst.php b/doc/source/const/class.PlatformMsgConst.php new file mode 100644 index 00000000..357be7fc --- /dev/null +++ b/doc/source/const/class.PlatformMsgConst.php @@ -0,0 +1,10 @@ + '上架', + self::forSale => '下架', + self::recycleBin => '删除至回收站', + self::delete => '彻底删除', + ); + + return $nameMap[$itemStatus] ? $nameMap[$itemStatus] : $itemStatus; + } + +} diff --git a/doc/source/const/class.PurchaseOrderConst.php b/doc/source/const/class.PurchaseOrderConst.php new file mode 100644 index 00000000..855c4558 --- /dev/null +++ b/doc/source/const/class.PurchaseOrderConst.php @@ -0,0 +1,359 @@ + TblConst::op_order_ds, + self::purchasePlatformLtao => TblConst::op_order_ltao, + self::purchasePlatformSooxieDS => TblConst::op_order_sooxie, + ]; + } + + public static function getOrderDsTblByPurchasePlatform($purchasePlatform) { + return self::getPurchasePlatformAndOrderDsTblMap()[$purchasePlatform]; + } + + public static function getDsPurchasePlatforms() { + return array_keys(self::getPurchasePlatformAndOrderDsTblMap()); + } + + public static function getDefaultAppendVenderRemarkFields() { + return array( + self::purchasePlatform2Field, + self::purchaseOrderSnField, + self::logisticsInfoField, + self::purchaseOrderBuyer, + ); + } + + + public static function getSupportPurchasePlatformMap() { + $supportPurchasePlatformMap = self::getPurchasePlatformMap(); + $forbidPurchasePlatforms = self::getForbidPurchasePlatformList(); + foreach ($forbidPurchasePlatforms as $forbidPurchasePlatform) { + unset($supportPurchasePlatformMap[$forbidPurchasePlatform]); + } + + unset($supportPurchasePlatformMap[self::purchasePlatformLtao]); + return $supportPurchasePlatformMap; + } + + public static function getPurchasePlatformMap() { + return array( + self::purchasePlatformTaobao => '淘宝', + self::purchasePlatformPdd => '拼多多', + self::purchasePlatformTmall => '天猫', + self::purchasePlatform1688 => '1688', + self::purchasePlatform1688DS => '1688分销', + self::purchasePlatform1688CG => '1688采购', + self::purchasePlatformTaote => '淘特', + self::purchasePlatformLtao => '淘特分销', + self::purchasePlatformJd => '京东', + self::purchasePlatformWsy => '网商园', + self::purchasePlatformSooxie => '搜鞋网', + self::purchasePlatformSooxieDS => '搜鞋网分销', + self::purchasePlatformVvic => '搜款网', + self::purchasePlatform17qcc => '青创网', + self::purchasePlatform17zwd => '一起做网店', + self::purchasePlatformHznzcn => '杭州女装网', + self::purchasePlatformBao66 => '包牛牛', + self::purchasePlatformK3 => '开山网', + self::purchasePlatformXingfujie => '新款网', + self::purchasePlatform2tong => '二童网', + self::purchasePlatformJuyi5 => '聚衣网', + self::purchasePlatform3e => '生意网', + self::purchasePlatformJp0663 => '军埔网', + self::purchasePlatform52dsy => '52电商园', + self::purchasePlatform91fj => '91家纺网', + self::purchasePlatformZlycw => '织里云仓', + ); + } + + public static function getHasPlatformOrderDetailIdPurchasePlatformList() + { + return [self::purchasePlatformHznzcn, self::purchasePlatformZlycw]; + } + + public static function getPurchasePlatformName($purchasePlatform) { + $purchasePlatformMap = self::getPurchasePlatformMap(); + + return $purchasePlatformMap[$purchasePlatform]; + } + + public static function getShortPurchasePlatformMap() { + return array( + self::purchasePlatformTaobao => 'TB', + self::purchasePlatformPdd => 'PDD', + self::purchasePlatformTmall => 'TM', + self::purchasePlatform1688 => '1688', + self::purchasePlatform1688CG => '1688CG', + self::purchasePlatform1688DS => '1688DS', + self::purchasePlatformJd => 'JD', + self::purchasePlatformWsy => 'WSY', + self::purchasePlatformSooxie => 'SX', + self::purchasePlatformSooxieDS => 'SX', + self::purchasePlatformVvic => 'VVIC', + self::purchasePlatform17qcc => '17QCC', + self::purchasePlatform17zwd => '17ZWD', + self::purchasePlatformHznzcn => 'HZNZCN', + self::purchasePlatformBao66 => 'BAO66', + self::purchasePlatformK3 => 'K3', + self::purchasePlatformXingfujie => 'XINGFUJIE', + self::purchasePlatform2tong => '2TONG', + self::purchasePlatformJuyi5 => 'JUYI5', + self::purchasePlatform3e => '3E', + self::purchasePlatformJp0663 => 'JP0663', + self::purchasePlatform52dsy => '52DSY', + self::purchasePlatformTaote => 'TAOTE', + self::purchasePlatform91fj => '91JF', + self::purchasePlatformZlycw => 'ZLYCW', + ); + } + + public static function getShortPurchasePlatformName($purchasePlatform) { + $purchasePlatformMap = self::getShortPurchasePlatformMap(); + + return $purchasePlatformMap[$purchasePlatform]; + } + + public static function getOrderStatusMaps() { + return [ + PurchaseOrderConst::purchaseOrderStatusWaitPay => '待付款', + PurchaseOrderConst::purchaseOrderStatusWaitSend => '待发货', + PurchaseOrderConst::purchaseOrderStatusHasSend => '待收货', + PurchaseOrderConst::purchaseOrderStatusFinished => '交易成功', + PurchaseOrderConst::purchaseOrderStatusCancel => '交易关闭', + PurchaseOrderConst::purchaseOrderStatusRefund => '退款中', + ]; + } + + public static function getPurchaseOrderStatusMap() { + return [ + PurchaseOrderConst::purchaseOrderStatusWaitConfirm => '待确认', + PurchaseOrderConst::purchaseOrderStatusWaitPay => '未付款', + PurchaseOrderConst::purchaseOrderStatusTakingGoods => '拿货中', + PurchaseOrderConst::purchaseOrderStatusWaitSend => '待发货', + PurchaseOrderConst::purchaseOrderStatusHasSend => '已发货', + PurchaseOrderConst::purchaseOrderStatusFinished => '已完成', + PurchaseOrderConst::purchaseOrderStatusCancel => '已关闭', + PurchaseOrderConst::purchaseOrderStatusRefund => '退款中', + ]; + } + + public static function getPurchaseOrderStatusArr($excludeStatus = []) { + $purchaseOrderStatusArr = array_keys(self::getOrderStatusMaps()); + return array_diff($purchaseOrderStatusArr, $excludeStatus); + } + + public static function getPurchaseFixedMobileColumnByPurchasePlatform($purchasePlatform) { + return 'purchase_pdd_fixed_mobile'; + } + + public static function getForbidPurchasePlatformList() { + return [ + self::purchasePlatformJd, + self::purchasePlatformTaobao, + self::purchasePlatformTmall, + self::purchasePlatformPdd, + ]; + } + +} \ No newline at end of file diff --git a/doc/source/const/class.PurchaseOrderTagConst.php b/doc/source/const/class.PurchaseOrderTagConst.php new file mode 100644 index 00000000..1080658d --- /dev/null +++ b/doc/source/const/class.PurchaseOrderTagConst.php @@ -0,0 +1,8 @@ + '完成', + self::success => '成功', + self::fail => '失败', + self::cancel => '已取消', + self::wait => '等待', + self::processing => '处理中', + self::waitRevert => '等待恢复', + self::processingRevert => '恢复处理中', + self::revertSuccess => '已恢复', + self::revertFail => '恢复失败', + ]; + + return $codeMap[$code] ? $codeMap[$code] : ''; + + } + + const productImgProcessTypeNormal = 'normal'; + const productImgProcessTypeRevert = 'revert'; +} \ No newline at end of file diff --git a/doc/source/const/class.TblConst.php b/doc/source/const/class.TblConst.php new file mode 100644 index 00000000..232e7ace --- /dev/null +++ b/doc/source/const/class.TblConst.php @@ -0,0 +1,239 @@ +shopService = Zc::singleton(ShopService::class); + $this->moveService = Zc::singleton(MoveService::class); + $this->productService = Zc::singleton(ProductService::class); + $this->rsyncProductService = Zc::singleton(RsyncProductService::class); + $this->watermarkService = Zc::singleton('WatermarkService'); + $this->moveImportService = Zc::singleton('MoveImportService'); + $this->feedbackService = Zc::singleton(FeedbackService::class); + + $this->productUtil = Zc::singleton(ProductUtil::class); + $this->moveUtil = Zc::singleton(MoveUtil::class); + $this->materialUtil = Zc::singleton('MaterialUtil'); + $this->spider = new PageSpider(array (), null, $_SERVER['REMOTE_ADDR']); + + $this->dsClient = Zc::singleton('DsClient'); + $this->webShop = Zc::getWebUser(); + $this->moveBatchSettingLog = Zc::getLog('move/batch/setting'); + $this->moveBatchUrlLog = Zc::getLog('move/batch/url'); + $this->timeStatLog = Zc::getLog('move/batch/time_stat'); + $this->moveBatchSaveTaskLog = Zc::getLog('move/batch/saveTask'); + $this->moveBatchDebugLog = Zc::getLog('move/batch/debug'); + $this->failRetryMoveTaskLog = Zc::getLog('move/batch/fail_retry'); + $this->moveAgainDetailLog = Zc::getLog('move/batch/again_detail'); + $this->moveBatchShopLog = Zc::getLog('move/batch/shop'); + $this->tailorImgTool = new TailorImgTool(); + $this->ltaoTool = new LtaoTool(); + + $this->materialService = Zc::singleton(MaterialService::class); + + Zc::import('@.vendor.CSVParse', '', '.php', 'class.'); + $this->csvParse = new CSVParse(); + $this->redis = RedisExt::factory('bizCache'); + } + + + public function target() { + if (!isset($_SESSION[SessionConst::geoIpArea])) { + $geoInfo = $this->shopService->getGeoIpInfo(CommonTool::clientIp(), false); + if (!empty($geoInfo)) { + $_SESSION[SessionConst::geoIpArea] = $geoInfo; + } + } + + if ($_GET['copyType'] == MoveConst::collectFetchBank) { + $this->redirect(Zc::url(RouteConst::moveBatchTarget, array('copyType' => $_GET['copyType']), 'https', Zc::C('fetchBank.domain'))); + } + + $copyType = in_array($_GET['copyType'], array ( + MoveConst::collectLinksCopy, + MoveConst::collectShopCopy, + MoveConst::collectWebsiteCopy, + MoveConst::collectDsCopy, + MoveConst::collectLtaoCopy, + MoveConst::collectSameProduct, + MoveConst::collectClueCopy, + )) ? $_GET['copyType'] : MoveConst::collectLinksCopy; + + $shopId = $_SESSION[SessionConst::shopId]; + $shopName = $_SESSION[SessionConst::shopName]; + + $moveAdvancedConfig = $this->moveService->getMoveAdvancedConfig($shopId); + + $appOrder = $this->shopService->getShopFirstAppOrder($shopId); + $isFetchBank = $this->webShop->getFlash('isFetchBank') ?: $_POST['isFetchBank']; + $categoryOptionArray = $this->productUtil->getCategoryOptionArray($shopId); + + $dsHelpArticleList = []; + + $dsBuyUrl = $this->moveService->getDsBuyUrl($shopId); + $dsMemberInfo = $this->moveService->getDsMemberInfo($shopId); + $dsMemberName = $dsMemberInfo['cnali_member_name']; + $ruleList = $this->getChoicenessSourceItemTag(); + + $collectTaskWareIds = $_POST['collectTaskWareIds'] ? json_decode($_POST['collectTaskWareIds'], true) : $this->webShop->getFlash('collectTaskWareIds'); + $fetchBankDetailIds = $_POST['fetchBankDetailIds'] ? json_decode($_POST['fetchBankDetailIds'], true) : $this->webShop->getFlash('fetchBankDetailIds'); + + $this->render(array ( + 'copyType' => $copyType, + 'shopId' => $shopId, + 'shopName' => $shopName, + 'appOrder' => $appOrder, + 'isFetchBank' => $isFetchBank, + 'collectTaskWareIds' => $collectTaskWareIds, + 'fetchBankDetailIds' => $fetchBankDetailIds, + 'moveAdvancedConfig' => $moveAdvancedConfig, + 'categoryOptionArray' => $categoryOptionArray, + 'alibabaHelpArticleList' => $dsHelpArticleList, + 'ltaoAuthInfo' => $ltaoAuthInfo, + 'dsBuyUrl' => $dsBuyUrl, + 'alibabaMemberName' => $dsMemberName, + 'alibabaMemberExpire' => $dsMemberInfo['gmt_expire'], + 'folderMenuTree' => $this->materialService->getMaterialFolderMenuTree($shopId), + 'ruleList' => $ruleList, + ), 'move/batch/target_all'); + } + + private function getChoicenessSourceItemTag() { + $tagCache = DsClientTool::tryGetChoicenessSourceItemTagByLocal(); + if ($tagCache) { + return $tagCache; + } + + $getRet = $this->dsClient->getChoicenessSourceItemTag(DsConst::platformDd); + if (CommonTool::isSuccessRet($getRet)) { + DsClientTool::stashChoicenessSourceItemTagToLocal($getRet['data']); + } + + return $getRet['data']; + } + + public function resetMoveSetting() { + $moveSettingId = !empty($_POST['moveSettingId']) ? (int)$_POST['moveSettingId'] : 0; + $shopId = $_SESSION[SessionConst::shopId]; + + if (!$moveSettingId || !$shopId) { + return $this->renderJSON(CommonTool::failResult('参数错误')); + } + + $newMoveSettingId = $this->moveUtil->resetMoveSetting($moveSettingId, $shopId); + if ($newMoveSettingId) { + $moveSettingList = $this->moveUtil->getInitMoveSettingList($shopId); + $renderData = array( + 'moveSettingList' => $moveSettingList, + 'moveSettingId' => $newMoveSettingId, + ); + return $this->renderJSON(CommonTool::successResult($renderData)); + } + return $this->renderJSON(CommonTool::failResult('恢复默认设置失败')); + } + + public function getInitDataList() { + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); + + $ret = $this->moveUtil->getInitDataList(); + return $this->renderJSON($ret); + } + + + public function getFreightTemplateList() { + $shopId = $_POST['authShopId'] ? $_POST['authShopId'] : $_SESSION[SessionConst::shopId]; + $accessToken = $this->shopService->getShopAccessToken($shopId); + $freightTemplateRet = $this->moveService->getFreightTemplateListFromDd($accessToken); + $ret = [ + 'freightTemplateList' => $freightTemplateRet['freightTemplateList'] ? $freightTemplateRet['freightTemplateList'] : [], + ]; + $this->renderJSON(CommonTool::successResult($ret)); + } + + public function getCurrentShopMoveSetting() { + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); + + $shopId = $_POST['curShopId'] ? $_POST['curShopId'] : $_SESSION[SessionConst::shopId]; + $accessToken = $_SESSION[SessionConst::accessToken]; + if (empty($shopId) || empty($accessToken)) { + $this->renderJSON(CommonTool::failResult("获取用户id失败,请联系客服")); + return ; + } + + $moveSettingList = $this->moveUtil->getInitMoveSettingList($shopId); + + foreach ($moveSettingList as $moveSetting) { + if ($moveSetting['is_config_default'] == 1) { + return $this->renderJSON(CommonTool::successResult('moveSetting', $moveSetting)); + } + } + + $moveSetting = array_shift($moveSettingList); + + return $this->renderJSON(CommonTool::successResult('moveSetting', $moveSetting)); + } + + public function saveMoveBatchConfigFirst() { + header('Access-Control-Allow-Credentials: true'); + header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); + $shopId = $_SESSION[SessionConst::shopId]; + $moveSetting = $_POST['moveSetting']; + + $ret = $this->moveUtil->saveMoveBatchConfigFirst($shopId, $moveSetting, $this->moveBatchSettingLog); + return $this->renderJSON($ret); + } + + + public function fetchAlibabaDetailUrlInfo() { + $shopId = $_SESSION[SessionConst::shopId]; + + $alibabaMemberId = $this->moveService->getAlibabaMemberId($shopId); + if (empty($alibabaMemberId)) { + $isExistDs = $this->moveService->isExistDs($shopId); + if ($isExistDs) { + return $this->renderJSON(CommonTool::failCodeResult(ErrorCodeConst::expireDsAuth, '抖店和1688授权过期,请重新授权')); + } + + return $this->renderJSON(CommonTool::failCodeResult(ErrorCodeConst::noDsAuth, '抖店没有1688主客授权,请授权')); + } + + $checkRet = $this->moveUtil->checkAbnormalRequest($shopId); + if (CommonTool::isFailRet($checkRet)) { + return $this->renderJSON($checkRet); + } + + $startTime = ZcNumberHelper::microtimeFloat(); + $this->moveBatchUrlLog->info('fetchDetailUrlInfo, shopId[' . $_SESSION[SessionConst::shopId] . '], post: ' . print_r($_POST, true)); + $detailUrls = $_POST['detailUrls']; + + $getProductInfoListRet = $this->getAlibabaProductsInfoListByDetailUrls($detailUrls, $shopId, true); + if (CommonTool::isFailRet($getProductInfoListRet)) { + return $this->renderJSON($getProductInfoListRet); + } + + $endTime = ZcNumberHelper::microtimeFloat(); + $costTime = bcsub($endTime, $startTime, 3); + $timeStatLogStr = sprintf('searchProductStat | %s | %s | %s', $shopId, count($detailUrls), $costTime); + $this->timeStatLog->info($timeStatLogStr); + + $productsInfoList = $getProductInfoListRet['productsInfoList']; + $productList = $this->moveUtil->processProductList($productsInfoList, $shopId, null, $_POST['productClueCatePathMap'] ?: [], $_POST['productClueIdMap'] ?: []); + $productList = $this->moveUtil->attachIsMoved($productList, $shopId); + return $this->renderJSON(CommonTool::successResult(array( + 'productList' => $productList, + 'sourceItemIds' => array_keys($productList), + 'hostname' => gethostname() + ))); + } + + private function getAlibabaProductsInfoListByDetailUrls($detailUrls, $shopId, $needCheckFree = false) { + $detailUrls = array_map('trim', preg_split("/\\r\\n|\\r|\\n|,|,|;|;/u", $detailUrls)); + + $ret = $this->buildAlibabaFetchUrlList($shopId, $detailUrls, $needCheckFree); + if (CommonTool::isFailRet($ret)) { + return $ret; + } + $fetchList = $ret['fetchList']; + + $productsInfoListRet = $this->moveUtil->fetchProductsList($fetchList, true); + $productsInfoList = $productsInfoListRet['productsInfoList']; + return CommonTool::successResult(array( + 'productsInfoList' => $productsInfoList, + )); + } + + private function buildAlibabaFetchUrlList($shopId, $detailUrls, $needCheckFree = false) { + $uniqueSourceProductArray = array(); + $sourceProducts = array(); + $fetchList = array(); + $fetchSourceList = []; + $aliCount = 0; + $shortUrlToNormalUrlMap = $this->moveUtil->getRealItemUrlFromShortUrl($detailUrls); + + foreach ($detailUrls as $url){ + //ctype_digit纯数字检测 + if(empty($url) || ctype_digit($url)){ + continue; + } + $url = $shortUrlToNormalUrlMap[$url] ? : $url; + $sourceProduct = $this->moveUtil->parseDetailUrl($url); + if (!empty($sourceProduct)) { + $productId = $sourceProduct['itemId']; + $source = $sourceProduct['source']; + $site = $sourceProduct['site']; + $isFromMobileLink = $sourceProduct['isFromMobileLink']; + + if ($uniqueSourceProductArray[$source.$productId.$site]) { + continue; + } + $uniqueSourceProductArray[$source.$productId.$site] = true; + + if ($source == FetchClientConst::collectTaskSource1688) { + $aliCount++; + } + $sourceProducts[] = $sourceProduct; + $fetchSourceList[] = $source; + } + if ($source == FetchClientConst::collectTaskSource1688) { + $fetchUrl = Zc::url(RouteConst::TimerMoveTaskFetchDsItem, array('itemId' => $productId, 'source' => $source, 'site' => $site, 'shopId' => $shopId, 'isFromMobileLink' => $isFromMobileLink, 'moveNeedCollectDetail' => FetchClientTool::moveNeedCollectDetail($source), 'trace' => MoveConst::traceDdmsFetchUrl()), 'http', Zc::C('multi.crawler.domain')); + } else { + $fetchUrl = Zc::url(RouteConst::TimerMoveTaskFetchItem, array('itemId' => $productId, 'source' => $source, 'site' => $site, 'shopId' => $shopId, 'isFromMobileLink' => $isFromMobileLink, 'moveNeedCollectDetail' => FetchClientTool::moveNeedCollectDetail($source), 'trace' => MoveConst::traceDdmsFetchUrl()), 'http', Zc::C('multi.crawler.domain')); + } + + $fetchList[$fetchUrl] = array(); + } + + $ret = $this->moveService->checkPlatformAuthorize($fetchSourceList, [FetchClientConst::collectTaskSource1688]); + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + if ($needCheckFree && $aliCount > 50) { + $getVersionRet = $this->shopService->getShopAppVersion($shopId); + $shopVersion = $getVersionRet['appVersion']; + if (AppConst::checkIsFreeVersion($shopVersion)) { + $authCode = $this->shopService->getAuthCodeByShopId($shopId); + $searchRet = $this->dsClient->getDsMemberVersion(DsConst::platformDd, $authCode); + if (CommonTool::isFailRet($searchRet)) { + return $searchRet; + } + $isFree = $searchRet['isFree']; + if ($isFree) { + return CommonTool::failCodeResult(ErrorCodeConst::isDsFreeUserLimit, '每次输入链接最多50条,请减少商品数量后重试或升级高级版'); + } + } + } + + $ret = $this->checkProductErrorInfo($sourceProducts, $aliCount); + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + return CommonTool::successResult([ + 'fetchList' => $fetchList, + ]); + } + + + + + private function checkProductErrorInfo($sourceProducts, $aliCount) { + if(empty($sourceProducts)){ + return CommonTool::failResult("商品详情页面链接或者ID错误, 请重新输入"); + } + if ($aliCount > 200) { + return CommonTool::failCodeResult('overLimit', "1688商品一次最多只支持200个链接,您当前提交了{$aliCount}个商品"); + } + if(count($sourceProducts) > 500){ + return CommonTool::failCodeResult('overLimit', "最多支持500个商品链接"); + } + } + + + private function checkRequireAttrAndQuality($products, $setting) { + if (!empty($setting['isValidateRequire'])) { + return CommonTool::successResult(); + } + + $requirePresetAttrNames = MoveConst::getRequirePresetAttrNames(); + $requirePresetQualityNames = MoveConst::getRequirePresetQualityNames(); + + $checkAttrNames = []; + foreach ($requirePresetAttrNames as $attrName) { + $isset = false; + foreach ((array)$setting['preset_attrs'] as $presetAttr) { + if (($attrName == $presetAttr['presetAttrName']) && $presetAttr['presetAttrValue'] && ($presetAttr['presetAttrEnable'] == 1)) { + $isset = true; + break; + } + } + if (!$isset) { + $checkAttrNames[] = $attrName; + } + } + + $checkQualityNames = []; + $ret = $this->doGetQualityListByCid($setting['move_shop_setting_id'], 0); + foreach ($requirePresetQualityNames as $qualityName) { + $isset = false; + foreach ($ret['qualityList'] as $quality) { + if (($qualityName == $quality['quality_name']) && !empty($quality['img_list'])) { + $isset = true; + break; + } + } + if (!$isset) { + $checkQualityNames[] = $qualityName; + } + } + + if (!$checkAttrNames && !$checkQualityNames) { + return CommonTool::successResult(); + } + + $needGetCateAttrCids = $needGetCateQualityCids = []; + foreach ($products as $product) { + if ($checkAttrNames) { + $needGetCateAttrCids[] = $product['cid']; + } + if ($checkQualityNames) { + $needGetCateQualityCids[] = $product['cid']; + } + } + + list($cateAttrs, $cateQualitys) = $this->moveService->getCateAttrsAndQualitys($needGetCateAttrCids, $needGetCateQualityCids, $_SESSION[SessionConst::accessToken]); + if ($needGetCateQualityCids) { + $needGetCateQualityCids[] = 0; + $shopProductQualitySettingList = $this->moveService->getShopProductQualitySettingList($_SESSION[SessionConst::shopId], $setting['move_shop_setting_id'], $needGetCateQualityCids); + $qualitySettings = []; + foreach ($shopProductQualitySettingList as $qualitySetting) { + $qualitySettings[$qualitySetting['cid']][] = $qualitySetting; + } + $productQualityMap = $qualitySettings ? $this->moveService->getProductQualityMap() : null; + } + + $requireAttrNames = $requireQualityList = []; + foreach ($products as $product) { + $cid = $product['cid']; + + if (!empty($cateAttrs[$cid])) { + foreach ($cateAttrs[$cid] as $prop) { + $propId = $prop['property_id']; + if (in_array($prop['property_name'], $checkAttrNames) && empty($product['props'][$propId]) && $prop['required']) { + $requireAttrNames[] = $prop['property_name']; + } + } + } + + if (!empty($cateQualitys[$cid])) { + $productQualityList = $cateQualitys[$cid]; + if ($qualitySettings[0]) { + $productQualityList = $this->moveUtil->appendQualityImgs($productQualityList, $qualitySettings[0], $productQualityMap); + } + if ($qualitySettings[$cid]) { + $productQualityList = $this->moveUtil->appendQualityImgs($productQualityList, $qualitySettings[$cid], $productQualityMap); + } + + foreach ($productQualityList as $quality) { + if(!$quality['is_required']) { + continue; + } + if (isset($product['productQualityMap'][$cid][$quality['quality_key']]) && array_filter($product['productQualityMap'][$cid][$quality['quality_key']])) { + continue; + } + if (!empty($quality['img_list'])) { + continue; + } + $requireQualityList[$quality['quality_key']] = $quality; + } + } + } + + $res = []; + $requireAttrNames && $res['requireAttrNames'] = $requireAttrNames; + $requireQualityList && $res['requireQualityList'] = $requireQualityList; + if ($res) { + return CommonTool::failResult($res); + } else { + return CommonTool::successResult(); + } + } + + public function saveTask() { + $shopId = $_SESSION[SessionConst::shopId]; + $this->moveBatchSaveTaskLog->info("shopId $shopId start saveTask"); + + ini_set('memory_limit', '1024M'); + $_POST = $_POST['valueMap'] ? json_decode($_POST['valueMap'], true) : json_decode(file_get_contents('php://input'), true); // 20220112起没有valueMap,兼容作用 + $needMoveShopIds = isset($_POST['needMoveShopIds']) ? $_POST['needMoveShopIds'] : (array($shopId)); // 前端没有传这个参数的时候使用这个用户自己 + $productSimpleDetails = json_decode($_POST['productSimpleDetails'], true); + + $copyType = $_POST['copyType']; + + $shopMoveSettingOperateLogMap = json_decode($_POST['shopMoveSettingOperateLogMap'], true); + $shopMoveConditionMap = $_POST['shopMoveConditionMap']; + $shopPreviewCateAttr = json_decode($_POST['previewCateAttr'], true); + + $source = $_POST['source']; + $isFetchBank = $_POST['isFetchBank'] ? $_POST['isFetchBank'] : false; + $copyType = $isFetchBank ? MoveConst::collectFetchBank : $_POST['copyType']; + + $hostname = gethostname(); + + $shopGroupMoveType = isset($_POST['shopGroupMoveType']) ? $_POST['shopGroupMoveType'] : null; + $shopGroupAllocType = isset($_POST['shopGroupAllocType']) ? $_POST['shopGroupAllocType'] : null; + + $this->moveBatchSaveTaskLog->info("shopId $shopId start checkAndFormatData"); + $checkAndFormatRet = $this->checkAndFormatData($shopId, $needMoveShopIds, $_POST, $shopMoveConditionMap, $shopPreviewCateAttr, $productSimpleDetails, $hostname, $copyType); + $this->moveBatchSaveTaskLog->info("shopId $shopId end checkAndFormatData"); + if (CommonTool::isFailRet($checkAndFormatRet)) { + return $this->renderJSON($checkAndFormatRet); + } + + $curProductDetails = $checkAndFormatRet['curProductDetails']; + $shopConditions = $checkAndFormatRet['shopConditions']; + $shopMoveConditionMap = $checkAndFormatRet['shopMoveConditionMap']; + + $this->moveBatchSaveTaskLog->info("shopId $shopId start allocShopProductsByAuthShop"); + $shopProducts = $this->allocShopProductsByAuthShop($needMoveShopIds, $curProductDetails); + + $checkDsValidRet = $this->checkDsValid($needMoveShopIds, $shopProducts); + if (CommonTool::isFailRet($checkDsValidRet)) { + return $this->renderJSON($checkDsValidRet); + } + + $this->moveBatchSaveTaskLog->info("shopId $shopId start saveTaskByAuthShop"); + $operateSource = $_POST['copyStep2Preview'] ? 'pc' : 'platform'; // 埋点,主客统计搬家来源 + $isFromLtaoRank = isset($_POST['isFromLtaoRank']) ? $_POST['isFromLtaoRank'] : 0; + $saveRet = $this->saveTaskByAuthShop($shopId, $copyType, $shopMoveConditionMap, $shopMoveSettingOperateLogMap, $shopConditions, $shopProducts, $shopPreviewCateAttr, $hostname, $operateSource, $isFromLtaoRank); + + if (CommonTool::isFailRet($saveRet)) { + return $this->renderJSON($saveRet); + } + + $shopTaskId = $saveRet['taskId']; + $redirectURL = Zc::url(RouteConst::moveBatchFinish, array('taskId' => $shopTaskId, 'source' => $source)); + $this->moveBatchSaveTaskLog->info("shopId $shopId session shopId " . $_SESSION[SessionConst::shopId] . " saveTask success " . print_r(Zc::G(), true)); + $submitCnt = (int)count($shopProducts[$_SESSION[SessionConst::shopId]]); + if ($submitCnt == 0) { + return $this->renderJSON(array( + 'result' => 'fail', + 'reason' => sprintf('%s:提交商品数为0,请检查是否正常提交商品', $hostname), + 'taskId' => $shopTaskId, + 'submitCnt' => $submitCnt, + )); + } + + if ($_POST['sameType']) { + $this->moveService->saveSameProductCopyLog($_POST['sameType'], $_POST['searchSameProductMap'], $shopId, $copyType == MoveConst::collectDsCopy); + } + $this->renderJSON(CommonTool::successResult(array( + 'hostname' => $hostname, + 'taskId' => $shopTaskId, + 'submitCnt' => $submitCnt, + 'redirectURL' => $redirectURL + ))); + } + + private function checkNeedChangeBrand($shopMoveConditionMap) { + return CommonTool::successResult(); // 先不判断 + foreach ($shopMoveConditionMap as $authShopId => $moveCondition) { + $brandId = $moveCondition['brand_id']; + + if(!is_numeric($brandId) || empty($brandId)) { + return CommonTool::successResult(); + } + + $name = $this->moveService->getBrandName($brandId, $authShopId); + if(empty($name)) { + return CommonTool::failResult('请在搬家配置重新设置品牌信息在提交任务!'); + } + } + + return CommonTool::successResult(); + } + + + private function getProductSimpleDetails($productSimpleDetails, $shopId) { + foreach ($productSimpleDetails as $authShopId => &$curProductDetails) { + foreach ($curProductDetails as $skipProductId => &$product) { + if ($product['needSkip'] == 1) { + unset($curProductDetails[$skipProductId]); + } + if ($shopId != $authShopId) { + unset($product['freight_template_id']); + } + } + } + + return $productSimpleDetails; + } + + + + public function saveTaskFailLog() { + $this->moveService->saveTaskFailLog($_SESSION[SessionConst::shopId], $_REQUEST, $_SERVER, CommonTool::clientIp(), 'save_task_fail_log'); + $this->renderJSON(CommonTool::successResult()); + } + + private function checkAndFormatData($shopId, $needMoveShopIds, $post, $shopMoveConditionMap, $shopPreviewCateAttr, $productSimpleDetails, $hostname, $copyType) { + $hasError = false; + $errorArray = array(); + $shopConditions = array(); + + $productSimpleDetails = $this->getProductSimpleDetails($productSimpleDetails, $shopId); + $curProductDetails = $productSimpleDetails[$shopId]; + if(empty($curProductDetails)){ + $this->moveService->saveTaskFailLog($_SESSION[SessionConst::shopId], $_REQUEST, $_SERVER, CommonTool::clientIp(), 'save_task'); + $this->moveBatchDebugLog->info("shopId[$shopId] empty curProductDetails"); + $this->moveBatchDebugLog->info($post); + $ret = CommonTool::failResult(sprintf('%s shopId:%s,未选择要搬家的商品', $hostname, $shopId)); + $ret['hostname'] = $hostname; + return $ret; + } + foreach ($curProductDetails as $productId => $productDetail) { + if (!$productDetail['cid']) { + $this->moveBatchDebugLog->info("shopId[$shopId] productId[$productId] invalid cid"); + $ret = CommonTool::failResult(sprintf('商品ID:%s 类目必填,请先设置', $productId)); + $ret['hostname'] = $hostname; + return $ret; + } + } + + foreach ($needMoveShopIds as $authShopId) { + $this->moveBatchSaveTaskLog->info("shopId $shopId $authShopId start rebuild move data"); + if (empty($shopMoveConditionMap[$authShopId]) || empty($shopMoveConditionMap[$authShopId]['desc_copy_type'])) { + $hasError = true; + $errorArray[] = sprintf('shopId:%s,搬家配置数据不完整,提交失败。请联系客服!', $authShopId); + $this->moveBatchDebugLog->info("shopId[$authShopId] 搬家配置数据不完整~~"); + $this->moveBatchDebugLog->info($post); + break; + } + if (!empty($shopPreviewCateAttr[$authShopId])) { + $shopMoveConditionMap[$authShopId]['usePreviewCommonCateAttr'] = true; + } + $conditionRet = $this->moveService->getTaskCondition($shopMoveConditionMap[$authShopId]); + if(CommonTool::isFailRet($conditionRet)){ + $hasError = true; + $errorArray[] = $conditionRet['reason']; + break; + } + $shopConditions[$authShopId] = $conditionRet['condition']; + + $shopIsExpire = $this->moveService->checkShopIsExpire($authShopId); + if ($shopIsExpire) { + $shopInfo = $this->shopService->getShop($authShopId); + $hasError = true; + $tip = ($shopId == $authShopId) ? '请联系客服续费!' : '请取消搬家至该店铺'; + $errorArray[] = sprintf('店铺【%s】,已过期,%s', $shopInfo['shop_name'], $tip); + break; + } + + if ($copyType == MoveConst::collectDsCopy) { + $this->moveService->attachDsMoveCopyTotal($authShopId); + } + + $moveConfig = $this->moveService->getAvailableCopyCount($authShopId); + $productTotal = count($curProductDetails); + $dsProducts = $this->moveService->getDsDetails($curProductDetails); + $dsProductTotal = $dsProducts ? count($dsProducts) : 0; + $productTotal = $productTotal - $dsProductTotal; + if ($productTotal > 0 && $productTotal > $moveConfig['available_total']){ + $appVersionRet = $this->shopService->getShopAppVersion($shopId); + $this->moveService->recordTriggerAppVersionLimitLog($shopId, $appVersionRet['appVersion'], $moveConfig['total'], $moveConfig['used_total'], $productTotal, 'move'); + $shopInfo = $this->shopService->getShop($authShopId); + $hasError = true; + $tip = $this->moveUtil->getChargeTipByShopInfo($shopInfo, $productTotal, $moveConfig['available_total']); + + $errorArray[] = $tip; + break; + } + } + + if ($hasError) { + $this->moveBatchSaveTaskLog->info("shopId $shopId saveTask hasError" . print_r(Zc::G(), true)); + $ret = CommonTool::failResult(implode(';', $errorArray)); + $ret['hostname'] = $hostname; + return $ret; + } + + return CommonTool::successResult(array( + 'curProductDetails' => $curProductDetails, + 'shopConditions' => $shopConditions, + 'shopMoveConditionMap' => $shopMoveConditionMap, + )); + } + + private function allocShopProductsByAuthShop($needMoveShopIds, $curProductDetails) { + $shopProducts = array(); + foreach ($needMoveShopIds as $authShopId) { + foreach ($curProductDetails as $productInfo){ + $newProduct = $this->moveUtil->formatSaveMoveTaskProduct($productInfo, $authShopId); + if (empty($newProduct)) { + continue; + } + + $productId = $productInfo['productId']; + $shopProducts[$authShopId][$productId] = $newProduct; + } + } + + return $shopProducts; + } + + private function saveTaskByAuthShop($shopId, $copyType, $shopMoveConditionMap, $shopMoveSettingOperateLogMap, $shopConditions, $shopProducts, $shopPreviewCateAttr, $hostname, $operateSource, $isFromLtaoRank) { + Zc::G("shopId $shopId start saveMoveSetting"); + list($updateErrorShopIds, $moveShopSettingIds) = $this->saveMoveSetting($shopMoveConditionMap, $shopMoveSettingOperateLogMap); + Zc::G("shopId $shopId end saveMoveSetting"); + if (!empty($updateErrorShopIds)) { + $ret = CommonTool::failResult(sprintf('店铺Id:%s,保存搬家配置失败,请稍后再尝试', implode(' ', $updateErrorShopIds))); + $ret['hostname'] = $hostname; + return $ret; + } + + if ($copyType == MoveConst::collectLinksCopy) { + $name = sprintf('%s 批量抓取', ZcDateHelper::now()); + } else { + $name = sprintf('%s', ZcDateHelper::now()); + } + + Zc::G("shopId $shopId start replaceShopConditionsBigField"); + $shopConditions = $this->moveService->replaceShopConditionsBigField($shopConditions, $moveShopSettingIds); + Zc::G("shopId $shopId end replaceShopConditionsBigField"); + $shopConditions = $this->attachMoveSettingIdToMoveTaskCondition($moveShopSettingIds, $shopConditions); + $this->moveBatchSaveTaskLog->info("shopId $shopId start addShopCollectTask"); + + $addRet = $this->moveService->addShopCollectTask($shopId, $shopProducts, $name, $copyType, $shopConditions, $shopPreviewCateAttr, $operateSource,$isFromLtaoRank); + + if (CommonTool::isFailRet($addRet)) { + $this->moveBatchSaveTaskLog->info("shopId $shopId saveTask addRet fail" . print_r(Zc::G(), true)); + $addRet['hostname'] = $hostname; + } + + return $addRet; + } + + + + public function saveMoveSetting($shopMoveConditionMap, $shopMoveSettingOperateLogMap = array()) { + $shopId = $_SESSION[SessionConst::shopId]; + + $updateErrorShopIds = array(); + $moveShopSettingIds = array(); + foreach ($shopMoveConditionMap as $authShopId => $moveCondition) { + if (empty($moveCondition)) { + $this->moveBatchSettingLog->info("authShopId[$authShopId] get empty moveCondition"); + continue; + } + + $moveCondition = $this->moveUtil->processMoveSetting($moveCondition); + $moveCondition['shop_id'] = $authShopId; + $moveShopSettingId = $moveCondition['move_shop_setting_id']; + if ($moveShopSettingId) { + $ret = $this->moveService->updateMoveSetting($authShopId, $moveShopSettingId, $moveCondition); + $this->moveService->addMoveShopSettingOperateLog($shopId, $authShopId, $shopMoveSettingOperateLogMap[$authShopId]); + $moveShopSettingIds[$authShopId] = $moveShopSettingId; + } else { + $ret = $this->moveService->insertMoveSetting($moveCondition); + if ($ret) { + $moveShopSettingIds[$authShopId] = $ret; + } + + } + + if (!$ret) { + $updateErrorShopIds[] = $authShopId; + } + $this->moveBatchSettingLog->info("shopId[$shopId] authShopId[$authShopId] post data:" . print_r($moveCondition, true) . "update ret:[$ret]" ); + } + return [$updateErrorShopIds, $moveShopSettingIds]; + } + + public function history() { + $moveShopStopInfo = $this->moveService->getMoveShopStopInfo($_SESSION[SessionConst::shopId]); + $folderMenuTree = $this->materialService->getMaterialFolderMenuTree($_SESSION[SessionConst::shopId]); + $shopId = $_SESSION[SessionConst::shopId]; + + $productCatList = $this->rsyncProductService->getAllLeafProductCatList($_SESSION[SessionConst::shopId]); + $cates = []; + $cates[] = '请选择分类'; + foreach ($productCatList as $productCat) { + $cates[$productCat['category_id']] = $productCat['path']; + } + + $this->render([ + 'moveShopStopInfo' => $moveShopStopInfo, + 'folderMenuTree' => $folderMenuTree, + 'shopId' => $shopId, + 'productCatList' => $cates + ]); + } + + public function historyProductList() { + $pageNo = $_GET['page'] > 0 ? (int)$_GET['page'] : 1; + $pageSize = $_GET['pageSize'] > 0 ? (int)$_GET['pageSize'] : 20; + $source = $_GET['source']; + $status = $_GET['status']; + + $shopId = $_SESSION[SessionConst::shopId]; + $filter = $this->moveUtil->buildHistoryProductListFilter($_GET); + $filter['isMoveHugeSeller'] = $_SESSION[SessionConst::isMoveHugeSeller]; + if (!in_array($pageSize, [20, 40, 100, 500, 1000, 2000])) { + $pageSize = 20; + } + + list($processingTaskCount, $taskDetailList, $total, $moveShopStopInfo) = $this->productUtil->getHistoryProductList($shopId, $filter, $pageNo, $pageSize); + $taskDetailList = $this->productUtil->buildLtaoProductToDsItemTag($taskDetailList); + $pagin = new ZcPagination($total, $pageSize, $pageNo); + $html = $this->renderWithoutLayout(array( + 'taskDetailList' => $taskDetailList, + 'pagin' => $pagin, + 'pageSize' => $pageSize, + 'status' => $status, + 'source' => $source, + 'taskTotal' => $total, + 'processingTaskCount' => $processingTaskCount, + 'filter' => $filter, + 'moveShopStopInfo' => $moveShopStopInfo, + 'showLimitPublishReason' => $this->productUtil->showLimitPublishReason($taskDetailList, $moveShopStopInfo), + ), 'move/batch/history_product_list', true); + $data['html'] = $html; + return $this->renderJSON($data); + } + + + public function failRetryMoveTasks() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult('CSRF校验不通过')); + } + + $shopId = $_SESSION[SessionConst::shopId]; + $taskDetailIds = is_array($_POST['taskDetailIds']) ? $_POST['taskDetailIds'] : [$_POST['taskDetailIds']]; + + $retryRet = $this->moveUtil->failRetryMoveTasks($shopId, $taskDetailIds, $this->failRetryMoveTaskLog); + $this->renderJSON($retryRet); + } + + + public function moveAgainDetail() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult('CSRF校验不通过')); + } + + $shopId = $_SESSION[SessionConst::shopId]; + $taskDetailIds = is_array($_POST['taskDetailIds']) ? $_POST['taskDetailIds'] : [$_POST['taskDetailIds']]; + + + if (count($taskDetailIds) == 1) { + $newDetailId = $this->moveService->moveAgainDetailsByDetailId($shopId, array_pop($taskDetailIds), false, $this->moveAgainDetailLog); + if ($newDetailId) { + return $this->renderJSON(CommonTool::successResult('processCount', 1)); + } else { + return $this->renderJSON(CommonTool::failResult('当前商品数据已失效,暂不支持操作,如有疑问请联系客服')); + } + } else { + $ret = $this->moveUtil->moveAgainDetail($shopId, $taskDetailIds, $this->moveAgainDetailLog); + return $this->renderJSON($ret); + } + } + + public function deleteDeleteTask(){ + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult(ErrorCodeConst::csrfTokenErrorTip)); + } + + $shopId = $_SESSION[SessionConst::shopId]; + $delCnt = 0; + ZC::G('start deleteDeleteTask'); + $detailIds = $this->moveService->getAllDeleteMoveCollectTaskDetailIds($shopId); + + $allChunkedDetailIds = array_chunk($detailIds, 100); + foreach ($allChunkedDetailIds as $sliceDetailIds) { + foreach ($sliceDetailIds as $detailId) { + $delRet = $this->moveService->delMoveTaskDetailHistory($shopId, $detailId); + if ($delRet) { + $delCnt++; + } + } + } + ZC::G('end deleteFailTask'); + + return $this->renderJSON(CommonTool::successResult('total', $delCnt)); + } + + public function batchDeleteTaskDetail() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult('CSRF校验不通过')); + } + + $shopId = $_SESSION[SessionConst::shopId]; + $accessToken = $_SESSION[SessionConst::accessToken]; + $ret = $this->moveUtil->batchDeleteTaskDetail($shopId, $accessToken); + return $this->renderJSON($ret); + } + + public function cancelCollectTask() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult('CSRF校验不通过')); + } + + list($successCancelDetailIds, $skipCancelDetailIds) = $this->moveUtil->cancelCollectTask(); + $html = ''; + if ($skipCancelDetailIds) { + list($processingTaskCount, $taskDetailList,) = $this->productUtil->getHistoryProductList($_SESSION[SessionConst::shopId], ['taskDetailIds' => $skipCancelDetailIds], 1, count($skipCancelDetailIds)); + $html = $this->renderWithoutLayout(array( + 'taskDetailList' => $taskDetailList, + ), 'move/batch/skip_cancel', true); + } + + return $this->renderJSON(CommonTool::successResult([ + 'processCount' => count($successCancelDetailIds), + 'skipCount' => count($skipCancelDetailIds), + 'html' => $html + ])); + } + + public function deleteFailTaskDetail() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult('CSRF校验不通过')); + } + + $shopId = $_SESSION[SessionConst::shopId]; + $delCount = $this->moveService->delMoveHistoryByStatus($shopId, StatusConst::fail); + return $this->renderJSON(CommonTool::successResult('total', $delCount)); + } + + public function deleteSkipTaskDetail() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult('CSRF校验不通过')); + } + + $shopId = $_SESSION[SessionConst::shopId]; + $delCount = $this->moveService->delMoveHistoryByStatus($shopId, StatusConst::skip); + return $this->renderJSON(CommonTool::successResult('total', $delCount)); + } + + + + + public function getDsAuthUrl() { + $shopId = $_SESSION[SessionConst::shopId]; + + $getUrlRet = $this->dsClient->getDsAuthUrl($shopId, AppConst::getDsPlatform(), Zc::C('acn.ds.domain')); + + return $this->renderJSON($getUrlRet); + } + + + + public function checkDsAuthExpire() { + $log = Zc::getLog('tool/fetch/checkAuth'); + $shopId = $_SESSION[SessionConst::shopId]; + + $authCode = $this->shopService->getAuthCodeByShopId($shopId); + if (empty($authCode)) { + return $this->renderJSON(CommonTool::successResult()); + } + + $dsMemberInfo = $this->moveService->getDsMemberInfo($shopId); + + $checkRet = $this->dsClient->checkDsAppAuthExpire(AppConst::getDsPlatform(), [], $dsMemberInfo['cnali_member_id'], $authCode); + $log->info('-----checkRet-----' . print_r($checkRet, true)); + if (CommonTool::isFailRet($checkRet)) { + return $this->renderJSON(CommonTool::successResult()); + } + $checkRet = $checkRet['userIdAndCheckRetMap'][$shopId]; + + if (CommonTool::isSuccessRet($checkRet) || empty($checkRet['code'])) { + return $this->renderJSON(CommonTool::successResult()); + } + + if ($checkRet['code'] == DsConst::authExpireTypeAuthExpire) { + $getUrlRet = $this->dsClient->getDsAuthUrl($shopId, AppConst::getDsPlatform(), Zc::C('acn.ds.domain')); + if (CommonTool::isSuccessRet($getUrlRet)) { + $checkRet['reason'] = sprintf('1688' . DsConst::getDsAppChineseName() . '授权已失效,重新授权', $getUrlRet['redirectUrl']); + } + } else { + $dsBuyUrl = $this->moveService->getDsBuyUrl($shopId); + $checkRet['reason'] = sprintf('1688' . DsConst::getDsAppChineseName() . '已过期,重新订购', $dsBuyUrl); + } + + return $this->renderJSON($checkRet); + } + + private function buildSearchSameProductFilter($sameType, $detailUrls, $shopId, $cluePicUrlNameMap = []) { + if ($sameType == MoveConst::collectSameProductTypeImg) { + if (empty($_FILES['searchSameProductImg'])) { + return CommonTool::failResult('请上传图片'); + } + $moveDir = 'shop/upload/' . $shopId; + $uploadRet = $this->materialUtil->uploadLocalMultipleImageToOss('searchSameProductImg', $moveDir, false); + if (CommonTool::isFailRet($uploadRet)) { + return $uploadRet; + } + $srcs = ZcArrayHelper::getSub($uploadRet['images'], 'src'); + $detailUrls = implode(',', $srcs); + if (empty($detailUrls)) { + return CommonTool::failResult('上传图片失败,请重试'); + } + } + + $detailUrls = array_map('trim', preg_split("/\\r\\n|\\r|\\n|,|,|;|;/u", $detailUrls)); + $detailUrls = array_filter(array_unique($detailUrls)); + if (empty($detailUrls)) { + return CommonTool::failResult('请输入链接'); + } + + $detailUrls = array_slice($detailUrls, 0, 10); + $productsInfoList = []; + if ($sameType == MoveConst::collectSameProductTypeMixContent) { + $linkDetails = []; + $k = mt_rand(1000, 100000); + foreach ($detailUrls as $detailUrl) { + if (CommonTool::checkIsImageLink($detailUrl)) { + $k++; + $productsInfoList[$k] = [ + 'itemId' => $k, + 'imgUrl' => $detailUrl, + 'title' => $cluePicUrlNameMap[$detailUrl] ?: '', + ]; + } else { + $linkDetails[] = $detailUrl; + } + } + + if ($linkDetails) { + $getProductsInfoListRet = $this->moveUtil->getProductsInfoListByDetailUrls(implode(',', $linkDetails), $shopId, null, null, null, null, true); + if (CommonTool::isSuccessRet($getProductsInfoListRet)) { + $fetchProductsInfoList = $getProductsInfoListRet['productsInfoList']; + $fetchProductsInfoList = $this->buildSearchSameProductProductInfoList($fetchProductsInfoList); + $productsInfoList = $productsInfoList + $fetchProductsInfoList; + } + } + } else if ($sameType == MoveConst::collectSameProductTypeLink) { + $getProductsInfoListRet = $this->moveUtil->getProductsInfoListByDetailUrls(implode(',', $detailUrls), $shopId); + if (CommonTool::isFailRet($getProductsInfoListRet)) { + return $getProductsInfoListRet; + } + + $productsInfoList = $getProductsInfoListRet['productsInfoList']; + $productsInfoList = $this->buildSearchSameProductProductInfoList($productsInfoList); + } else if ($sameType == MoveConst::collectSameProductTypeImgUrl || $sameType == MoveConst::collectSameProductTypeImg) { + $k = mt_rand(1000, 100000); + foreach ($detailUrls as $imgUrl) { + $k++; + $productsInfoList[$k] = [ + 'itemId' => $k, + 'imgUrl' => $imgUrl, + 'title' => $cluePicUrlNameMap[$imgUrl] ?: '', + ]; + } + } + + return CommonTool::successResult('productsInfoList', $productsInfoList); + } + + public function searchSameProduct() { + if (!$this->webShop->validateCsrfToken()) { + return $this->renderJSON(CommonTool::failResult(ErrorCodeConst::csrfTokenErrorTip)); + } + + $this->moveBatchUrlLog->info('fetchDetailUrlInfo, shopId[' . $_SESSION[SessionConst::shopId] . '], post: ' . print_r($_POST, true)); + $shopId = $_SESSION[SessionConst::shopId]; + $detailUrls = $_POST['detailUrls']; + $sameType = $_POST['sameType']; + $copyType = $_POST['copyType']; + $cluePicUrlNameMap = $_POST['cluePicUrlNameMap']; + + $checkRet = $this->moveUtil->checkAbnormalRequest($shopId); + if (CommonTool::isFailRet($checkRet)) { + return $this->renderJSON($checkRet); + } + + $ret = $this->buildSearchSameProductFilter($sameType, $detailUrls, $shopId, $cluePicUrlNameMap ?: []); + if (CommonTool::isFailRet($ret)) { + return $this->renderJSON($ret); + } + $productsInfoList = $ret['productsInfoList']; + + if ($copyType == MoveConst::collectLtaoCopy) { + list($productsInfoList) = $this->moveUtil->searchLtaoSameProducts($productsInfoList, $shopId, $cluePicUrlNameMap ?: []); + } else { + $productsInfoList = $this->moveUtil->searchSameProducts($productsInfoList, FetchClientConst::collectTaskSource1688, $shopId, $copyType == MoveConst::collectDsCopy); + } + + $productsInfoList = $this->mergeSameProductIsSelect($productsInfoList); + + + $html = $this->renderWithoutLayout([ + 'productsInfoList' => $productsInfoList, + 'copyType' => $copyType, + ], 'move/batch/search_1688_same_product', true); + + return $this->renderJSON(CommonTool::successResult([ + 'html' => $html, + 'productsInfoList' => $productsInfoList + ])); + } + + private function filterNotDsProducts($productsInfoList, $shopId) { + $i = 0; + foreach ($productsInfoList as &$productsInfo) { + $sameWareList = array_slice($productsInfo['sameWareList'], 0, 20); + $sameWareList = ZcArrayHelper::changeKeyRow($sameWareList, 'itemId'); + $productsInfo['sameWareList'] = $sameWareList; + $productsInfo['sameWareNum'] = count($productsInfo['sameWareList']); + if ($i > 0) { + continue; + } + + $detailUrls = ZcArrayHelper::getSub($productsInfo['sameWareList'], 'itemUrl'); + + $detailUrls = implode(',', $detailUrls); + $getProductInfoListRet = $this->getAlibabaProductsInfoListByDetailUrls($detailUrls, $shopId); + if (CommonTool::isFailRet($getProductInfoListRet)) { + $productsInfo['sameWareList'] = []; + $productsInfo['sameWareNum'] = 0; + $i++; + continue; + } + $itemsInfoList = $getProductInfoListRet['productsInfoList']; + + foreach ($productsInfo['sameWareList'] as $itemId => $itemInfo) { + if (!isset($itemsInfoList[$itemId]) || !$itemsInfoList[$itemId]['isFromDs']) { + unset($productsInfo['sameWareList'][$itemId]); + } + } + $productsInfo['sameWareNum'] = count($productsInfo['sameWareList']); + $productsInfo['hasFilterDs'] = true; + $i++; + } + + return $productsInfoList; + } + + private function buildSearchSameProductProductInfoList($productsInfoList) { + $newProductsInfoList = []; + foreach ($productsInfoList as $productsInfo) { + $imgUrl = $productsInfo['item_image'] ?: reset($productsInfo['image_paths']); + if (empty($imgUrl)) { + continue; + } + $newProductsInfoList[$productsInfo['itemId']] = [ + 'itemId' => $productsInfo['itemId'], + 'source' => $productsInfo['source'], + 'site' => $productsInfo['site'], + 'imgUrl' => $imgUrl, + 'title' => $productsInfo['title'], + 'price' => $productsInfo['sale_price'] ?: $productsInfo['jd_price'] + ]; + } + + return $newProductsInfoList; + } + + private function mergeSameProductIsSelect($productsInfoList) { + foreach ($productsInfoList as &$productsInfo) { + foreach ($productsInfo['sameWareList'] as &$sameProduct) { + $sameProduct['isSelect'] = 0; + unset($sameProduct); + } + unset($productsInfo); + } + + return $productsInfoList; + } + + public function singleRetrySearchSameProduct() { + $shopId = $_SESSION[SessionConst::shopId]; + + $imgUrl = $_POST['imgUrl']; + $copyType = $_POST['copyType']; + $cluePicUrlNameMap = $_POST['cluePicUrlNameMap']; + + $productsInfoList = ['100000' => ['itemId' => 100000, 'imgUrl' => $imgUrl]]; + if ($copyType == MoveConst::collectLtaoCopy) { + list($productsInfoList) = $this->moveUtil->searchLtaoSameProducts($productsInfoList, $shopId, $cluePicUrlNameMap ?: []); + } else { + $productsInfoList = $this->moveUtil->searchSameProducts($productsInfoList, FetchClientConst::collectTaskSource1688, $shopId, $copyType == MoveConst::collectDsCopy); + } + $productsInfoList = $this->mergeSameProductIsSelect($productsInfoList); + + if ($copyType == MoveConst::collectDsCopy) { + $productsInfoList = $this->filterNotDsProducts($productsInfoList, $shopId); + } + + $sameProductInfos = $productsInfoList[100000]; + + return CommonTool::successResult([ + 'sameProductInfos' => $sameProductInfos + ]); + } +} \ No newline at end of file diff --git a/doc/source/service/class.MoveService.php b/doc/source/service/class.MoveService.php new file mode 100644 index 00000000..ecf28803 --- /dev/null +++ b/doc/source/service/class.MoveService.php @@ -0,0 +1,12497 @@ +db = Zc::getDb(); + $this->dd = DdFactory::getDdClient(); + $this->ltaoClient = LtaoFactory::getLtaoClient(); + + $this->queueDao = Zc::singleton(QueueDao::class); + $this->shopDao = Zc::singleton(ShopDao::class); + $this->moveDao = Zc::singleton(MoveDao::class); + $this->productDao = Zc::singleton(ProductDao::class); + $this->areaDao = Zc::singleton(AreaDao::class); + $this->materialDao = Zc::singleton(MaterialDao::class); + $this->moveProductManualSourceDao = Zc::singleton(MoveProductManualSourceDao::class); + + $this->ltaoTool = new LtaoTool(); + + $this->dsClient = Zc::singleton('DsClient'); + $this->fetchBankClient = Zc::singleton('FetchBankClient'); + $this->redis = RedisExt::factory('bizCache'); + $this->solidRedis = RedisExt::factory('solidCache'); + $this->statRedis = RedisExt::factory('statCache'); + + $this->quotaLog = Zc::getLog('move/quota', ZcLog::INFO); + $this->moveLog = Zc::getLog('move/log', ZcLog::INFO); + $this->moveProductPublishBufferLog = Zc::getLog('timer/move/buffer/move_product_publish', ZcLog::INFO); + $this->productPublishLockRedisLog = Zc::getLog('timer/move/publish/product_publish_lock_redis', ZcLog::INFO); + $this->log = Zc::getLog(); + $this->unlockLog = Zc::getLog('move/unlock', ZcLog::INFO); + $this->moveGroupQueueBufferLog = Zc::getLog('timer/move/group/move_buffer', ZcLog::INFO); + $this->countMoveGroupLog = Zc::getLog('timer/move/group/count', ZcLog::INFO); + $this->moveRestoreLog = Zc::getLog('timer/move/move_restore_history/' . date('Ymd') . '/move_restore_history', ZcLog::INFO); + $this->syncMoveSettingLog = Zc::getLog('move/sync_move_setting', ZcLog::INFO); + $this->spider = new PageSpider(array (), null, $_SERVER['REMOTE_ADDR']); + } + + public function saveSysConfig($data) { + $update['gmt_modified'] = date('Y-m-d H:i:s'); + if ($data['qqNum']) { + $update['qq_num'] = $data['qqNum']; + } + if ($data['qqLink']) { + $update['qq_link'] = $data['qqLink']; + } + if ($data['qqGroupNum']) { + $update['qq_group_num'] = $data['qqGroupNum']; + } + if ($data['qqGroupLink']) { + $update['qq_group_link'] = $data['qqGroupLink']; + } + if ($data['name']) { + $appVersionDiffConfig = [ + 'name' => $data['name'], + AppConst::appVersionCodeFree => $data[AppConst::appVersionCodeFree], + AppConst::appVersionCodePaid => $data[AppConst::appVersionCodePaid], + AppConst::appVersionCodeProfessional => $data[AppConst::appVersionCodeProfessional], + ]; + + if (AppConst::isddmsV2()) { + $appVersionDiffConfig[AppConst::appVersionCodeLuxury] = $data[AppConst::appVersionCodeLuxury]; + $appVersionDiffConfig[AppConst::appVersionCodeFlagship] = $data[AppConst::appVersionCodeFlagship]; + } + $update['app_version_diff_config'] = json_encode($appVersionDiffConfig); + } + + $this->db->update('im_config', $update, 'im_config_id = 1'); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqNum', $data['qqNum']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqLink', $data['qqLink']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqGroupNum', $data['qqGroupNum']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqGroupLink', $data['qqGroupLink']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'appVersionDiffConfig', $update['app_version_diff_config']); + } + + public function getSysConfig() { + $sysConfig = $this->redis->hGetAll(RedisKeyConst::sysConfig); + + if ($sysConfig) { + $sysConfig['appVersionDiffConfig'] = json_decode($sysConfig['appVersionDiffConfig'], true); + return $sysConfig; + } + + $sysConfig = $this->db->queryFirstRow('select * from im_config limit 1'); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqNum', $sysConfig['qq_num']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqLink', $sysConfig['qq_link']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqGroupNum', $sysConfig['qq_group_num']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'qqGroupLink', $sysConfig['qq_group_link']); + $this->redis->hSet(RedisKeyConst::sysConfig, 'appVersionDiffConfig', $sysConfig['app_version_diff_config']); + + $sysConfig = $this->redis->hGetAll(RedisKeyConst::sysConfig); + $sysConfig['appVersionDiffConfig'] = json_decode($sysConfig['appVersionDiffConfig'], true); + + return $sysConfig ? $sysConfig : []; + } + + public function recordOrderInfo($orderInfoFromDd) { + $orderInfo['order_id'] = $orderInfoFromDd['order_id']; + $orderInfo['shop_id'] = $orderInfoFromDd['shop_id']; + $orderInfo['service_start_time'] = date('Y-m-d H:i:s', $orderInfoFromDd['service_start_time']); + $orderInfo['service_end_time'] = date('Y-m-d H:i:s', $orderInfoFromDd['service_end_time']); + $orderInfo['status'] = $orderInfoFromDd['status']; + $orderInfo['phone'] = $orderInfoFromDd['phone']; + $orderInfo['pay_amount'] = $orderInfoFromDd['pay_amount']; + $orderInfo['pay_time'] = date('Y-m-d H:i:s', $orderInfoFromDd['pay_time']); + $orderInfo['order_create_time'] = date('Y-m-d H:i:s', $orderInfoFromDd['order_create_time']); + $orderInfo['pay_type'] = $orderInfoFromDd['pay_type']; + $orderInfo['spec_type'] = $orderInfoFromDd['push_sku_info']['spec_type']; + $orderInfo['spec_value'] = $orderInfoFromDd['push_sku_info']['spec_value']; + $orderInfo['price'] = $orderInfoFromDd['push_sku_info']['price']; + $orderInfo['duration'] = $orderInfoFromDd['push_sku_info']['duration']; + $orderInfo['duration_unit'] = $orderInfoFromDd['push_sku_info']['duration_unit']; + $orderInfo['title'] = $orderInfoFromDd['push_sku_info']['title']; + $orderInfo['gmt_create'] = date('Y-m-d H:i:s'); + $orderInfo['gmt_modified'] = date('Y-m-d H:i:s'); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->expireOldVersion($orderInfo); + + list($realDb,) = DbRoute::getDbAndTbl(TblConst::appOrder); + $this->db->useDbIdOnce($realDb)->insert('app_order', $orderInfo); + $this->db->useDbIdOnce('ac')->update('trigger_app_version_limit_log', [ + 'is_upgrade' => 1, + 'upgrade_version' => $orderInfoFromDd['push_sku_info']['spec_value'] + ], 'shop_id = %i and gmt_create > %s', $orderInfoFromDd['shop_id'], date('Y-m-d')); + + $this->shopDao->forceUpdateAppVersionByDb($orderInfo['shop_id']); + if (AppConst::isDd()) { + $this->moveDao->insertDsAsyncNoticeTask($orderInfo['shop_id'], MoveConst::syncShopInfoToDs, ''); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return true; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + private function expireOldVersion($orderInfo) { + if ($orderInfo['spec_type'] != 0) { + return; + } + + list($realDb,) = DbRoute::getDbAndTbl(TblConst::appOrder); + $this->db->useDbIdOnce($realDb)->update('app_order', ['service_end_time' => date('Y-m-d H:i:s')], 'shop_id = %i AND service_end_time > %s AND spec_value != %s', $orderInfo['shop_id'], date('Y-m-d H:i:s'), $orderInfo['spec_value']); + } + + public function getShopExpireTime($shopId) { + return $this->moveDao->getShopExpireTime($shopId); + } + + public function updateMoveConfig($shopId, $expireTime) { + $ret = $this->shopDao->getShopAppVersion($shopId); + $appVersion = $ret['appVersion']; + $appVersionMoveLimit = AppConst::getAppVersionMoveLimit(); + $freeNum = AppConst::getFreeMoveLimit(); + + if(AppConst::isddmsV2()) { + $freeNum = (time() >= strtotime('2022-04-01 00:00:00')) ? 10 : 50; + } + + $moveTotal = $appVersionMoveLimit[$appVersion] ? : $freeNum; + $batchTaskTotal = AppConst::getAppVersionBatchTaskProductLimit($appVersion); + $exportProductTotal = AppConst::getAppVersionExportProductLimit($appVersion); + $detectTaskTotal = AppConst::getAppVersionDetectTaskProductLimit($appVersion); + + $monthFistDate = date('Y-m-01 00:00:00'); + $expireMonthLastDate = date('Y-m-t 23:59:59', strtotime($expireTime)); + + while(true) { + $nextMonthFirstDate = date('Y-m-01 00:00:00', strtotime("+1 months", strtotime($monthFistDate))); + + $spanLastDate = ZcDateHelper::strAddSeconds($nextMonthFirstDate, -1); + if ($spanLastDate <= $expireMonthLastDate) { + $gmtExpireMonthList[] = $spanLastDate; + } + + $monthFistDate = $nextMonthFirstDate; + if ($monthFistDate > $expireMonthLastDate) { + break; + } + } + $this->quotaLog->info("shopId[$shopId], gmtExpireMonthList: " . print_r($gmtExpireMonthList, true)); + return $this->saveMoveShopConfig($shopId, $moveTotal, $batchTaskTotal, $exportProductTotal, $detectTaskTotal, $gmtExpireMonthList); + } + + private function saveMoveShopConfig($shopId, $moveTotal, $batchTaskTotal, $exportProductTotal, $detectTaskTotal, $gmtExpireMonthList) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $configRows = $this->getMoveShopConfigListByShopId($shopId); + $mvcIds = array (); + foreach ($gmtExpireMonthList as $gmtExpireMonth) { + + $existRow = array (); + foreach ($configRows as $row) { + if ($row['gmt_expire'] == $gmtExpireMonth) { + $existRow = $row; + break; + } + } + + if (empty($existRow)) { + $insert = array ( + 'shop_id' => $shopId, + 'total' => $moveTotal, + 'batch_task_product_total' => $batchTaskTotal, + 'export_product_total' => $exportProductTotal, + 'detect_task_product_total' => $detectTaskTotal, + 'ykt_video_create_total' => $moveTotal, + 'node_video_create_total' => $moveTotal, + 'fb_total' => AppConst::getAllowAddFbCountByAppVersion($moveTotal), + 'import_total' => AppConst::getAllowAddFbCountByAppVersion($moveTotal), + 'gmt_expire' => $gmtExpireMonth, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + $r = $this->db->insert('move_shop_config', $insert); + $mvcIds[] = $this->db->lastInsertId(); + + $this->quotaLog->info("insertRow: shopId[$shopId], " . ZcArrayHelper::sp($insert) . "], ret[$r], mscId[" . $this->db->lastInsertId() . ']'); + } else { + $mvcIds[] = $existRow['move_shop_config_id']; + + $realMoveTotal = $moveTotal; + $this->updateMoveShopConfig($shopId, $existRow['move_shop_config_id'], array( + 'total' => $realMoveTotal, + 'batch_task_product_total' => $batchTaskTotal, + 'export_product_total' => $exportProductTotal, + 'detect_task_product_total' => $detectTaskTotal, + 'ykt_video_create_total' => $realMoveTotal, + 'node_video_create_total' => $realMoveTotal, + 'fb_total' => AppConst::getAllowAddFbCountByAppVersion($realMoveTotal), + 'import_total' => AppConst::getAllowAddFbCountByAppVersion($realMoveTotal), + )); + + $this->quotaLog->info("updateRow: shopId[$shopId], oldRow[" . ZcArrayHelper::sp($existRow) . "], newRow, total $moveTotal"); + } + } + + if ($mvcIds) { + $delCount = $this->db->delete('move_shop_config', 'shop_id = %i and move_shop_config_id not in %li and `gmt_expire` > %s', $shopId, $mvcIds, date('Y-m-01 00:00:00', strtotime($gmtExpireMonthList[0]))); + $this->quotaLog->info("deleteRow: shopId[$shopId], mvcIds[" . implode(',', $mvcIds) . "], delCount[" . $delCount . ']'); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return true; + } catch (Exception $ex) { + $this->quotaLog->error("saveMoveShopConfig error message is : " . $ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function checkShopIsExpire($shopId) { + $shopInfo = $this->shopDao->getShop($shopId); + return ($shopInfo['gmt_expire'] < ZcDateHelper::now()) ? true : false; + } + + public function attachDsMoveCopyTotal($shopId) { + return; + $curMonth = date('Y-m-t 23:59:59'); + $moveConfig = $this->db->queryFirstRow("select * from `move_shop_config` where `shop_id` = %i and `gmt_expire` >= now() and `gmt_expire` <= %s", $shopId, $curMonth); + if ($moveConfig['is_attach_ds']) { + return true; + } + + $this->db->update('move_shop_config', [ + 'is_attach_ds' => 1, + 'attach_total' => new ZcDbEval('attach_total + 1000'), + 'gmt_modified' => date('Y-m-d H:i:s') + ], 'move_shop_config_id = %i and is_attach_ds = 0', $moveConfig['move_shop_config_id']); + } + + public function getAvailableCopyCount($shopId) { + if (AppConst::isMsDdOd()) { + return array(); + } + $shopInfo = $this->shopDao->getShop($shopId, AppConst::appDd); + $shopGmtExpire = $shopInfo['gmt_expire']; + if (strtotime($shopGmtExpire) < time()) { + return array(); + } + $this->accountBalancedLastMonth($shopId); + $currentMonthMoveConfig = $this->getCurrentMonthMoveConfig($shopId); + if (empty($currentMonthMoveConfig)) { + return array(); + } + return $currentMonthMoveConfig; + } + + public function getAvailableCopyCountByShopIds($shopIds) { + $moveConfigMap = []; + foreach ($shopIds as $shopId) { + $moveConfigMap[$shopId] = $this->getAvailableCopyCount($shopId); + } + + return $moveConfigMap; + } + + private function getCurrentMonthMoveConfig($shopId) { + return $this->moveDao->getCurrentMonthMoveConfig($shopId); + } + + public function getMoveAttachTotalByShopId($shopId) { + return $this->moveDao->getMoveAttachTotalByShopId($shopId); + } + + private function lockBalanceLastMonth($shopId) { + $lock = $this->db->queryFirstField('select 1 from balance_move_attach_total_log where shop_id = %i and balance_month = %i', $shopId, date('Ym',strtotime('last month'))); + if ($lock) { + return CommonTool::failResult('已经结算'); + } + + try { + $this->db->insert('balance_move_attach_total_log', [ + 'shop_id' => $shopId, + 'balance_month' => date('Ym',strtotime('last month')), + 'gmt_create' => date('Y-m-d H:i:s'), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]); + return CommonTool::successResult(); + } catch (Exception $e) { + return CommonTool::failResult('已经结算'); + } + } + + public function accountBalancedLastMonth($shopId) { + $lockRet = $this->lockBalanceLastMonth($shopId); + if (CommonTool::isFailRet($lockRet)) { + return; + } + + //$needDeductPaidNum有正负概念 + $needDeductPaidNum = $this->getLastMonthNeedDeductPaidNum($shopId); + if (!empty($needDeductPaidNum)) { + if ($needDeductPaidNum > 0) { + $this->moveDao->decreaseMoveAttachTotal($shopId, $needDeductPaidNum); + $this->moveDao->addMoveAttachLog('', $shopId, $needDeductPaidNum, '月结增减'); + } else { + $needIncreaseAttachTotal = abs($needDeductPaidNum); + $this->moveDao->increaseMoveAttachTotal($shopId, $needIncreaseAttachTotal); + $this->moveDao->addMoveAttachLog('', $shopId, $needIncreaseAttachTotal, '月结增减'); + } + + $attachTotal = -$needDeductPaidNum; + $this->moveDao->insertMoveAttachRechargeOrder(array( + 'move_attach_recharge_order_uuid' => new ZcDbEval('uuid()'), + 'shop_id' => $shopId, + 'attach_total' => $attachTotal, + 'order_source' => RechargeConst::orderSourceIsMoveDeduct, + 'status' => StatusConst::paySuccess + )); + } + } + + private function getLastMonthNeedDeductPaidNum($shopId) { + $lastMoveConfig = $this->getLastMoveConfig($shopId); + if (empty($lastMoveConfig) || $lastMoveConfig['is_balanced']) { + return 0; + } + + $this->updateMoveShopConfig($shopId, $lastMoveConfig['move_shop_config_id'], array('is_balanced' => 1)); + $presentNumSurplus = $this->getPresentNumSurplus($lastMoveConfig); + $prePaidFailTotal = $lastMoveConfig['pre_paid_fail_total']; + if ($presentNumSurplus > 0) { + $needDeductPaidNum = -abs($prePaidFailTotal); + return $needDeductPaidNum; + } + + $needDeductPaidNum = abs($presentNumSurplus); + $needDeductPaidNum = $needDeductPaidNum - $prePaidFailTotal; + + + return $needDeductPaidNum; + } + + private function getPresentNumSurplus($moveConfig) { + return $this->moveDao->getPresentNumSurplus($moveConfig); + } + + private function getLastMoveConfig($shopId) { + $curMonth = date('Y-m-t 23:59:59'); + return $this->db->queryFirstRow("select * from `move_shop_config` where `shop_id` = %i and `gmt_expire` < %s order by gmt_expire desc", $shopId, $curMonth); + } + + public function getMoveSettingList($shopId) { + $moveSettingList = $this->db->query('SELECT * FROM move_shop_setting WHERE shop_id = %i ORDER BY is_config_default DESC, move_shop_setting_id DESC', $shopId); + $moveSettingList = $this->replaceMoveSettingBigField($moveSettingList); + $moveSettingList = $this->formatMoveShopSetting($moveSettingList); + $moveSettingList = $this->resetMoveShopSetting($moveSettingList); + $moveSettingList = $this->filterOtherDefaultSetting($moveSettingList); + $moveSettingList = ZcArrayHelper::changeKeyRow($moveSettingList, 'move_shop_setting_id'); + return $moveSettingList; + } + + public function getMoveSettingInfo($shopId, $moveSettingId) { + $moveSettingList = $this->db->query('SELECT * FROM move_shop_setting WHERE shop_id = %i AND move_shop_setting_id = %i', $shopId, $moveSettingId); + $moveSettingList = $this->replaceMoveSettingBigField($moveSettingList); + return $moveSettingList[0]; + } + + private function filterOtherDefaultSetting($moveSettingList) { + $isFindDefault = false; + foreach ($moveSettingList as $settingId => $setting) { + if ($setting['is_config_default'] != 1) { + continue; + } + + if ($isFindDefault) { + unset($moveSettingList[$settingId]); + continue; + } + + $isFindDefault = true; + } + + return $moveSettingList; + } + + private function resetMoveShopSetting($moveSettingList) { + foreach ($moveSettingList as &$moveSetting) { + if(empty($moveSetting['item_num_type'])){ + $moveSetting['item_num_type'] = MoveConst::sourceAddressOnlineWebForcePrefixItemId; + } + if(empty($moveSetting['item_num_type_other'])){ + $moveSetting['item_num_type_other'] = MoveConst::sourceAddressForcePrefixItemId; + } + + $moveSetting['is_title_over_flow_delete'] = 1; + + $moveSetting['pay_type'] = MoveConst::payTypeOnLine; + } + + return $moveSettingList; + } + private function replaceMoveSettingBigField($moveSettingList) { + $bigFieldIdFields = $this->getMoveSettingBigFieldIdFields(); + $fields = $this->getMoveSettingBigFields(); + foreach($moveSettingList as $key => &$val) { + $fieldIds = ZcArrayHelper::filterColumns($val, $bigFieldIdFields); + $bigFieldContents = $this->getMoveSettingBigFieldInfos($fieldIds, $val['shop_id']); + foreach ($fields as $field) { + if (!empty($bigFieldContents[$field])) { + $val[$field] = $bigFieldContents[$field]['content']; + } elseif(!empty($val[$field])) { + continue; + } else { + $val[$field] = ''; + } + } + } + return $moveSettingList; + } + + private function getMoveSettingBigFieldIdFields() { + return array( + 'skip_title_keyword_id', + 'skip_sku_alias_keyword_id', + 'skip_brand_keyword_id', + 'skip_send_city_info_id', + 'title_delete_id', + 'title_search_id', + 'title_replace_id', + 'desc_prefix_id', + 'desc_suffix_id', + 'desc_prefix_img_id', + 'desc_suffix_img_id', + 'quality_report_id', + 'class_quality_id', + 'recommend_remark_search_id', + 'recommend_remark_replace_id', + 'recommend_remark_prefix_id', + 'recommend_remark_suffix_id', + 'preset_attrs_id', + 'preset_cate_attrs_id', + 'sku_alias_delete_id', + 'sku_search_id', + 'sku_replace_id', + 'skip_shop_name_id', + 'range_price_group_id' + ); + } + + private function getMoveSettingBigFields() { + return array( + 'skip_title_keyword', + 'skip_sku_alias_keyword', + 'skip_brand_keyword', + 'skip_send_city_info', + 'title_delete', + 'title_search', + 'title_replace', + 'desc_prefix', + 'desc_suffix', + 'desc_prefix_img', + 'desc_suffix_img', + 'quality_report', + 'class_quality', + 'recommend_remark_search', + 'recommend_remark_replace', + 'recommend_remark_prefix', + 'recommend_remark_suffix', + 'preset_attrs', + 'preset_cate_attrs', + 'sku_alias_delete', + 'sku_search', + 'sku_replace', + 'skip_shop_name', + 'range_price_group' + ); + } + + private function getMoveSettingBigFieldInfos($bigFieldIds, $shopId) { + $queryIds = array(); + $fieldInfos = array(); + + foreach ($bigFieldIds as $field => $id) { + if (is_numeric($id)) { + $queryIds[] = $id; + } + } + if (!empty($queryIds)) { + $fieldInfos = $this->db->query("SELECT * FROM move_shop_setting_big_field WHERE shop_id = %i AND move_shop_setting_big_field_id IN %li", $shopId, $queryIds); + $fieldInfos = ZcArrayHelper::changeKeyRow($fieldInfos, 'field_name'); + } + return $fieldInfos; + } + + private function formatMoveShopSetting($moveSettingList) { + foreach ($moveSettingList as &$moveSetting) { + if(unserialize($moveSetting['title_search'])){ + $moveSetting['title_search'] = unserialize($moveSetting['title_search']); + } + if (unserialize($moveSetting['range_price_group'])) { + $moveSetting['range_price_group'] = unserialize($moveSetting['range_price_group']); + } + + if(unserialize($moveSetting['title_replace'])){ + $moveSetting['title_replace'] = unserialize($moveSetting['title_replace']); + } + + if(unserialize($moveSetting['recommend_remark_search'])){ + $moveSetting['recommend_remark_search'] = unserialize($moveSetting['recommend_remark_search']); + } + + if(unserialize($moveSetting['recommend_remark_replace'])){ + $moveSetting['recommend_remark_replace'] = unserialize($moveSetting['recommend_remark_replace']); + } + + if($moveSetting['class_quality']){ + $moveSetting['class_quality'] = explode(',', $moveSetting['class_quality']); + } + + if($moveSetting['quality_report']){ + $moveSetting['quality_report'] = explode(',', $moveSetting['quality_report']); + } + + if(unserialize($moveSetting['preset_attrs'])) { + $moveSetting['preset_attrs'] = unserialize($moveSetting['preset_attrs']); + } + + if(unserialize($moveSetting['preset_cate_attrs'])) { + $moveSetting['preset_cate_attrs'] = unserialize($moveSetting['preset_cate_attrs']); + } + + if(unserialize($moveSetting['sku_search'])){ + $moveSetting['sku_search'] = unserialize($moveSetting['sku_search']); + } + + if(unserialize($moveSetting['sku_replace'])){ + $moveSetting['sku_replace'] = unserialize($moveSetting['sku_replace']); + } + if (unserialize($moveSetting['common_size_template']) !== false) { + $moveSetting['common_size_template'] = unserialize($moveSetting['common_size_template']); + } + if($moveSetting['presell_time_sku_spec_name_and_stock_percent_map']){ + $moveSetting['presell_time_sku_spec_name_and_stock_percent_map'] = json_decode($moveSetting['presell_time_sku_spec_name_and_stock_percent_map'], true); + } + } + + return $moveSettingList; + } + + public function insertMoveSetting($data) { + $column = $this->getMoveShopSettingColumn(); + $update = ZcArrayHelper::filterColumns($data, $column); + $bigFieldData = $update; + $this->setColumnTitleKeyword($update); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $update = $this->buildMoveSettingBigField($update, array()); + $bigFieldData = CommonTool::safeArrayMerge($bigFieldData, $update); + $update['gmt_modified'] = ZcDbEval::now(); + $update['gmt_create'] = ZcDbEval::now(); + $this->db->insert('move_shop_setting', $update); + $moveShopSettingId = $this->db->lastInsertId(); + + $this->saveProductQualitySetting($update['shop_id'], $moveShopSettingId, $data); + $this->saveSizeTemplateSetting($update['shop_id'], $moveShopSettingId, $data['cate_size_template_map']); + $this->checkAndMoveConfigImageAuditTask($bigFieldData, $data, $update['shop_id'], $moveShopSettingId); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return $moveShopSettingId; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function resetMoveSetting($shopId, $moveSettingId, $data) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $moveSettingList = $this->db->query('SELECT config_name, is_config_default FROM move_shop_setting WHERE shop_id = %i and move_shop_setting_id = %i', $shopId, $moveSettingId); + if (!$moveSettingList) { + return false; + } + $data = array_merge($data, $moveSettingList[0]); + $this->deleteMoveSetting($shopId, [$moveSettingId]); + $newMoveSettingId = $this->insertMoveSetting($data); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + return $newMoveSettingId; + } + + private function getMoveShopSettingColumn() { + return array( + 'shop_id', + 'config_name', + 'is_config_default', + 'length', + 'width', + 'height', + 'weight', + 'process_main_image_type', + 'mobile', + 'delivery_delay_day', + 'freight_template_id', + 'supply_7day_return', + 'step_stock_num', + 'stock_type', + 'assoc_ids', + 'limit_per_buyer', + 'maximum_per_order', + 'minimum_per_order', + 'move_onsale_type', + 'reduce_type', + 'filter_empty_color_img', + 'del_main_img_head_num', + 'del_main_img_tail_num', + 'del_main_img_index_list', + 'keep_first_main_img', + 'tailor_img_type', + 'price_percent', + 'price_add', + 'price_sub', + 'price_tail', + 'price_decimal', + 'price_decimal_diy_value', + 'base_price_type', + 'price_mode', + 'enable_range_price', + 'range_price_group', + 'quantity', + 'reset_sku_stock_num', + 'reset_sku_zero_stock_num', + 'del_sku_stock_num', + 'title_search', + 'title_search_id', + 'title_replace', + 'title_replace_id', + 'title_prefix', + 'title_suffix', + 'title_delete', + 'title_delete_id', + 'title_del_letter', + 'title_del_number', + 'title_del_blank', + 'title_del_e_symbol', + 'title_del_product_num', + 'title_del_brand', + 'title_del_bracket', + 'is_title_over_flow_delete', + 'title_over_flow_delete_type', + 'use_source_mobile_desc', + 'desc_prefix', + 'desc_prefix_id', + 'desc_suffix', + 'desc_suffix_id', + 'desc_prefix_img', + 'desc_prefix_img_id', + 'desc_suffix_img', + 'desc_suffix_img_id', + 'desc_replace', + 'desc_replace_id', + 'desc_copy_type', + 'del_desc_img_head_num', + 'brand_id', + 'brand_name', + 'is_copy_recommend_remark', + 'recommend_remark', + 'item_num_type', + 'item_num_fetch_bank_type', + 'item_num_type_other', + 'item_num_prefix', + 'item_num_suffix', + 'is_build_sku_code', + 'sku_code_rule', + 'sku_code_separator', + 'sku_code_chinese', + 'sku_code_num_start', + 'sku_code_num_step', + 'sku_code_item_num_empty_operate', + 'del_desc_img_tail_num', + 'skip_copied', + 'skip_without_color_img', + 'skip_for_sale_product', + 'skip_has_brand_name', + 'skip_3c_product', + 'skip_global', + 'skip_old_ware', + 'skip_supermarket', + 'skip_season', + 'skip_stock_num', + 'skip_sale_count', + 'skip_min_price', + 'skip_max_price', + 'is_skip_min_credit_level', + 'is_skip_max_credit_level', + 'skip_min_credit_level', + 'skip_max_credit_level', + 'skip_reviews_cnt', + 'skip_review_well_rate', + 'skip_title_keyword', + 'skip_title_keyword_id', + 'skip_sku_alias_keyword', + 'skip_sku_alias_keyword_id', + 'skip_yushou', + 'skip_send_city', + 'skip_send_city_info', + 'skip_shop_name', + 'skip_no_from_ds', + 'recommend_remark_search_id', + 'recommend_remark_replace_id', + 'recommend_remark_prefix_id', + 'recommend_remark_suffix_id', + 'recommend_remark_search', + 'recommend_remark_replace', + 'recommend_remark_prefix', + 'recommend_remark_suffix', + 'skip_brand_keyword', + 'skip_brand_keyword_id', + 'base_market_price_type', + 'market_price_percent', + 'market_price_add', + 'market_price_sub', + 'market_price_tail', + 'market_price_decimal', + 'market_price_decimal_diy_value', + 'skip_match_category_fail', + 'match_fail_use_category_id', + 'pay_type', + 'presell_type', + 'presell_delay', + 'presell_end_time', + 'presell_end_time_type', + 'presell_end_time_delay', + 'presell_time_sku_spec_name_and_stock_percent_map', + 'place_order_delay', + 'quality_report_id', + 'quality_report', + 'class_quality_id', + 'class_quality', + 'preset_attrs', + 'preset_cate_attrs', + 'preset_cate_attrs_id', + 'sku_alias_delete', + 'sku_search', + 'sku_replace', + 'sku_min_price_status', + 'sku_min_price_type', + 'add_sku_min_price_price_percent', + 'add_sku_min_price_price_add', + 'add_sku_min_price_price_sub', + 'add_sku_min_price_price_tail', + 'add_sku_min_price_price_decimal', + 'add_sku_min_price_price_decimal_diy_value', + 'add_sku_min_price_sku_name', + 'add_sku_min_price_quantity', + 'add_sku_price_source', + 'update_sku_min_price_price_percent', + 'update_sku_min_price_price_add', + 'update_sku_min_price_price_sub', + 'update_sku_min_price_price_tail', + 'update_sku_min_price_price_decimal', + 'update_sku_min_price_price_decimal_diy_value', + 'update_sku_min_price_quantity', + 'update_sku_price_source', + 'ali_price_type', + 'no_consign_price_type', + 'use_user_ban_word', + 'use_system_ban_word', + 'auto_filter_ban_word', + 'add_sku_min_price_type', + 'add_sku_min_price_color_img', + 'copy_jd_cid_only', + 'copy_1688_cid_only', + 'copy_pdd_cid_only', + 'copy_ltao_cid_only', + 'is_auto_filling_main_image', + 'image_num_filling_to_num', + 'is_auto_filling_use_sku_img', + 'is_auto_filling_use_desc_img', + 'is_auto_filling_flip_main_img', + 'is_auto_filling_rotating_main_img', + 'is_auto_filling_copy_main_img', + 'is_copy_source_video', + 'is_use_source_white_bg_img', + 'build_white_bg_img_use_main_img_index', + 'is_use_source_long_pic', + 'is_build_long_pic', + 'build_long_pic_mode', + 'build_long_pic_use_main_img_index', + 'common_size_template', + 'is_append_size_template_to_desc', + 'append_size_template_to_desc_position', + 'use_source_presell', + 'presell_delivery_type', + 'source_post_fee_price_add_value', + ); + } + + private function setColumnTitleKeyword(&$data) { + if(is_array($data['title_search'])) { + $data['title_search'] = serialize($data['title_search']); + } + if (is_array($data['range_price_group'])) { + $data['range_price_group'] = serialize($data['range_price_group']); + } + + if(is_array($data['title_replace'])) { + $data['title_replace'] = serialize($data['title_replace']); + } + + if(is_array($data['recommend_remark_search'])) { + $data['recommend_remark_search'] = serialize($data['recommend_remark_search']); + } + + if(is_array($data['recommend_remark_replace'])) { + $data['recommend_remark_replace'] = serialize($data['recommend_remark_replace']); + } + + if(is_array($data['quality_report'])) { + $data['quality_report'] = implode(',', $data['quality_report']); + } + + if(is_array($data['class_quality'])) { + $data['class_quality'] = implode(',', $data['class_quality']); + } + + if(is_array($data['preset_attrs'])) { + $data['preset_attrs'] = serialize($data['preset_attrs']); + } + + if(is_array($data['preset_cate_attrs'])) { + $data['preset_cate_attrs'] = serialize($data['preset_cate_attrs']); + } + + if(is_array($data['sku_search'])) { + $data['sku_search'] = serialize($data['sku_search']); + } + + if(is_array($data['sku_replace'])) { + $data['sku_replace'] = serialize($data['sku_replace']); + } + + if(is_array($data['common_size_template'])) { + $data['common_size_template'] = serialize($data['common_size_template']); + } + } + + private function buildMoveSettingBigField($insertDate, $fieldInfos, $bigFieldIds = array()) { + $bigFields = $this->getMoveSettingBigFields(); + $update = ZcArrayHelper::filterColumns($insertDate, $bigFields); + foreach ($update as $field => $content) { + if (empty($content)) { + $insertDate[$field . '_id'] = null; + } elseif ($fieldInfos[$field]['content'] != $content) { + $insert = array( + 'field_name' => $field, + 'shop_id' => $insertDate['shop_id'], + 'content' => $content, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + $ret = $this->db->insert('move_shop_setting_big_field', $insert); + if ($ret) { + $insertDate[$field . '_id'] = $this->db->lastInsertId(); + } + } else { + $insertDate[$field . '_id'] = $bigFieldIds[$field . '_id']; + } + unset($insertDate[$field]); + } + + return $insertDate; + } + + public function updateMoveSetting($shopId, $moveShopSettingId, $data) { + $moveBatchSettingLog = Zc::getLog('move/batch/setting'); + $column = $this->getMoveShopSettingColumn(); + $update = ZcArrayHelper::filterColumns($data, $column); + $bigFieldData = $update; + $this->setColumnTitleKeyword($update); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $update = $this->updateMoveSettingBigField($update, $moveShopSettingId, $shopId); + $bigFieldData = CommonTool::safeArrayMerge($bigFieldData, $update); + $update['gmt_modified'] = ZcDbEval::now(); + $affRow = $this->db->update('move_shop_setting', $update, ' shop_id = %i AND move_shop_setting_id = %i', $shopId, $moveShopSettingId); + $this->saveProductQualitySetting($shopId, $moveShopSettingId, $data); + $this->saveSizeTemplateSetting($shopId, $moveShopSettingId, $data['cate_size_template_map']); + $this->checkAndMoveConfigImageAuditTask($bigFieldData, $data, $update['shop_id'], $moveShopSettingId); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return $affRow; + + } catch (Exception $ex) { + $moveBatchSettingLog->info('updateMoveSetting error: ' . $ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + private function updateMoveSettingBigField($data, $moveShopSettingId, $shopId) { + $bigFields = $this->getMoveSettingBigFieldIdFields(); + $fieldString = implode(',', $bigFields); + $bigFieldIds = $this->db->queryFirstRow('SELECT %l FROM move_shop_setting WHERE shop_id = %i AND move_shop_setting_id = %i ', $fieldString, $data['shop_id'], $moveShopSettingId); + $fieldInfos = $this->getMoveSettingBigFieldInfos($bigFieldIds, $shopId); + + return $this->buildMoveSettingBigField($data, $fieldInfos, $bigFieldIds); + } + + public function getHasMovedSourceItemIds($shopIds, $sourceItemIds, $source) { + $sourceItemIds = is_array($sourceItemIds) ? $sourceItemIds : array($sourceItemIds); + $shopIds = is_array($shopIds) ? $shopIds : array($shopIds); + + if (empty($sourceItemIds)) { + return array(); + } + + $sources = $this->getRealMoveSources($source); + + $movedProductList = array(); + $ret = $this->db->query("SELECT source_item_id, MAX(gmt_create) latest_gmt_create FROM move_collect_task_detail WHERE shop_id in %li AND source in %ls AND source_item_id IN %ls AND `status` = %s GROUP BY source_item_id", $shopIds, $sources, $sourceItemIds, StatusConst::success); + $movedProductList += ZcArrayHelper::changeKeyRow($ret, 'source_item_id'); + +// if (in_array($source, array(FetchClientConst::collectTaskSourceJd, FetchClientConst::collectTaskSourceSn, FetchClientConst::collectTaskSourceYhd, FetchClientConst::collectTaskSourceZhaojiafang, FetchClientConst::collectTaskSourceSecoo))) { +// $sourceItemIds = $this->filterSourceItemIds($source, $sourceItemIds); +// if (!empty($sourceItemIds)) { +// $ret = $this->db->query("SELECT source_sku_id source_item_id, MAX(gmt_create) latest_gmt_create FROM move_sku_log WHERE shop_id in %li AND source_sku_id IN %ls AND `status` = %s GROUP BY source_sku_id", $shopIds, $sourceItemIds, StatusConst::success); +// $movedProductList += ZcArrayHelper::changeKeyRow($ret, 'source_item_id'); +// } +// } + + return $movedProductList; + } + + public function checkMoveSkipCopied($shopId, $sourceItemId, $source, $moveCollectTaskDetailId) { + + $sources = $this->getRealMoveSources($source); + $ret = $this->db->query("SELECT source_item_id, move_collect_task_detail_id FROM move_collect_task_detail WHERE shop_id = %i AND source in %ls AND source_item_id = %s AND `status` in %ls order by move_collect_task_detail_id asc ", $shopId, $sources, $sourceItemId, [StatusConst::success, StatusConst::processing]); + + if(empty($ret)) { + return false; + } + + if(count($ret) > 1 && $ret[0]['move_collect_task_detail_id'] != $moveCollectTaskDetailId) { + return true; + } + + return false; + } + + private function getRealMoveSources($source) { + $sources = [ + $source, + ]; + if ($realSources = $this->getRealSources($source)) { + $sources = CommonTool::safeArrayMerge($sources, $realSources); + } + + return $sources; + } + + private function getRealSources($source) { + $realSources = ''; + if(in_array($source, [FetchClientConst::collectTaskSourceAuthDd, FetchClientConst::collectTaskSourceDd, FetchClientConst::collectTaskSourceToutiaomall])) { + $realSources = [FetchClientConst::collectTaskSourceAuthDd, FetchClientConst::collectTaskSourceDd, FetchClientConst::collectTaskSourceToutiaomall]; + } + + if(in_array($source, [FetchClientConst::collectTaskSourceAuthPdd, FetchClientConst::collectTaskSourcePinduoduo])) { + $realSources = [FetchClientConst::collectTaskSourceAuthPdd, FetchClientConst::collectTaskSourcePinduoduo]; + } + + if(in_array($source, [FetchClientConst::collectTaskSourceAuthKs, FetchClientConst::collectTaskSourceKs])) { + $realSources = [FetchClientConst::collectTaskSourceAuthKs, FetchClientConst::collectTaskSourceKs]; + } + + if(in_array($source, [FetchClientConst::collectTaskSourceAuthWeidian, FetchClientConst::collectTaskSourceWeidian])) { + $realSources = [FetchClientConst::collectTaskSourceAuthWeidian, FetchClientConst::collectTaskSourceWeidian]; + } + + if(in_array($source, [FetchClientConst::collectTaskSourceAuthYz, FetchClientConst::collectTaskSourceYouZan])) { + $realSources = [FetchClientConst::collectTaskSourceAuthYz, FetchClientConst::collectTaskSourceYouZan]; + } + + return $realSources; + } + + private function filterSourceItemIds($source, $sourceItemIds) { + $sourceItemIds = array_filter($sourceItemIds); + if ($source != FetchClientConst::collectTaskSourceSn) { + return $sourceItemIds; + } + + $newSourceItemIds = array(); + foreach ($sourceItemIds as $sourceItemId) { + $sourceItemIdList = explode('_', $sourceItemId); + if (!empty($sourceItemIdList[1]) && is_numeric($sourceItemIdList[1])) { + $newSourceItemIds[] = $sourceItemIdList[1]; + continue; + } + + if (is_numeric($sourceItemId)) { + $newSourceItemIds[] = $sourceItemId; + } + } + + return $newSourceItemIds; + } + + public function getMovingSourceItemIds($shopIds, $sourceItemIds, $source, $isFrontVerify = true) { + $shopIds = is_array($shopIds) ? $shopIds : array($shopIds); + $movedProductList = array(); + if ($isFrontVerify) { + $moveStatus = array(StatusConst::processing, StatusConst::wait); + } else { + $moveStatus = array(StatusConst::processing); + } + if (empty($sourceItemIds)) { + return $movedProductList; + } + + $sources = $this->getRealMoveSources($source); + $sourceItemIds = is_array($sourceItemIds) ? $sourceItemIds : array($sourceItemIds); + $ret = $this->db->query("SELECT source_item_id, MAX(gmt_create) latest_gmt_create FROM move_collect_task_detail WHERE shop_id in %li AND source in %ls AND source_item_id IN %ls AND `status` IN %ls GROUP BY source_item_id", $shopIds, $sources, $sourceItemIds, $moveStatus); + $movedProductList += ZcArrayHelper::changeKeyRow($ret, 'source_item_id'); + + if (!FetchClientTool::isMultiSkuPageSource($source)) { + return $movedProductList; + } + + $ret = $this->db->query("SELECT sibling_sku_id source_item_id, MAX(gmt_create) latest_gmt_create FROM move_sku_temps WHERE shop_id in %li AND sibling_sku_id IN %ls GROUP BY sibling_sku_id", $shopIds, $sourceItemIds); + $movedProductList += ZcArrayHelper::changeKeyRow($ret, 'source_item_id'); + + return $movedProductList; + } + + public function insertUpdateMoveAdvancedConfig($data, $otherFilterFiled = array()) { + $update = ZcArrayHelper::filterColumns($data, array_merge(array('shop_id', 'is_fast_mode', 'force_category_id', 'is_hide_move_setting', 'website_copy_source', 'website_copy_site', 'large_color_img_nav_mode', 'step2_item_sort'), $otherFilterFiled)); + $update['gmt_modified'] = ZcDbEval::now(); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + return $this->db->insertUpdate('move_shop_advaced_config', $insert, $update); + } + + public function getMoveAdvancedConfig($shopId) { + return $this->db->queryFirstRow('SELECT * FROM move_shop_advaced_config WHERE shop_id = %i', $shopId); + } + + public function getMoveSettingFieldMap() { + return array ( + 'base' => CommonTool::moveSettingFieldMap(), + 'skip' => [ + 'skip' => '跳过配置' + ], + + ); + } + + public function getAllMoveSettingField($filter = []) { + $wheres = array(); + if (!empty($filter['keywords'])) { + $wheres[] = $this->db->prepare('and keywords like %ss', $filter['keywords'], $filter['keywords']); + } + + $whereStr = implode(' ', $wheres); + + $rows = $this->db->query("select * from move_setting_search_field where 1 %l order by move_setting_search_field_id asc", $whereStr); + return $rows; + } + + public function insertUpdateMoveSettingField($update) { + if (empty($update)) { + return false; + } + $update['gmt_modified'] = ZcDbEval::now(); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + + $af = $this->db->insertUpdate('move_setting_search_field', $insert, $update); + return $af === false ? false : true; + } + + public function getAllMoveSettingFieldFromCache() { + $cacheKey = RedisKeyConst::searchMoveSettingFieldArr; + $cacheData = $this->redis->get($cacheKey); + $cacheData = unserialize($cacheData); + if (!empty($cacheData)) { + return $cacheData; + } + + $rows = $this->getAllMoveSettingField(); + $fieldList = ZcArrayHelper::changeKey($rows, 'group_key'); + $moveSettingFieldMap = $this->getMoveSettingFieldMap(); + $moveSettingFieldArr = []; + foreach ($moveSettingFieldMap as $tab => $map) { + foreach($map as $groupKey => $name) { + $moveSettingFieldArr[] = [ + 'id' => $fieldList[$groupKey]['move_setting_search_field_id'], + 'name' => $name, + 'tab' => $tab, + 'groupKey' => $groupKey, + 'keywords' => $fieldList[$groupKey]['keywords'], + ]; + } + } + + if (!empty($rows)) { + $rows = ZcArrayHelper::changeKeyRow($moveSettingFieldArr, 'id'); + $this->redis->setex($cacheKey, 48 * 3600, serialize($moveSettingFieldArr)); + } + + return $moveSettingFieldArr; + } + + public function saveGatherMatchCidData($gatherMatchCidDataList) { + $insertArr = array(); + foreach ($gatherMatchCidDataList as $gatherMatchCidData) { + $insert = array(); + $insert['product_id'] = $gatherMatchCidData['productId']; + $insert['shop_id'] = $gatherMatchCidData['shopId']; + $insert['source'] = $gatherMatchCidData['source']; + $insert['title'] = $gatherMatchCidData['title']; + $insert['site'] = $gatherMatchCidData['site']; + $insert['match_cid'] = $gatherMatchCidData['matchCid']; + $insert['match_path'] = str_ireplace('>', '>', $gatherMatchCidData['matchPath']); + $insert['custom_select_cid'] = $gatherMatchCidData['customSelectCid']; + $insert['custom_select_path'] = str_ireplace('>', '>', $gatherMatchCidData['customSelectPath']); + $insert['source_cat_list'] = str_ireplace('>', '>', $gatherMatchCidData['sourceCatList']); + $insert['gmt_modified'] = ZcDbEval::now(); + $insert['gmt_create'] = ZcDbEval::now(); + if (CommonTool::anyEmpty($insert['product_id'], $insert['shop_id'], $insert['source'])) { + continue; + } + $insertArr[] = $insert; + } + + if (empty($insertArr)) { + return ; + } + + $chunkInsertArr = array_chunk($insertArr, 500); + foreach ($chunkInsertArr as $chunkInsert) { + $this->db->insert('gather_match_cid_data', $chunkInsert); + } + } + + public function checkMoveSetting($setting) { + $moveShopSettingId = $setting['move_shop_setting_id']; + if (!is_numeric($moveShopSettingId)) { + return CommonTool::failResult('获取配置信息失败,请重试或联系客服'); + } + + if ($setting['presell_type'] == MoveConst::presellTypePresell && (is_numeric($setting['presell_delay']) && ($setting['presell_delay'] < 2 || $setting['presell_delay'] > 30 ))) { + return CommonTool::failResult('预售发货时间大于2天小于30天'); + } + + if ($setting['presell_type'] == MoveConst::presellTypePresell && $setting['presell_end_time_type'] == MoveConst::presellEndTimeTypeRelative && (is_numeric($setting['presell_end_time_delay']) && ($setting['presell_end_time_delay'] < 0 || $setting['presell_end_time_delay'] > 29 ))) { + return CommonTool::failResult('预售相对结束时间大于0天小于29天'); + } + + if ($setting['presell_type'] == MoveConst::presellTypeStair && (is_numeric($setting['place_order_delay']) && ($setting['place_order_delay'] < 2 || $setting['place_order_delay'] > 30 ))) { + return CommonTool::failResult('订单生成后发货时间大于2天小于30天'); + } + + if ($setting['presell_type'] == MoveConst::presellConfigLevelNowAndPresell && count($setting['presell_time_sku_spec_name_and_stock_percent_map']) == 1) { + return CommonTool::failResult('现货+预售模式必须选择48小时内发货 以及(5、15、45)天内发货中的一个发货时效'); + } + + if ($setting['limit_per_buyer'] && $setting['maximum_per_order'] && $setting['limit_per_buyer'] < $setting['maximum_per_order']) { + return CommonTool::failResult('每次限购件数不能超过累计限购件数'); + } + + if ($setting['maximum_per_order'] && $setting['minimum_per_order'] && $setting['maximum_per_order'] < $setting['minimum_per_order']) { + return CommonTool::failResult('起售件数不能超过商品每次限购件数'); + } + + if ($setting['limit_per_buyer'] && $setting['minimum_per_order'] && $setting['limit_per_buyer'] < $setting['minimum_per_order']) { + return CommonTool::failResult('起售件数不能超过商品累计限购件数'); + } + + return CommonTool::successResult(); + } + + public function getTaskCondition($setting) { + $condition = array(); + + $checkRet = $this->checkMoveSetting($setting); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + if ($setting['skip_copied'] == MoveConst::skipCopyYes){ + $condition['skipCopied'] = true; + } + if ($setting['delivery_delay_day']) { + $condition['deliveryDelayDay'] = $setting['delivery_delay_day']; + } + if ($setting['freight_template_id']) { + $condition['freightTemplateId'] = $setting['freight_template_id']; + } + if ($setting['reduce_type']) { + $condition['reduceType'] = $setting['reduce_type']; + } + if ($setting['filter_empty_color_img']) { + $condition['filterEmptyColorImg'] = $setting['filter_empty_color_img']; + } + if (is_numeric($setting['supply_7day_return'])) { + $condition['supply7dayReturn'] = $setting['supply_7day_return']; + } + if ($setting['move_onsale_type']) { + $condition['moveOnsaleType'] = $setting['move_onsale_type']; + } + if ($setting['skip_min_price']) { + $condition['skipMinPrice'] = $setting['skip_min_price']; + } + if ($setting['skip_max_price']) { + $condition['skipMaxPrice'] = $setting['skip_max_price']; + } + if ($setting['skip_without_color_img'] == MoveConst::skipWithoutColorImgYes) { + $condition['skipWithoutColorImg'] = true; + } + if ($setting['skip_sale_count'] > 0) { + $condition['skipSaleCount'] = ZcNumberHelper::numFormat($setting['skip_sale_count']); + } + if (!empty($setting['skip_sku_alias_keyword'])) { + $condition['skipSkuAliasKeyword'] = str_replace(',', ',', $setting['skip_sku_alias_keyword']); + } + if (!empty($setting['skip_brand_keyword'])) { + $condition['skipBrandKeyword'] = str_replace(',', ',', $setting['skip_brand_keyword']); + } + + if ((int)trim($setting['quantity']) > 0) { + $condition['quantity'] = (int)trim($setting['quantity']); + } + if ($setting['price_percent'] > 0) { + $condition['price']['pricePercent'] = ZcNumberHelper::numFormat($setting['price_percent']); + } + if ($setting['price_add'] > 0) { + $condition['price']['priceAdd'] = ZcNumberHelper::numFormat($setting['price_add']); + } + if ($setting['price_sub'] > 0) { + $condition['price']['priceSub'] = ZcNumberHelper::numFormat($setting['price_sub']); + } + if (is_numeric($setting['price_tail']) && ($setting['price_tail'] >= 0)) { + $condition['price']['priceTail'] = ZcNumberHelper::numFormat($setting['price_tail']); + } + if ($setting['price_mode']) { + $condition['price']['priceMode'] = $setting['price_mode']; + } + if (!empty($setting['price_decimal'])) { + $condition['price']['priceDecimal'] = $setting['price_decimal']; + } + if (isset($setting['base_price_type'])) { + $condition['price']['basePriceType'] = $setting['base_price_type']; + } + if ($setting['ali_price_type']) { + $condition['price']['aliPriceType'] = $setting['ali_price_type']; + } + if($setting['enable_range_price'] > 0) { + $condition['price']['rangePriceGroup'] = $setting['range_price_group']; + } + if (is_numeric($setting['source_post_fee_price_add_value'])) { + $condition['price']['sourcePostFeePriceAddValue'] = $setting['source_post_fee_price_add_value']; + } + + foreach ($this->getPriceDecimalDiyKeys() as $keyCamelCase => $keyUnderScore) { + $value = isset($setting[$keyUnderScore]) ? preg_replace('/[^\d]/', '', $setting[$keyUnderScore]) : ''; + $value = strlen($value) > 2 ? substr($value, 0, 2) : $value; + if($keyCamelCase == 'marketPriceDecimalDiyValue') { + $condition['marketPrice'][$keyCamelCase] = $value; + } else { + $condition['price'][$keyCamelCase] = $value; + } + } + + if ($setting['market_price_percent'] > 0) { + $condition['marketPrice']['marketPricePercent'] = ZcNumberHelper::numFormat($setting['market_price_percent']); + } + if ($setting['market_price_add'] > 0) { + $condition['marketPrice']['marketPriceAdd'] = ZcNumberHelper::numFormat($setting['market_price_add']); + } + if ($setting['market_price_sub'] > 0) { + $condition['marketPrice']['marketPriceSub'] = ZcNumberHelper::numFormat($setting['market_price_sub']); + } + if ($setting['market_price_tail'] > 0) { + $condition['marketPrice']['marketPriceTail'] = ZcNumberHelper::numFormat($setting['market_price_tail']); + } + if (!empty($setting['market_price_decimal'])) { + $condition['marketPrice']['marketPriceDecimal'] = $setting['market_price_decimal']; + } + if ($setting['base_market_price_type']) { + $condition['marketPrice']['baseMarketPriceType'] = $setting['base_market_price_type']; + } + + if(!empty($setting['title_prefix'])){ + $condition['title']['titlePrefix'] = ltrim($setting['title_prefix']); + } + if(!empty($setting['title_suffix'])){ + $condition['title']['titleSuffix'] = rtrim($setting['title_suffix']); + } + if(!empty($setting['title_search'])){ + $condition['title']['titleSearch'] = $setting['title_search']; + } + if(!empty($setting['title_replace'])){ + $condition['title']['titleReplace'] = $setting['title_replace']; + } + if(!empty($setting['title_delete'])){ + $condition['title']['titleDelete'] = str_replace([',', '、'], ',', $setting['title_delete']); + } + if (!empty($setting['skip_title_keyword'])) { + $condition['skipTitleKeyword'] = str_replace(',', ',', $setting['skip_title_keyword']); + } + + if(!empty($setting['title_del_letter'])){ + $condition['title']['titleDelLetter'] = $setting['title_del_letter']; + } + if(!empty($setting['title_del_number'])){ + $condition['title']['titleDelNumber'] = $setting['title_del_number']; + } + if(!empty($setting['title_del_blank'])){ + $condition['title']['titleDelBlank'] = $setting['title_del_blank']; + } + if(!empty($setting['title_del_product_num'])){ + $condition['title']['titleDelProductNum'] = $setting['title_del_product_num']; + } + if (!empty($setting['title_del_brand'])) { + $condition['title']['titleDelBrand'] = $setting['title_del_brand']; + } + if (!empty($setting['title_del_bracket'])) { + $condition['title']['titleDelBracket'] = $setting['title_del_bracket']; + } + if ($setting['is_title_over_flow_delete']) { + $condition['title']['isTitleOverFlowDelete'] = $setting['is_title_over_flow_delete']; + } + if (!empty($setting['title_over_flow_delete_type'])) { + $condition['title']['titleOverFlowDeleteType'] = $setting['title_over_flow_delete_type']; + } + if (!empty($setting['recommend_remark_search'])) { + $condition['recommendRemarkSearch'] = $setting['recommend_remark_search']; + } + if (!empty($setting['recommend_remark_replace'])) { + $condition['recommendRemarkReplace'] = $setting['recommend_remark_replace']; + } + if (!empty($setting['recommend_remark_prefix'])) { + $condition['recommendRemarkPrefix'] = $setting['recommend_remark_prefix']; + } + if (!empty($setting['recommend_remark_suffix'])) { + $condition['recommendRemarkSuffix'] = $setting['recommend_remark_suffix']; + } + if (!empty($setting['sku_alias_delete'])) { + $condition['skuAliasDelete'] = str_replace([',', '、'], ',', $setting['sku_alias_delete']); + } + + if(!empty($setting['use_source_mobile_desc'])){ + $condition['desc']['useSourceMobileDesc'] = $setting['use_source_mobile_desc']; + } + if(!empty($setting['desc_prefix'])){ + $condition['desc']['descPrefix'] = ltrim($setting['desc_prefix']); + } + if(!empty($setting['desc_suffix'])){ + $condition['desc']['descSuffix'] = rtrim($setting['desc_suffix']); + } + if(!empty($setting['desc_prefix_img'])){ + $condition['desc']['descPrefixImg'] = ltrim($setting['desc_prefix_img']); + } + if(!empty($setting['desc_suffix_img'])){ + $condition['desc']['descSuffixImg'] = rtrim($setting['desc_suffix_img']); + } + + if (!empty($setting['desc_copy_type'])) { + $condition['desc']['descCopyType'] = $setting['desc_copy_type']; + } + + if (!empty($setting['del_desc_img_head_num'])) { + $condition['desc']['delDescImgHeadNum'] = $setting['del_desc_img_head_num']; + } + + if (!empty($setting['del_desc_img_tail_num'])) { + $condition['desc']['delDescImgTailNum'] = $setting['del_desc_img_tail_num']; + } + + if (!empty($setting['del_main_img_head_num'])) { + $condition['delMainImgHeadNum'] = $setting['del_main_img_head_num']; + } + + if (!empty($setting['del_main_img_tail_num'])) { + $condition['delMainImgTailNum'] = $setting['del_main_img_tail_num']; + } + + if (!empty($setting['del_main_img_index_list'])) { + $condition['delMainImgIndexList'] = $setting['del_main_img_index_list']; + } + + if ($setting['keep_first_main_img']) { + $condition['keepFirstMainImg'] = $setting['keep_first_main_img']; + } + + if ($setting['tailor_img_type']) { + $condition['tailorImgType'] = $setting['tailor_img_type']; + } + + if ($setting['process_main_image_type'] > 0) { + $condition['processMainImageType'] = $setting['process_main_image_type']; + } + + if ($setting['first_use_source_delivery'] == 1) { + $condition['firstUseSourceDelivery'] = $setting['first_use_source_delivery']; + } + if ($setting['weight'] > 0) { + $condition['packageInfo']['weight'] = $setting['weight']; + } + if ($setting['length'] > 0) { + $condition['packageInfo']['length'] = $setting['length']; + } + if ($setting['width'] > 0) { + $condition['packageInfo']['width'] = $setting['width']; + } + if ($setting['height'] > 0) { + $condition['packageInfo']['height'] = $setting['height']; + } + + if ($setting['brand_id']) { + $condition['brandId'] = $setting['brand_id']; + } + + if ($setting['brand_name']) { + $condition['brandName'] = $setting['brand_name']; + } + if ($setting['is_copy_recommend_remark']) { + $condition['isCopyRecommendRemark'] = $setting['is_copy_recommend_remark']; + } + if ($setting['recommend_remark']) { + $condition['recommendRemark'] = $setting['recommend_remark']; + } + if ($setting['item_num_type']) { + $condition['itemNumType'] = $setting['item_num_type']; + } + if ($setting['item_num_fetch_bank_type']) { + $condition['itemNumFetchBankType'] = $setting['item_num_fetch_bank_type']; + } + if ($setting['item_num_type_other']) { + $condition['itemNumTypeOther'] = $setting['item_num_type_other']; + } + if ($setting['item_num_prefix']) { + $condition['itemNumPrefix'] = $setting['item_num_prefix']; + } + if ($setting['item_num_suffix']) { + $condition['itemNumSuffix'] = $setting['item_num_suffix']; + } + if ($setting['is_build_sku_code']) { + $condition['isBuildSkuCode'] = $setting['is_build_sku_code']; + } + if ($setting['sku_code_rule']) { + $condition['skuCodeRule'] = $setting['sku_code_rule']; + } + if ($setting['sku_code_separator']) { + $condition['skuCodeSeparator'] = $setting['sku_code_separator']; + } + if ($setting['sku_code_chinese']) { + $condition['skuCodeChinese'] = $setting['sku_code_chinese']; + } + if ($setting['sku_code_num_start']) { + $condition['skuCodeNumStart'] = $setting['sku_code_num_start']; + } + if ($setting['sku_code_num_step']) { + $condition['skuCodeNumStep'] = $setting['sku_code_num_step']; + } + if ($setting['sku_code_item_num_empty_operate']) { + $condition['skuCodeItemNumEmptyOperate'] = $setting['sku_code_item_num_empty_operate']; + } + + if ($setting['skip_stock_num']) { + $condition['skipStockNum'] = $setting['skip_stock_num']; + } + + if ($setting['reset_sku_stock_num']) { + $condition['resetSkuStockNum'] = $setting['reset_sku_stock_num']; + } + + if ($setting['reset_sku_zero_stock_num']) { + $condition['resetSkuZeroStockNum'] = $setting['reset_sku_zero_stock_num']; + } + + if ($setting['skip_has_brand_name'] == MoveConst::skipHasBrandNameYes) { + $condition['skipHasBrandName'] = true; + } + + if ($setting['skip_for_sale_product'] == MoveConst::skipCopyYes) { + $condition['skipForSaleProduct'] = true; + } + + if ($setting['copy_jd_cid_only']) { + $condition['copyJdCidOnly'] = $setting['copy_jd_cid_only']; + } + + if ($setting['copy_1688_cid_only']) { + $condition['copy1688CidOnly'] = $setting['copy_1688_cid_only']; + } + + if ($setting['copy_pdd_cid_only']) { + $condition['copyPddCidOnly'] = $setting['copy_pdd_cid_only']; + } + + if ($setting['copy_ltao_cid_only']) { + $condition['copyLtaoCidOnly'] = $setting['copy_ltao_cid_only']; + } + + if ($setting['skip_season']) { + $condition['skipSeason'] = $setting['skip_season']; + } + + if ($setting['skip_3c_product'] == MoveConst::skipCopyYes) { + $condition['skip3cProduct'] = true; + } + + if ($setting['skip_global'] == MoveConst::skipCopyYes) { + $condition['skipGlobal'] = true; + } + + if ($setting['skip_old_ware'] == MoveConst::skipCopyYes) { + $condition['skipOldWare'] = true; + } + + if ($setting['del_sku_stock_num']) { + $condition['delSkuStockNum'] = $setting['del_sku_stock_num']; + } + + if ($setting['skip_supermarket'] == MoveConst::skipCopyYes) { + $condition['skipSupermarket'] = true; + } + + if ($setting['skip_no_from_ds'] == MoveConst::skipCopyYes) { + $condition['skipNoFromDs'] = true; + } + + if ($setting['is_skip_min_credit_level'] && $setting['skip_min_credit_level']) { + $condition['isSkipMinCreditLevel'] = $setting['is_skip_min_credit_level']; + $condition['skipMinCreditLevel'] = $setting['skip_min_credit_level']; + } + + if ($setting['is_skip_max_credit_level'] && $setting['skip_max_credit_level']) { + $condition['isSkipMaxCreditLevel'] = $setting['is_skip_max_credit_level']; + $condition['skipMaxCreditLevel'] = $setting['skip_max_credit_level']; + } + + if ($setting['skip_reviews_cnt']) { + $condition['skipReviewsCnt'] = $setting['skip_reviews_cnt']; + } + + if ($setting['skip_review_well_rate']) { + $condition['skipReviewsWellRate'] = $setting['skip_review_well_rate']; + } + + + if (is_numeric($setting['skip_match_category_fail'])) { + $condition['skipMatchCategoryFail'] = $setting['skip_match_category_fail']; + } + + if ($setting['skip_yushou'] > 0) { + $condition['skipYushou'] = $setting['skip_yushou']; + } + if ($setting['skip_send_city'] > 0) { + $condition['skipSendCity'] = $setting['skip_send_city']; + } + if($setting['skip_send_city_info']) { + $condition['skipSendCityInfo'] = $setting['skip_send_city_info']; + } + + if (is_numeric($setting['match_fail_use_category_id'])) { + $condition['matchFailUseCategoryId'] = $setting['match_fail_use_category_id']; + } + + if (is_numeric($setting['quality_report_id'])) { + $condition['qualityReportId'] = $setting['quality_report_id']; + } + + if (is_numeric($setting['class_quality_id'])) { + $condition['classQualityId'] = $setting['class_quality_id']; + } + + if (is_numeric($setting['pay_type'])) { + $condition['payType'] = $setting['pay_type']; + } + + if (is_numeric($setting['presell_type'])) { + $condition['presellType'] = $setting['presell_type']; + } + + if (is_numeric($setting['presell_delay'])) { + $condition['presellDelay'] = $setting['presell_delay']; + } + + if (is_numeric($setting['presell_delivery_type'])) { + $condition['presellDeliveryType'] = $setting['presell_delivery_type']; + } + + if (is_numeric($setting['place_order_delay'])) { + $condition['placeOrderDelay'] = $setting['place_order_delay']; + } + + if ($setting['presell_end_time']) { + $condition['presellEndTime'] = $setting['presell_end_time']; + } + + if (is_numeric($setting['presell_end_time_type'])) { + $condition['presellEndTimeType'] = $setting['presell_end_time_type']; + } + + if (is_numeric($setting['presell_end_time_delay'])) { + $condition['presellEndTimeDelay'] = $setting['presell_end_time_delay']; + } + + if ($setting['presell_time_sku_spec_name_and_stock_percent_map']) { + $condition['presellTimeSkuSpecNameAndStockPercentMap'] = $setting['presell_time_sku_spec_name_and_stock_percent_map']; + } + + if ($setting['step_stock_num']) { + $condition['stepStockNum'] = $setting['step_stock_num']; + } + + if (isset($setting['stock_type'])) { + $condition['stockType'] = $setting['stock_type']; + } + + if ($setting['assoc_ids']) { + $condition['assocIds'] = $setting['assoc_ids']; + } + + if ($setting['limit_per_buyer']) { + $condition['limitPerBuyer'] = $setting['limit_per_buyer']; + } + + if ($setting['maximum_per_order']) { + $condition['maximumPerOrder'] = $setting['maximum_per_order']; + } + + if ($setting['minimum_per_order']) { + $condition['minimumPerOrder'] = $setting['minimum_per_order']; + } + + if (!empty($setting['preset_attrs'])) { + $condition['presetAttrs'] = $this->getEnablePresetAttrs($setting['preset_attrs']); + } + + if (!empty($setting['preset_cate_attrs'])) { + $condition['presetCateAttrs'] = $setting['preset_cate_attrs']; + } + + if (!empty($setting['task_preset_attrs'])) { + $condition['taskPresetAttrs'] = $this->getEnablePresetAttrs($setting['task_preset_attrs']); + } + + if (!empty($setting['task_quality_map'])) { + $condition['taskQualityMap'] = $setting['task_quality_map']; + } + + if(!empty($setting['sku_search'])){ + $condition['sku']['skuSearch'] = $setting['sku_search']; + } + + if(!empty($setting['sku_replace'])){ + $condition['sku']['skuReplace'] = $setting['sku_replace']; + } + + if (isset($setting['sku_min_price_status'])) { + $condition['price']['skuMinPriceStatus'] = $setting['sku_min_price_status']; + } + + if ($setting['sku_min_price_type']) { + $condition['price']['skuMinPriceType'] = $setting['sku_min_price_type']; + } + + if ($setting['add_sku_min_price_price_percent']) { + $condition['price']['addSkuMinPricePricePercent'] = $setting['add_sku_min_price_price_percent']; + } + + if ($setting['add_sku_min_price_price_add']) { + $condition['price']['addSkuMinPricePriceAdd'] = $setting['add_sku_min_price_price_add']; + } + + if ($setting['add_sku_min_price_price_sub']) { + $condition['price']['addSkuMinPricePriceSub'] = $setting['add_sku_min_price_price_sub']; + } + + if ($setting['add_sku_min_price_price_tail']) { + $condition['price']['addSkuMinPricePriceTail'] = $setting['add_sku_min_price_price_tail']; + } + + if ($setting['add_sku_min_price_price_decimal']) { + $condition['price']['addSkuMinPricePriceDecimal'] = $setting['add_sku_min_price_price_decimal']; + } + + if ($setting['add_sku_min_price_sku_name']) { + $condition['price']['addSkuMinPriceSkuName'] = $setting['add_sku_min_price_sku_name']; + } + + if (isset($setting['add_sku_min_price_quantity'])) { + $condition['price']['addSkuMinPriceQuantity'] = $setting['add_sku_min_price_quantity']; + } + + if (isset($setting['add_sku_price_source'])) { + $condition['price']['addSkuPriceSource'] = $setting['add_sku_price_source']; + } + + if ($setting['update_sku_min_price_price_percent']) { + $condition['price']['updateSkuMinPricePricePercent'] = $setting['update_sku_min_price_price_percent']; + } + + if ($setting['update_sku_min_price_price_add']) { + $condition['price']['updateSkuMinPricePriceAdd'] = $setting['update_sku_min_price_price_add']; + } + + if ($setting['update_sku_min_price_price_sub']) { + $condition['price']['updateSkuMinPricePriceSub'] = $setting['update_sku_min_price_price_sub']; + } + + if ($setting['update_sku_min_price_price_tail']) { + $condition['price']['updateSkuMinPricePriceTail'] = $setting['update_sku_min_price_price_tail']; + } + + if ($setting['update_sku_min_price_price_decimal']) { + $condition['price']['updateSkuMinPricePriceDecimal'] = $setting['update_sku_min_price_price_decimal']; + } + + if (isset($setting['update_sku_min_price_quantity'])) { + $condition['price']['updateSkuMinPriceQuantity'] = $setting['update_sku_min_price_quantity']; + } + + if (isset($setting['update_sku_price_source'])) { + $condition['price']['updateSkuPriceSource'] = $setting['update_sku_price_source']; + } + + if (isset($setting['add_sku_min_price_type'])) { + $condition['price']['addSkuMinPriceType'] = $setting['add_sku_min_price_type']; + } + if (isset($setting['add_sku_min_price_color_img'])) { + $condition['price']['addSkuMinPriceColorImg'] = $setting['add_sku_min_price_color_img']; + } + if (isset($setting['common_size_template'])) { + $condition['commonSizeTemplate'] = $setting['common_size_template']; + } + if (isset($setting['is_append_size_template_to_desc'])) { + $condition['isAppendSizeTemplateToDesc'] = $setting['is_append_size_template_to_desc']; + } + if (isset($setting['append_size_template_to_desc_position'])) { + $condition['appendSizeTemplateToDescPosition'] = $setting['append_size_template_to_desc_position']; + } + if (isset($setting['use_source_presell'])) { + $condition['useSourcePresell'] = $setting['use_source_presell']; + } + + if($setting['is_auto_filling_main_image']) { + $condition['autoFillingMainImage']['isAutoFillingImage'] = $setting['is_auto_filling_main_image']; + $condition['autoFillingMainImage']['imageNumFillingToNum'] = $setting['image_num_filling_to_num']; + $condition['autoFillingMainImage']['isAutoFillingUseSkuImg'] = $setting['is_auto_filling_use_sku_img']; + $condition['autoFillingMainImage']['isAutoFillingUseDescImg'] = $setting['is_auto_filling_use_desc_img']; + $condition['autoFillingMainImage']['isAutoFillingFlipMainImg'] = $setting['is_auto_filling_flip_main_img']; + $condition['autoFillingMainImage']['isAutoFillingRotatingMainImg'] = $setting['is_auto_filling_rotating_main_img']; + $condition['autoFillingMainImage']['isAutoFillingCopyMainImg'] = $setting['is_auto_filling_copy_main_img']; + } + + $condition['mobile'] = $setting['mobile']; + $condition['skipShopName'] = $setting['skip_shop_name']; + + $condition['useUserBanWord'] = $setting['use_user_ban_word'] ? : 0; + $condition['autoFilterBanWord'] = $setting['auto_filter_ban_word'] ? 1 : 0; + $condition['useSystemBanWord'] = $setting['use_system_ban_word'] ? : 0; + $condition['moveShopSettingId'] = $setting['move_shop_setting_id'] ? : 0; + $condition['noConsignPriceType'] = $setting['no_consign_price_type'] ? 1 : 0; + + if (isset($setting['is_copy_source_video'])) { + $condition['isCopySourceVideo'] = $setting['is_copy_source_video']; + } + if (isset($setting['is_use_source_white_bg_img'])) { + $condition['isUseSourceWhiteBgImg'] = $setting['is_use_source_white_bg_img']; + } + if (isset($setting['build_white_bg_img_use_main_img_index'])) { + $condition['buildWhiteBgImgUseMainImgIndex'] = (int) $setting['build_white_bg_img_use_main_img_index']; + } + if (isset($setting['is_use_source_long_pic'])) { + $condition['isUseSourceLongPic'] = $setting['is_use_source_long_pic']; + } + if (isset($setting['is_build_long_pic'])) { + $condition['isBuildLongPic'] = $setting['is_build_long_pic']; + } + if (isset($setting['build_long_pic_mode'])) { + $condition['buildLongPicMode'] = $setting['build_long_pic_mode']; + } + if (isset($setting['build_long_pic_use_main_img_index'])) { + $condition['buildLongPicUseMainImgIndex'] = (int) $setting['build_long_pic_use_main_img_index']; + } + + return CommonTool::successResult('condition', $condition); + } + + public function getSettingFromCondition($condition) { + $setting = array(); + if ($condition['skipCopied'] == true) { + $setting['skip_copied'] = MoveConst::skipCopyYes; + } + if ($condition['deliveryDelayDay']) { + $setting['delivery_delay_day'] = $condition['deliveryDelayDay']; + } + if ($condition['freightTemplateId']) { + $setting['freight_template_id'] = $condition['freightTemplateId']; + } + if ($condition['reduceType']) { + $setting['reduce_type'] = $condition['reduceType']; + } + if ($condition['filterEmptyColorImg']) { + $setting['filter_empty_color_img'] = $condition['filterEmptyColorImg']; + } + if ($condition['supply7dayReturn']) { + $setting['supply_7day_return'] = $condition['supply7dayReturn']; + } + if ($condition['moveOnsaleType']) { + $setting['move_onsale_type'] = $condition['moveOnsaleType']; + } + if ($condition['skipMinPrice']) { + $setting['skip_min_price'] = $condition['skipMinPrice']; + } + if ($condition['skipMaxPrice']) { + $setting['skip_max_price'] = $condition['skipMaxPrice']; + } + if ($condition['skipWithoutColorImg']) { + $setting['skip_without_color_img'] = MoveConst::skipWithoutColorImgYes; + } + if ($condition['skipSaleCount']) { + $setting['skip_sale_count'] = $condition['skipSaleCount']; + } + if ($condition['skipSkuAliasKeyword']) { + $setting['skip_sku_alias_keyword'] = $condition['skipSkuAliasKeyword']; + } + if ($condition['skipBrandKeyword']) { + $setting['skip_brand_keyword'] = $condition['skipBrandKeyword']; + } + if ($condition['quantity']) { + $setting['quantity'] = $condition['quantity']; + } + if (isset($condition['price']['pricePercent'])) { + $setting['price_percent'] = $condition['price']['pricePercent']; + } + if ($condition['sourcePostFeePriceAddValue']) { + $setting['source_post_fee_price_add_value'] = $condition['price']['sourcePostFeePriceAddValue']; + } + if (isset($condition['price']['priceAdd'])) { + $setting['price_add'] = $condition['price']['priceAdd']; + } + if (isset($condition['price']['priceSub'])) { + $setting['price_sub'] = $condition['price']['priceSub']; + } + if (isset($condition['price']['priceTail'])) { + $setting['price_tail'] = $condition['price']['priceTail']; + } + if (isset($condition['price']['priceMode'])) { + $setting['price_mode'] = $condition['price']['priceMode']; + } + if (isset($condition['price']['priceDecimal'])) { + $setting['price_decimal'] = $condition['price']['priceDecimal']; + } + if (isset($condition['price']['basePriceType'])) { + $setting['base_price_type'] = $condition['price']['basePriceType']; + } + if (isset($condition['price']['aliPriceType'])) { + $setting['ali_price_type'] = $condition['price']['aliPriceType']; + } + if (isset($condition['price']['rangePriceGroup'])) { + $setting['enable_range_price'] = $condition['price']['rangePriceGroup']; + } + foreach ($this->getPriceDecimalDiyKeys() as $keyCamelCase => $keyUnderScore) { + $priceKey = $keyCamelCase == 'marketPriceDecimalDiyValue' ? 'marketPrice' : 'price'; + if (isset($condition[$priceKey][$keyCamelCase])) { + $setting[$keyUnderScore] = $condition[$priceKey][$keyCamelCase]; + } + } + if (isset($condition['marketPrice']['marketPricePercent'])) { + $setting['market_price_percent'] = $condition['marketPrice']['marketPricePercent']; + } + if (isset($condition['marketPrice']['marketPriceAdd'])) { + $setting['market_price_add'] = $condition['marketPrice']['marketPriceAdd']; + } + if (isset($condition['marketPrice']['marketPriceSub'])) { + $setting['market_price_sub'] = $condition['marketPrice']['marketPriceSub']; + } + if (isset($condition['marketPrice']['marketPriceTail'])) { + $setting['market_price_tail'] = $condition['marketPrice']['marketPriceTail']; + } + if (isset($condition['marketPrice']['marketPriceDecimal'])) { + $setting['market_price_decimal'] = $condition['marketPrice']['marketPriceDecimal']; + } + if (isset($condition['marketPrice']['baseMarketPriceType'])) { + $setting['base_market_price_type'] = $condition['marketPrice']['baseMarketPriceType']; + } + if (isset($condition['title']['titlePrefix'])) { + $setting['title_prefix'] = $condition['title']['titlePrefix']; + } + if (isset($condition['title']['titleSuffix'])) { + $setting['title_suffix'] = $condition['title']['titleSuffix']; + } + if (isset($condition['title']['titleSearch'])) { + $setting['title_search'] = $condition['title']['titleSearch']; + } + if (isset($condition['title']['titleReplace'])) { + $setting['title_replace'] = $condition['title']['titleReplace']; + } + if (isset($condition['title']['titleDelete'])) { + $setting['title_delete'] = $condition['title']['titleDelete']; + } + if (isset($condition['skipTitleKeyword'])) { + $setting['skip_title_keyword'] = $condition['skipTitleKeyword']; + } + if (isset($condition['title']['titleDelLetter'])) { + $setting['title_del_letter'] = $condition['title']['titleDelLetter']; + } + if (isset($condition['title']['titleDelNumber'])) { + $setting['title_del_number'] = $condition['title']['titleDelNumber']; + } + if (isset($condition['title']['titleDelBlank'])) { + $setting['title_del_blank'] = $condition['title']['titleDelBlank']; + } + if (isset($condition['title']['titleDelProductNum'])) { + $setting['title_del_product_num'] = $condition['title']['titleDelProductNum']; + } + if (isset($condition['title']['titleDelBrand'])) { + $setting['title_del_brand'] = $condition['title']['titleDelBrand']; + } + if (isset($condition['title']['titleDelBracket'])) { + $setting['title_del_bracket'] = $condition['title']['titleDelBracket']; + } + if (isset($condition['title']['isTitleOverFlowDelete'])) { + $setting['is_title_over_flow_delete'] = $condition['title']['isTitleOverFlowDelete']; + } + if (isset($condition['title']['titleOverFlowDeleteType'])) { + $setting['title_over_flow_delete_type'] = $condition['title']['titleOverFlowDeleteType']; + } + if (isset($condition['recommendRemarkSearch'])) { + $setting['recommend_remark_search'] = $condition['recommendRemarkSearch']; + } + if (isset($condition['recommendRemarkReplace'])) { + $setting['recommend_remark_replace'] = $condition['recommendRemarkReplace']; + } + if (isset($condition['recommendRemarkPrefix'])) { + $setting['recommend_remark_prefix'] = $condition['recommendRemarkPrefix']; + } + if (isset($condition['recommendRemarkSuffix'])) { + $setting['recommend_remark_suffix'] = $condition['recommendRemarkSuffix']; + } + if (isset($condition['skuAliasDelete'])) { + $setting['sku_alias_delete'] = $condition['skuAliasDelete']; + } + if (isset($condition['desc']['useSourceMobileDesc'])) { + $setting['use_source_mobile_desc'] = $condition['desc']['useSourceMobileDesc']; + } + if (isset($condition['desc']['descPrefix'])) { + $setting['desc_prefix'] = $condition['desc']['descPrefix']; + } + if (isset($condition['desc']['descSuffix'])) { + $setting['desc_suffix'] = $condition['desc']['descSuffix']; + } + if (isset($condition['desc']['descPrefixImg'])) { + $setting['desc_prefix_img'] = $condition['desc']['descPrefixImg']; + } + if (isset($condition['desc']['descSuffixImg'])) { + $setting['desc_suffix_img'] = $condition['desc']['descSuffixImg']; + } + if (isset($condition['desc']['descCopyType'])) { + $setting['desc_copy_type'] = $condition['desc']['descCopyType']; + } + if (isset($condition['desc']['delDescImgHeadNum'])) { + $setting['del_desc_img_head_num'] = $condition['desc']['delDescImgHeadNum']; + } + if (isset($condition['desc']['delDescImgTailNum'])) { + $setting['del_desc_img_tail_num'] = $condition['desc']['delDescImgTailNum']; + } + if (isset($condition['delMainImgHeadNum'])) { + $setting['del_main_img_head_num'] = $condition['delMainImgHeadNum']; + } + if (isset($condition['delMainImgTailNum'])) { + $setting['del_main_img_tail_num'] = $condition['delMainImgTailNum']; + } + if (isset($condition['delMainImgIndexList'])) { + $setting['del_main_img_index_list'] = $condition['delMainImgIndexList']; + } + if (isset($condition['keepFirstMainImg'])) { + $setting['keep_first_main_img'] = $condition['keepFirstMainImg']; + } + if (isset($condition['tailorImgType'])) { + $setting['tailor_img_type'] = $condition['tailorImgType']; + } + if (isset($condition['processMainImageType'])) { + $setting['process_main_image_type'] = $condition['processMainImageType']; + } + if (isset($condition['firstUseSourceDelivery'])) { + $setting['first_use_source_delivery'] = $condition['firstUseSourceDelivery']; + } + if (isset($condition['packageInfo']['weight'])) { + $setting['weight'] = $condition['packageInfo']['weight']; + } + if (isset($condition['packageInfo']['length'])) { + $setting['length'] = $condition['packageInfo']['length']; + } + if (isset($condition['packageInfo']['width'])) { + $setting['width'] = $condition['packageInfo']['width']; + } + if (isset($condition['packageInfo']['height'])) { + $setting['height'] = $condition['packageInfo']['height']; + } + if (isset($condition['brandId'])) { + $setting['brand_id'] = $condition['brandId']; + } + if (isset($condition['brandName'])) { + $setting['brand_name'] = $condition['brandName']; + } + if (isset($condition['isCopyRecommendRemark'])) { + $setting['is_copy_recommend_remark'] = $condition['isCopyRecommendRemark']; + } + if (isset($condition['recommendRemark'])) { + $setting['recommend_remark'] = $condition['recommendRemark']; + } + if (isset($condition['itemNumType'])) { + $setting['item_num_type'] = $condition['itemNumType']; + } + if (isset($condition['itemNumFetchBankType'])) { + $setting['item_num_fetch_bank_type'] = $condition['itemNumFetchBankType']; + } + if (isset($condition['itemNumTypeOther'])) { + $setting['item_num_type_other'] = $condition['itemNumTypeOther']; + } + if (isset($condition['itemNumPrefix'])) { + $setting['item_num_prefix'] = $condition['itemNumPrefix']; + } + if (isset($condition['itemNumSuffix'])) { + $setting['item_num_suffix'] = $condition['itemNumSuffix']; + } + if (isset($condition['isBuildSkuCode'])) { + $setting['is_build_sku_code'] = $condition['isBuildSkuCode']; + } + if (isset($condition['skuCodeRule'])) { + $setting['sku_code_rule'] = $condition['skuCodeRule']; + } + if (isset($condition['skuCodeSeparator'])) { + $setting['sku_code_separator'] = $condition['skuCodeSeparator']; + } + if (isset($condition['skuCodeChinese'])) { + $setting['sku_code_chinese'] = $condition['skuCodeChinese']; + } + if (isset($condition['skuCodeNumStart'])) { + $setting['sku_code_num_start'] = $condition['skuCodeNumStart']; + } + if (isset($condition['skuCodeNumStep'])) { + $setting['sku_code_num_step'] = $condition['skuCodeNumStep']; + } + if (isset($condition['skuCodeItemNumEmptyOperate'])) { + $setting['sku_code_item_num_empty_operate'] = $condition['skuCodeItemNumEmptyOperate']; + } + if (isset($condition['skipStockNum'])) { + $setting['skip_stock_num'] = $condition['skipStockNum']; + } + if (isset($condition['resetSkuStockNum'])) { + $setting['reset_sku_stock_num'] = $condition['resetSkuStockNum']; + } + if (isset($condition['resetSkuZeroStockNum'])) { + $setting['reset_sku_zero_stock_num'] = $condition['resetSkuZeroStockNum']; + } + if ($condition['skipHasBrandName']) { + $setting['skip_has_brand_name'] = MoveConst::skipHasBrandNameYes; + } + if ($condition['skipForSaleProduct']) { + $setting['skip_for_sale_product'] = MoveConst::skipCopyYes; + } + if (isset($condition['copyJdCidOnly'])) { + $setting['copy_jd_cid_only'] = $condition['copyJdCidOnly']; + } + if (isset($condition['copy1688CidOnly'])) { + $setting['copy_1688_cid_only'] = $condition['copy1688CidOnly']; + } + if (isset($condition['copyPddCidOnly'])) { + $setting['copy_pdd_cid_only'] = $condition['copyPddCidOnly']; + } + if (isset($condition['copyLtaoCidOnly'])) { + $setting['copy_ltao_cid_only'] = $condition['copyLtaoCidOnly']; + } + if (isset($condition['skipSeason'])) { + $setting['skip_season'] = $condition['skipSeason']; + } + if ($condition['skip3cProduct']) { + $setting['skip_3c_product'] = MoveConst::skipCopyYes; + } + if ($condition['skipGlobal']) { + $setting['skip_global'] = MoveConst::skipCopyYes; + } + if ($condition['skipOldWare']) { + $setting['skip_old_ware'] = MoveConst::skipCopyYes; + } + if ($condition['skipSupermarket']) { + $setting['skip_supermarket'] = MoveConst::skipCopyYes; + } + if ($condition['delSkuStockNum']) { + $setting['del_sku_stock_num'] = $condition['delSkuStockNum']; + } + if ($condition['isSkipMinCreditLevel'] && $condition['skipMinCreditLevel']) { + $setting['is_skip_min_credit_level'] = $condition['isSkipMinCreditLevel']; + $setting['skip_min_credit_level'] = $condition['skipMinCreditLevel']; + } + if ($condition['isSkipMaxCreditLevel'] && $condition['skipMaxCreditLevel']) { + $setting['is_skip_max_credit_level'] = $condition['isSkipMaxCreditLevel']; + $setting['skip_max_credit_level'] = $condition['skipMaxCreditLevel']; + } + if ($condition['skipReviewsCnt']) { + $setting['skip_reviews_cnt'] = $condition['skipReviewsCnt']; + } + if ($condition['skipReviewsWellRate']) { + $setting['skip_review_well_rate'] = $condition['skipReviewsWellRate']; + } + if (isset($condition['skipMatchCategoryFail'])) { + $setting['skip_match_category_fail'] = $condition['skipMatchCategoryFail']; + } + if (isset($condition['skipYushou'])) { + $setting['skip_yushou'] = $condition['skipYushou']; + } + if (isset($condition['skipSendCity'])) { + $setting['skip_send_city'] = $condition['skipSendCity']; + } + if (isset($condition['skipNoFromDs'])) { + $setting['skip_no_from_ds'] = $condition['skipNoFromDs']; + } + if (isset($condition['matchFailUseCategoryId'])) { + $setting['match_fail_use_category_id'] = $condition['matchFailUseCategoryId']; + } + if (isset($condition['qualityReportId'])) { + $setting['quality_report_id'] = $condition['qualityReportId']; + } + if (isset($condition['classQualityId'])) { + $setting['class_quality_id'] = $condition['classQualityId']; + } + if (isset($condition['payType'])) { + $setting['pay_type'] = $condition['payType']; + } + if (isset($condition['presellType'])) { + $setting['presell_type'] = $condition['presellType']; + } + if (isset($condition['presellDelay'])) { + $setting['presell_delay'] = $condition['presellDelay']; + } + if (isset($condition['placeOrderDelay'])) { + $setting['place_order_delay'] = $condition['placeOrderDelay']; + } + if (isset($condition['presellEndTime'])) { + $setting['presell_end_time'] = $condition['presellEndTime']; + } + if (isset($condition['presellEndTimeType'])) { + $setting['presell_end_time_type'] = $condition['presellEndTimeType']; + } + if (isset($condition['presellEndTimeDelay'])) { + $setting['presell_end_time_delay'] = $condition['presellEndTimeDelay']; + } + if (isset($condition['presellTimeSkuSpecNameAndStockPercentMap'])) { + $setting['presell_time_sku_spec_name_and_stock_percent_map'] = $condition['presellTimeSkuSpecNameAndStockPercentMap']; + } + if (isset($condition['stepStockNum'])) { + $setting['step_stock_num'] = $condition['stepStockNum']; + } + if (isset($condition['stockType'])) { + $setting['stock_type'] = $condition['stockType']; + } + if (isset($condition['assocIds'])) { + $setting['assoc_ids'] = $condition['assocIds']; + } + if (isset($condition['limitPerBuyer'])) { + $setting['limit_per_buyer'] = $condition['limitPerBuyer']; + } + if (isset($condition['maximumPerOrder'])) { + $setting['maximum_per_order'] = $condition['maximumPerOrder']; + } + if (isset($condition['minimumPerOrder'])) { + $setting['minimum_per_order'] = $condition['minimumPerOrder']; + } + if (isset($condition['presetAttrs'])) { + $setting['preset_attrs'] = $this->getSettingPresetAttrs($condition['presetAttrs']); + } + if (isset($condition['presetCateAttrs'])) { + $setting['preset_cate_attrs'] = $condition['presetCateAttrs']; + } + if (isset($condition['taskPresetAttrs'])) { + $setting['task_preset_attrs'] = $this->getSettingPresetAttrs($condition['taskPresetAttrs']); + } + if (isset($condition['taskQualityMap'])) { + $setting['task_quality_map'] = $condition['taskQualityMap']; + } + if (isset($condition['sku']['skuSearch'])) { + $setting['sku_search'] = $condition['sku']['skuSearch']; + } + if (isset($condition['sku']['skuReplace'])) { + $setting['sku_replace'] = $condition['sku']['skuReplace']; + } + if (isset($condition['price']['skuMinPriceStatus'])) { + $setting['sku_min_price_status'] = $condition['price']['skuMinPriceStatus']; + } + if (isset($condition['price']['skuMinPriceType'])) { + $setting['sku_min_price_type'] = $condition['price']['skuMinPriceType']; + } + if (isset($condition['price']['addSkuMinPricePricePercent'])) { + $setting['add_sku_min_price_price_percent'] = $condition['price']['addSkuMinPricePricePercent']; + } + if (isset($condition['price']['addSkuMinPricePriceAdd'])) { + $setting['add_sku_min_price_price_add'] = $condition['price']['addSkuMinPricePriceAdd']; + } + if (isset($condition['price']['addSkuMinPricePriceSub'])) { + $setting['add_sku_min_price_price_sub'] = $condition['price']['addSkuMinPricePriceSub']; + } + if (isset($condition['price']['addSkuMinPricePriceTail'])) { + $setting['add_sku_min_price_price_tail'] = $condition['price']['addSkuMinPricePriceTail']; + } + if (isset($condition['price']['addSkuMinPricePriceDecimal'])) { + $setting['add_sku_min_price_price_decimal'] = $condition['price']['addSkuMinPricePriceDecimal']; + } + if (isset($condition['price']['addSkuMinPriceSkuName'])) { + $setting['add_sku_min_price_sku_name'] = $condition['price']['addSkuMinPriceSkuName']; + } + if (isset($condition['price']['addSkuMinPriceQuantity'])) { + $setting['add_sku_min_price_quantity'] = $condition['price']['addSkuMinPriceQuantity']; + } + if (isset($condition['price']['addSkuPriceSource'])) { + $setting['add_sku_price_source'] = $condition['price']['addSkuPriceSource']; + } + if (isset($condition['price']['updateSkuMinPricePricePercent'])) { + $setting['update_sku_min_price_price_percent'] = $condition['price']['updateSkuMinPricePricePercent']; + } + if (isset($condition['price']['updateSkuMinPricePriceAdd'])) { + $setting['update_sku_min_price_price_add'] = $condition['price']['updateSkuMinPricePriceAdd']; + } + if (isset($condition['price']['updateSkuMinPricePriceSub'])) { + $setting['update_sku_min_price_price_sub'] = $condition['price']['updateSkuMinPricePriceSub']; + } + if (isset($condition['price']['updateSkuMinPricePriceTail'])) { + $setting['update_sku_min_price_price_tail'] = $condition['price']['updateSkuMinPricePriceTail']; + } + if (isset($condition['price']['updateSkuMinPricePriceDecimal'])) { + $setting['update_sku_min_price_price_decimal'] = $condition['price']['updateSkuMinPricePriceDecimal']; + } + if (isset($condition['price']['updateSkuMinPriceQuantity'])) { + $setting['update_sku_min_price_quantity'] = $condition['price']['updateSkuMinPriceQuantity']; + } + if (isset($condition['price']['updateSkuPriceSource'])) { + $setting['update_sku_price_source'] = $condition['price']['updateSkuPriceSource']; + } + if (isset($condition['price']['addSkuMinPriceType'])) { + $setting['add_sku_min_price_type'] = $condition['price']['addSkuMinPriceType']; + } + if (isset($condition['price']['addSkuMinPriceColorImg'])) { + $setting['add_sku_min_price_color_img'] = $condition['price']['addSkuMinPriceColorImg']; + } + if (isset($condition['commonSizeTemplate'])) { + $setting['common_size_template'] = $condition['commonSizeTemplate']; + } + if (isset($condition['isAppendSizeTemplateToDesc'])) { + $setting['is_append_size_template_to_desc'] = $condition['isAppendSizeTemplateToDesc']; + } + if (isset($condition['appendSizeTemplateToDescPosition'])) { + $setting['append_size_template_to_desc_position'] = $condition['appendSizeTemplateToDescPosition']; + } + if (isset($condition['useSourcePresell'])) { + $setting['use_source_presell'] = $condition['useSourcePresell']; + } + if (isset($condition['autoFillingMainImage']['isAutoFillingImage'])) { + $setting['is_auto_filling_main_image'] = $condition['autoFillingMainImage']['isAutoFillingImage']; + $setting['image_num_filling_to_num'] = $condition['autoFillingMainImage']['imageNumFillingToNum']; + $setting['is_auto_filling_use_sku_img'] = $condition['autoFillingMainImage']['isAutoFillingUseSkuImg']; + $setting['is_auto_filling_use_desc_img'] = $condition['autoFillingMainImage']['isAutoFillingUseDescImg']; + $setting['is_auto_filling_flip_main_img'] = $condition['autoFillingMainImage']['isAutoFillingFlipMainImg']; + $setting['is_auto_filling_rotating_main_img'] = $condition['autoFillingMainImage']['isAutoFillingRotatingMainImg']; + $setting['is_auto_filling_copy_main_img'] = $condition['autoFillingMainImage']['isAutoFillingCopyMainImg']; + } + if (isset($condition['mobile'])) { + $setting['mobile'] = $condition['mobile']; + } + if (isset($condition['skipShopName'])) { + $setting['skip_shop_name'] = $condition['skipShopName']; + } + if (isset($condition['useUserBanWord'])) { + $setting['use_user_ban_word'] = $condition['useUserBanWord']; + } + if (isset($condition['autoFilterBanWord'])) { + $setting['auto_filter_ban_word'] = $condition['autoFilterBanWord']; + } + if (isset($condition['useSystemBanWord'])) { + $setting['use_system_ban_word'] = $condition['useSystemBanWord']; + } + if (isset($condition['moveShopSettingId'])) { + $setting['move_shop_setting_id'] = $condition['moveShopSettingId']; + } + if (isset($condition['isCopySourceVideo'])) { + $setting['is_copy_source_video'] = $condition['isCopySourceVideo']; + } + if (isset($condition['isUseSourceWhiteBgImg'])) { + $setting['is_use_source_white_bg_img'] = $condition['isUseSourceWhiteBgImg']; + } + if (isset($condition['buildWhiteBgImgUseMainImgIndex'])) { + $setting['build_white_bg_img_use_main_img_index'] = $condition['buildWhiteBgImgUseMainImgIndex']; + } + if (isset($condition['isUseSourceLongPic'])) { + $setting['is_use_source_long_pic'] = $condition['isUseSourceLongPic']; + } + if (isset($condition['isBuildLongPic'])) { + $setting['is_build_long_pic'] = $condition['isBuildLongPic']; + } + if (isset($condition['buildLongPicMode'])) { + $setting['build_long_pic_mode'] = $condition['buildLongPicMode']; + } + if (isset($condition['buildLongPicUseMainImgIndex'])) { + $setting['build_long_pic_use_main_img_index'] = $condition['buildLongPicUseMainImgIndex']; + } + + return $setting; + } + + public function formatRetryMoveProduct($product, $taskDetail, $taskDetailExt) { + $product['newTitle'] = $taskDetail['source_title']; + $product['cid'] = $taskDetail['cid']; + $product['newItemNum'] = $taskDetailExt['item_num']; + $product['brandId'] = $taskDetailExt['brand_id']; + if ($taskDetail['source_img_url']) { + $product['productImg'] = $taskDetail['source_img_url']; + } + if ($taskDetailExt['product_image_urls']) { + $product['productImgUrls'] = $taskDetailExt['product_image_urls']; + } + if ($taskDetailExt['source_category_path']) { + $product['sourceCategoryPath'] = $taskDetailExt['source_category_path']; + } + if ($taskDetailExt['price']) { + $product['price'] = $taskDetailExt['price']; + } + if ($taskDetailExt['market_price']) { + $product['newMarketPrice'] = $taskDetailExt['market_price']; + } + if ($taskDetailExt['cost_price']) { + $product['costPrice'] = $taskDetailExt['cost_price']; + } + if ($taskDetailExt['fetch_bank_detail_id']) { + $product['fetchBankDetailId'] = $taskDetailExt['fetch_bank_detail_id']; + } + if ($taskDetailExt['limit_per_buyer']) { + $product['newLimitPerBuyer'] = $taskDetailExt['limit_per_buyer']; + } + if ($taskDetailExt['maximum_per_order']) { + $product['newMaximumPerOrder'] = $taskDetailExt['maximum_per_order']; + } + if ($taskDetailExt['minimum_per_order']) { + $product['newMinimumPerOrder'] = $taskDetailExt['minimum_per_order']; + } + if ($taskDetailExt['presell_type']) { + $product['newPresellType'] = $taskDetailExt['presell_type']; + } + if ($taskDetailExt['delivery_delay_day']) { + $product['newDeliveryDelayDay'] = $taskDetailExt['delivery_delay_day']; + } + if ($taskDetailExt['presell_delay']) { + $product['newPresellDelay'] = $taskDetailExt['presell_delay']; + } + if ($taskDetailExt['presell_end_time']) { + $product['newPresellEndTime'] = $taskDetailExt['presell_end_time']; + } + if ($taskDetailExt['white_bg_img_url']) { + $product['whiteBgImgUrl'] = $taskDetailExt['white_bg_img_url']; + } + if ($taskDetailExt['long_pic_url']) { + $product['longPicUrl'] = $taskDetailExt['long_pic_url']; + } + if ($taskDetailExt['skus']['skuMap']) { + $product['skuMap'] = $taskDetailExt['skus']['skuMap']; + } + if ($taskDetailExt['need_shift_img']) { + $product['needShiftImg'] = $taskDetailExt['need_shift_img']; + } + if ($taskDetailExt['has_change_img']) { + $product['hasChangeImg'] = $taskDetailExt['has_change_img']; + } + if ($taskDetailExt['has_change_color_map']) { + $product['hasChangeColorMap'] = $taskDetailExt['has_change_color_map']; + } + if ($taskDetailExt['has_change_img'] || $taskDetailExt['has_change_color_map']) { + $product['colorMap'] = $taskDetailExt['skus']['colorMap']; + } + if ($taskDetailExt['has_change_img'] || $taskDetailExt['has_change_color_map']) { + $product['colorMap'] = $taskDetailExt['skus']['colorMap']; + } + if ($taskDetailExt['skus']['sizeMap']) { + $product['sizeMap'] = $taskDetailExt['skus']['sizeMap']; + } + if ($taskDetailExt['skus']['skuPresellChildSkuDetail']) { + $product['newSkuPresellChildSkuDetail'] = $taskDetailExt['skus']['skuPresellChildSkuDetail']; + $product['newPresellTimeSkuSpecNameAndStockPercentMap'] = $taskDetailExt['skus']['presellTimeSkuSpecNameAndStockPercentMap']; + } + if ($taskDetailExt['match_cid']) { + $product['matchCid'] = $taskDetailExt['match_cid']; + } + if ($taskDetailExt['match_path']) { + $product['matchPath'] = $taskDetailExt['match_path']; + } + if ($taskDetailExt['props']) { + $product['props'] = $taskDetailExt['props']; + } + if ($taskDetailExt['del_img_urls']) { + $product['delImgUrls'] = $taskDetailExt['del_img_urls']; + } + if ($taskDetailExt['has_save_notes']) { + $product['hasSaveNotes'] = $taskDetailExt['has_save_notes']; + $product['notes'] = $taskDetailExt['notes']; + } + if ($taskDetailExt['shop_category']) { + $product['shopCateIds'] = $taskDetailExt['shop_category']; + } + if ($taskDetailExt['website_source']) { + $product['websiteSource'] = $taskDetailExt['website_source']; + } + if ($taskDetailExt['length']) { + $product['newLength'] = $taskDetailExt['length']; + } + if ($taskDetailExt['width']) { + $product['newWidth'] = $taskDetailExt['width']; + } + if ($taskDetailExt['height']) { + $product['newHeight'] = $taskDetailExt['height']; + } + if ($taskDetailExt['weight']) { + $product['newWeight'] = $taskDetailExt['weight']; + } + if ($taskDetailExt['auth_shop_id']) { + $product['authShopId'] = $taskDetailExt['authShopId']; + } + if (is_numeric($taskDetailExt['size_template_id'])) { + $product['newSizeTemplateId'] = $taskDetailExt['size_template_id']; + } + if ($taskDetailExt['class_quality']) { + $product['classQuality'] = explode(',', $taskDetailExt['class_quality']); + } + if ($taskDetailExt['quality_report']) { + $product['qualityReport'] = explode(',', $taskDetailExt['quality_report']); + } + $product['calRecommendRemark'] = $taskDetailExt['recommend_remark'] ?: ''; + if ($taskDetailExt['recommend_remark']) { + $product['newRecommendRemark'] = $product['calRecommendRemark']; + } + if (is_numeric($taskDetailExt['freight_template_id'])) { + $product['newFreightTemplateId'] = $taskDetailExt['freight_template_id']; + } + if (is_numeric($taskDetailExt['reduce_type'])) { + $product['newReduceType'] = $taskDetailExt['reduce_type']; + } + if ($taskDetailExt['place_order_delay']) { + $product['newPlaceOrderDelay'] = $taskDetailExt['place_order_delay']; + } + if ($taskDetailExt['quality_map']) { + $product['productQualityMap'][$product['cid']] = $taskDetailExt['quality_map']; + } + if ($taskDetailExt['video_url']) { + $product['hasChangeVideo'] = 1; + $product['videoInfo']['videoUrl'] = $taskDetailExt['video_url']; + } + if ($taskDetailExt['video_upload_folder_id']) { + $product['videoInfo']['uploadFolderId'] = $taskDetailExt['video_upload_folder_id']; + } + if ($taskDetailExt['material_video_id']) { + $product['materialVideoId'] = $taskDetailExt['material_video_id']; + } + $product['generateLongPicByMiaoshouXiuxiu'] = $taskDetailExt['generate_long_pic_by_miaoshou_xiuxiu']; + + return $product; + } + + public function getShopSizeTemplateById($sizeTemplateId) { + return $this->productDao->getShopSizeTemplateById($sizeTemplateId); + } + + public function getPriceDecimalDiyKeys() { + return [ + 'priceDecimalDiyValue' => 'price_decimal_diy_value', + 'marketPriceDecimalDiyValue' => 'market_price_decimal_diy_value', + 'addSkuMinPricePriceDecimalDiyValue' => 'add_sku_min_price_price_decimal_diy_value', + 'updateSkuMinPricePriceDecimalDiyValue' => 'update_sku_min_price_price_decimal_diy_value' + ]; + } + + public function getEnablePresetAttrs($presetAttrs) { + $enablePresetAttrs = array (); + foreach ($presetAttrs as $presetAttr) { + $presetAttrName = trim($presetAttr['presetAttrName']); + $presetAttrValue = trim($presetAttr['presetAttrValue']); + if (isset($enablePresetAttrs[$presetAttrName])) { + continue; + } + if (CommonTool::anyEmpty($presetAttrName)) { + continue; + } + if (!$presetAttr['presetAttrEnable']) { + continue; + } + $enablePresetAttrs[$presetAttrName] = [ + 'value' => $presetAttrValue, + 'isForce' => isset($presetAttr['presetAttrIsForce']) ? $presetAttr['presetAttrIsForce'] : 1 + ]; + } + return $enablePresetAttrs; + } + + public function getSettingPresetAttrs($conditionPresetAttrs) { + $presetAttrs = array(); + foreach ($conditionPresetAttrs as $presetAttrName => $presetAttr) { + $presetAttrs[] = [ + 'presetAttrEnable' => 1, + 'presetAttrName' => $presetAttrName, + 'presetAttrValue' => $presetAttr['value'], + 'presetAttrIsForce' => $presetAttr['isForce'], + ]; + } + return $presetAttrs; + } + + public function getEnablePresetCateAttrs($presetCateAttrs) { + foreach ($presetCateAttrs as $cid => &$presetCateAttr) { + foreach ($presetCateAttr as $aid => $presetAttr) { + if (empty($presetAttr['enable'])) { + unset($presetCateAttr[$aid]); + } + } + if (empty($presetCateAttrs[$cid])) { + unset($presetCateAttrs[$cid]); + } + } + return $presetCateAttrs; + } + + public function addMoveShopSettingOperateLog($shopId, $authShopId, $moveShopSettingOperateLog) { + if (empty($moveShopSettingOperateLog)) { + return false; + } + + $this->db->useDbIdOnce('ac')->insert('move_shop_setting_operate_log', array( + 'shop_id' => $shopId, + 'auth_shop_id' => $authShopId, + 'ip' => CommonTool::clientIp(), + 'hostname' => gethostname(), + 'data' => serialize($moveShopSettingOperateLog), + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + + public function replaceShopConditionsBigField($shopConditions, $moveShopSettingIds) { + $bigFieldIds = $this->getMoveSettingBigFieldIdFields(); + $bigFieldString = implode(',', $bigFieldIds); + foreach ($shopConditions as $shopId => &$condition) { + $bigFieldData = $this->db->queryFirstRow('SELECT %l FROM move_shop_setting WHERE shop_id = %i AND move_shop_setting_id = %i ', $bigFieldString, $shopId, $moveShopSettingIds[$shopId]); + if(!empty($condition['desc']['descPrefix'])){ + $condition['desc']['descPrefixId'] = $bigFieldData['desc_prefix_id']; + unset($condition['desc']['descPrefix']); + } + if(!empty($condition['desc']['descSuffix'])){ + $condition['desc']['descSuffixId'] = $bigFieldData['desc_suffix_id']; + unset($condition['desc']['descSuffix']); + } + if(!empty($condition['desc']['descPrefixImg'])){ + $condition['desc']['descPrefixImgId'] = $bigFieldData['desc_prefix_img_id']; + unset($condition['desc']['descPrefixImg']); + } + if(!empty($condition['desc']['descSuffixImg'])){ + $condition['desc']['descSuffixImgId'] = $bigFieldData['desc_suffix_img_id']; + unset($condition['desc']['descSuffixImg']); + } + if(!empty($condition['title']['titleDelete'])){ + $condition['title']['titleDeleteId'] = $bigFieldData['title_delete_id']; + unset($condition['title']['titleDelete']); + } + if (!empty($condition['skipTitleKeyword'])) { + $condition['skipTitleKeywordId'] = $bigFieldData['skip_title_keyword_id']; + unset($condition['skipTitleKeyword']); + } + if (!empty($condition['skipSkuAliasKeyword'])) { + $condition['skipSkuAliasKeywordId'] = $bigFieldData['skip_sku_alias_keyword_id']; + unset($condition['skipSkuAliasKeyword']); + } + if (!empty($condition['skipSendCityInfo'])) { + $condition['skipSendCityInfoId'] = $bigFieldData['skip_send_city_info_id']; + unset($condition['skipSendCityInfo']); + } + if (!empty($condition['recommendRemarkSearch'])) { + $condition['recommendRemarkSearchId'] = $bigFieldData['recommend_remark_search_id']; + unset($condition['recommendRemarkSearch']); + } + if (!empty($condition['recommendRemarkReplace'])) { + $condition['recommendRemarkReplaceId'] = $bigFieldData['recommend_remark_replace_id']; + unset($condition['recommendRemarkReplace']); + } + if (!empty($condition['recommendRemarkPrefix'])) { + $condition['recommendRemarkPrefixId'] = $bigFieldData['recommend_remark_prefix_id']; + unset($condition['recommendRemarkPrefix']); + } + if (!empty($condition['recommendRemarkSuffix'])) { + $condition['recommendRemarkSuffixId'] = $bigFieldData['recommend_remark_suffix_id']; + unset($condition['recommendRemarkSuffix']); + } + if (!empty($condition['skipBrandKeyword'])) { + $condition['skipBrandKeywordId'] = $bigFieldData['skip_brand_keyword_id']; + unset($condition['skipBrandKeyword']); + } + if (!empty($condition['skuAliasDelete'])) { + $condition['skuAliasDeleteId'] = $bigFieldData['sku_alias_delete_id']; + unset($condition['skuAliasDelete']); + } + if (!empty($condition['sku']['skuSearch'])) { + $condition['sku']['skuSearchId'] = $bigFieldData['sku_search_id']; + unset($condition['sku']['skuSearch']); + } + if (!empty($condition['sku']['skuReplace'])) { + $condition['sku']['skuReplaceId'] = $bigFieldData['sku_replace_id']; + unset($condition['sku']['skuReplace']); + } + if(!empty($condition['presetCateAttrs'])) { + $condition['presetCateAttrsId'] = $bigFieldData['preset_cate_attrs_id']; + unset($condition['presetCateAttrs']); + } + if (!empty($condition['title']['titleSearch'])) { + $condition['title']['titleSearchId'] = $bigFieldData['title_search_id']; + unset($condition['title']['titleSearch']); + } + if (!empty($condition['title']['titleReplace'])) { + $condition['title']['titleReplaceId'] = $bigFieldData['title_replace_id']; + unset($condition['title']['titleReplace']); + } + } + + return $shopConditions; + } + + public function addShopCollectTask($shopId, $shopProductsList, $name, $copyType, $shopConditions, $previewCateAttrData = [], $operateSource = '', $isFromLtaoRank = 0) { + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + foreach ($shopProductsList as $authShopId => $products) { + $addRet = $this->addCollectTask($authShopId, $shopId, $copyType, $name, $shopConditions[$authShopId], $products, $previewCateAttrData[$authShopId], $isFromLtaoRank); + if (CommonTool::isSuccessRet($addRet) && ($authShopId == $shopId)) { + $taskId = $addRet['taskId']; + $cnaliDsDetailMap = $addRet['cnaliDsDetailMap']; + } + } + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->moveLog->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("添加任务数据失败"); + } + + return CommonTool::successResult(array( + 'taskId' => $taskId, + 'cnaliDsDetailMap' => $cnaliDsDetailMap + )); + } + + public function updateShopCollectTask($shopId, $taskDetail, $shopProductsList, $shopConditions) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->updateCollectTask($shopId, $taskDetail, $shopConditions[$shopId], $shopProductsList[$shopId]); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->moveLog->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("更新任务数据失败"); + } + return CommonTool::successResult(); + } + + public function addDsShopCollectTask($shopId, $condition, $itemDataList) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + $name = sprintf('%s 主客铺货复制', ZcDateHelper::now()); + + try { + $addTaskRet = $this->addCollectTask($shopId, $shopId, MoveConst::collectDsCopy, $name, $condition, $itemDataList, array()); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::successResult('respData', $addTaskRet['cnaliDsDetailMap']); + } catch (Exception $ex) { + $this->moveLog->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("添加任务数据失败:" . $ex->getMessage()); + } + } + + private function addCollectTask($shopId, $operatorShopId, $copyType, $name, $condition, $products, $previewCateAttrData, $isFromLtaoRank = 0) { + $logger = Zc::getLog('move/add_task'); + $productTotal = count($products); + $dsTotal = 0; + if ($copyType == MoveConst::collectDsCopy) { + $dsProducts = $this->getDsTaskDetails($products); + $dsTotal = $dsProducts ? count($dsProducts) : 0; + $productTotal = $productTotal - $dsTotal; + } + $checkAndGetConfigIdRet = $this->checkAvailableCopyAndGetMoveConfigId($shopId, $productTotal); + if (CommonTool::isFailRet($checkAndGetConfigIdRet)) { + throw new Exception($checkAndGetConfigIdRet['reason']); + } + $moveShopConfigId = $checkAndGetConfigIdRet['moveShopConfigId']; + + if ($productTotal > 0) { + if ($copyType == MoveConst::collectDsCopy && empty($dsTotal)) { // 目前主客复制不扣额度,如果有这个类型的,要扣额度代表主客创建失败,变成普通商品链接复制 + $copyType = MoveConst::collectLinksCopy; + } + + $deductRet = $this->deductMoveCopyCount($shopId, $productTotal, $moveShopConfigId); + if (CommonTool::isFailRet($deductRet)) { + throw new Exception("shopId $shopId " . $deductRet['reason']); + } + } + + $insert = array( + 'shop_id' => $shopId, + 'copy_type' => $copyType, + 'name' => $name, + 'status' => StatusConst::wait, + 'success_count' => 0, + 'fail_count' => 0, + 'condition' => serialize($condition), + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + + $this->db->insert('move_collect_task', $insert); + $moveCollectTaskId = $this->db->lastInsertId(); + + if (!empty($previewCateAttrData)) { + $saveRet = $this->savePreviewCateAttrToOss($previewCateAttrData, $moveCollectTaskId, $shopId); + $logger->info("save cateAttr to oss ret" . json_encode($saveRet)); + } + + $logger->info("INSERT move_collect_task SQL:" . $this->db->lastSql()); + + $cnaliDsDetailMap = array(); + + foreach ($products as $product) { + $insertTaskDetail = array( + 'shop_id' => $shopId, + 'auth_shop_id' => $product['auth_shop_id'] ? $product['auth_shop_id'] : '', + 'operator_shop_id' => $operatorShopId, + 'move_collect_task_id' => $moveCollectTaskId, + 'is_fast_mode' => $product['is_fast_mode'], + 'source' => $product['source'], + 'site' => $product['site'], + 'source_item_id' => $product['source_item_id'], + 'source_title' => $product['source_title'], + 'source_img_url' => $product['source_img_url'], + 'source_shop_name' => $product['source_shop_name'], + 'move_shop_config_id' => $moveShopConfigId, + 'cid' => $product['cid'], + 'status' => StatusConst::processing, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + $this->db->insert('move_collect_task_detail', $insertTaskDetail); + $logger->info("INSERT move_collect_task_detail SQL:" . $this->db->lastSql()); + $moveCollectTaskDetailId = $this->db->lastInsertId(); + + $insertTaskDetailExt = $this->buildInsertTaskDetailExt($shopId, $product); + $insertTaskDetailExt['move_collect_task_detail_id'] = $moveCollectTaskDetailId; + $insertExtRet = $this->db->insert('move_collect_task_detail_ext', $insertTaskDetailExt); + $logger->info("INSERT move_collect_task_detail_ext {$insertExtRet} SQL:" . $this->db->lastSql() . 'insertTaskDetailExt' . print_r($insertTaskDetailExt, true)); + + $logger->info("moveCollectTaskDetailId:" . $moveCollectTaskDetailId); + + $limitSource = 'all'; + if (($product['source'] == FetchClientConst::collectTaskSource1688) && $product['is_fast_mode']) { + $limitSource = FetchClientConst::collectTaskSource1688; + } + $this->addTaskBuffer($shopId, $moveCollectTaskId, $moveCollectTaskDetailId, $productTotal, $limitSource); + $logger->info("INSERT move_product_publish_buffer SQL:" . $this->db->lastSql()); + } + + return CommonTool::successResult(array( + 'taskId' => $moveCollectTaskId, + 'cnaliDsDetailMap' => $cnaliDsDetailMap, + )); + } + + private function updateCollectTask($shopId, $taskDetail, $condition, $products) { + $logger = Zc::getLog('move/update_task'); + $productTotal = count($products); + $taskId = $taskDetail['move_collect_task_id']; + $taskDetailId = $taskDetail['move_collect_task_detail_id']; + $moveCollectTaskDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $taskDetailId); + if (!empty($moveCollectTaskDetailExt['cnali_ds_detail_id'])) { + $productTotal = 0; + } + + $checkAndGetConfigIdRet = $this->checkAvailableCopyAndGetMoveConfigId($shopId, $productTotal); + if (CommonTool::isFailRet($checkAndGetConfigIdRet)) { + throw new Exception($checkAndGetConfigIdRet['reason']); + } + $moveShopConfigId = $checkAndGetConfigIdRet['moveShopConfigId']; + + if ($productTotal > 0) { + $deductRet = $this->deductMoveCopyCount($shopId, $productTotal, $moveShopConfigId); + if (CommonTool::isFailRet($deductRet)) { + throw new Exception("shopId $shopId " . $deductRet['reason']); + } + } + + foreach ($products as $product) { + $updateTaskDetail = array( + 'is_fast_mode' => 0, + 'source_title' => $product['source_title'], + 'source_img_url' => $product['source_img_url'], + 'cid' => $product['cid'], + 'status' => StatusConst::processing, + 'move_shop_config_id' => $moveShopConfigId, + 'gmt_modified' => ZcDbEval::now() + ); + $this->db->update('move_collect_task_detail', $updateTaskDetail, "move_collect_task_detail_id = %i", $taskDetailId); + $logger->info("UPDATE move_collect_task_detail SQL:" . $this->db->lastSql()); + + $this->addTaskBuffer($shopId, $taskId, $taskDetailId, $productTotal); + + $this->db->delete('move_collect_task_detail_notice', 'move_collect_task_detail_id = %i', $taskDetailId); + $this->insertUpdateMoveCollectTaskDetailRetry($shopId, $taskDetailId); + + $updateDetailExtRet = $this->updateMoveCollectTaskDetailExt($shopId, $taskDetail['move_collect_task_detail_id'], $product); + if (CommonTool::isFailRet($updateDetailExtRet)) { + throw new Exception("shopId $shopId " . $updateDetailExtRet['reason']); + } + $logger->info("INSERT move_product_publish_buffer SQL:" . $this->db->lastSql()); + } + return CommonTool::successResult(); + } + + public function tryAddMoveAuthPlatformProductLog($authPlatform, $authPlatformUserId, $authPlatformItemId, $applyPlatformMoveCollectTaskDetailId, $applyPlatformItemId, $applyPlatformUserId, $status = StatusConst::processing) { + if (!in_array($authPlatform, PlatformAuthConst::getNeedRecordMoveLogAuthPlatforms())) { + return CommonTool::successResult(); + } + + $params = array( + 'authPlatform' => $authPlatform, + 'authPlatformUserId' => $authPlatformUserId, + 'authPlatformItemId' => $authPlatformItemId, + 'applyPlatformMoveCollectTaskDetailId' => $applyPlatformMoveCollectTaskDetailId, + 'applyPlatformItemId' => $applyPlatformItemId, + 'applyPlatformUserId' => $applyPlatformUserId, + 'status' => $status, + ); + + $this->addPlatformAsyncNoticeTask($applyPlatformUserId, MoveConst::platformAsyncNoticeTaskTypePlatformAuthMove, $params); + return CommonTool::successResult(); + } + + public function addPlatformAsyncNoticeTask($shopId, $type, $params) { + $this->db->insert('platform_async_notice_task', array( + 'shop_id' => $shopId, + 'type' => $type, + 'params' => is_array($params) ? json_encode($params) : $params, + 'locked' => 0, + 'try_times' => 0, + 'gmt_exec' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + + private function insertMoveCollectDetailDsLog($shopId, $moveCollectTaskDetailId, $cnaliDsDetailId) { + $insert = $update = array( + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'cnali_ds_detail_id' => $cnaliDsDetailId, + 'gmt_modified' => ZcDbEval::now(), + ); + + $insert['gmt_create'] = ZcDbEval::now(); + + return $this->db->insertUpdate('move_collect_task_detail_ds_log', $insert, $update); + } + + private function insertMoveCollectDetailMobileLog($shopId, $moveCollectTaskDetailId) { + $insert = $update = array( + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'gmt_modified' => ZcDbEval::now(), + ); + + $insert['gmt_create'] = ZcDbEval::now(); + + return $this->db->insertUpdate('move_collect_task_detail_mobile_log', $insert, $update); + } + + private function insertMoveCollectDetailFromMobileLog($shopId, $moveCollectTaskDetailId) { + $insert = $update = array( + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'gmt_modified' => ZcDbEval::now(), + ); + + $insert['gmt_create'] = ZcDbEval::now(); + + return $this->db->insertUpdate('move_collect_task_detail_from_mobile_log', $insert, $update); + } + + private function insertMoveCollectDetailLtaoLog($shopId, $moveCollectTaskDetailId, $ltaoCategoryId, $isFromLtaoRank = 0) { + $insert = $update = array( + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'ltao_category_id' => $ltaoCategoryId, + 'is_from_rank' => $isFromLtaoRank, + 'gmt_modified' => ZcDbEval::now(), + ); + + $insert['gmt_create'] = ZcDbEval::now(); + + return $this->db->insertUpdate('move_collect_task_detail_ltao_log', $insert, $update); + } + + private function addDsTask($shopId, $shopProductsList, $operateSource) { + $dsShopProductsList = $this->getDsProductsList($shopProductsList); + if (empty($dsShopProductsList)) { + return CommonTool::successResult(array( + 'shopProductsList' => $shopProductsList + )); + } + + $memberId = $this->getAlibabaMemberId($shopId); + if (empty($memberId)) { + $isExistDs = $this->isExistDs($shopId); + if ($isExistDs) { + return CommonTool::failCodeResult(ErrorCodeConst::expireDsAuth, '抖店和1688授权过期,请重新授权'); + } + + return CommonTool::failCodeResult(ErrorCodeConst::noDsAuth, '抖店没有1688主客授权,请授权'); + } + + $saveDsTaskRet = $this->dsClient->saveDsTask(AppConst::getDsPlatform(), $memberId, $dsShopProductsList, $operateSource); + if (CommonTool::isFailRet($saveDsTaskRet)) { + return $saveDsTaskRet; + } + $dsDetailIdMap = $saveDsTaskRet['dsDetailIdMap']; + + $shopProductsList = $this->doRebuildDsDetailIdToDetails($shopProductsList, $dsDetailIdMap); + return CommonTool::successResult(array( + 'shopProductsList' => $shopProductsList + )); + } + + private function doRebuildDsDetailIdToDetails($shopProductsList, $dsDetailIdMap) { + foreach ($shopProductsList as $shopId => $productsList) { + foreach ($productsList as $productId => $productInfo) { + if (!$productInfo['isFromDs']) { + continue; + } + + if (!isset($dsDetailIdMap[$productId][$shopId])) { + continue; + } + + $shopProductsList[$shopId][$productId]['cnali_ds_detail_id'] = $dsDetailIdMap[$productId][$shopId]; + } + } + + return $shopProductsList; + } + + private function getDsProductsList($shopProductsList) { + $dsProductsList = []; + foreach ($shopProductsList as $shopId => $products) { + $dsProducts = $this->getDsDetails($products); + if (empty($dsProducts)) { + continue; + } + + $alibabaMemberId = $this->getAlibabaMemberId($shopId); + if (empty($alibabaMemberId)) { + continue; + } + + $dsProductsList[$shopId] = $dsProducts; + } + + return $dsProductsList; + } + + public function getDsDetails($products) { + $dsDetails = []; + foreach ($products as $productId => $productInfo) { + if ($productInfo['isFromDs']) { + $dsDetails[$productId] = $productInfo; + } + } + + return $dsDetails; + } + + public function getDsTaskDetails($products) { + $dsDetails = []; + foreach ($products as $productId => $productInfo) { + if ($productInfo['isFromDs'] && $productInfo['cnali_ds_detail_id']) { + $dsDetails[$productId] = $productInfo; + } + } + + return $dsDetails; + } + + private function buildInsertTaskDetailExt($shopId, $data) { + return array( + 'shop_id' => $shopId, + 'product_image_urls' => !empty($data['product_image_urls']) ? serialize($data['product_image_urls']) : null, + 'price' => $data['price'], + 'pingou_price' => $data['pingou_price'], + 'market_price' => $data['market_price'], + 'cost_price' => $data['cost_price'], + 'skus' => !empty($data['skus']) ? serialize($data['skus']) : null, + 'has_change_img' => $data['has_change_img'] ? MoveConst::settingBoolTrue : null, + 'need_shift_img' => $data['need_shift_img'] ? MoveConst::settingBoolTrue : null, + 'props' => !empty($data['props']) ? serialize($data['props']) : null, + 'del_img_urls' => !empty($data['del_img_urls']) ? serialize($data['del_img_urls']) : null, + 'notes' => !empty($data['notes']) ? $data['notes'] : null, + 'has_save_notes' => $data['has_save_notes'], + 'move_import_task_id' => $data['move_import_task_id'], + 'move_import_task_detail_id' => $data['move_import_task_detail_id'], + 'source_attrs' => !empty($data['source_attrs']) ? serialize($data['source_attrs']) : null, + 'quality_map' => !empty($data['quality_map']) ? serialize($data['quality_map']) : null, + 'has_change_color_map' => $data['has_change_color_map'], + 'has_change_size_map' => $data['has_change_size_map'], + 'has_change_title' => $data['has_change_title'], + 'brand_id' => $data['brand_id'], + 'fetch_bank_detail_id' => $data['fetch_bank_detail_id'], + 'cnali_ds_detail_id' => $data['cnali_ds_detail_id'] ? : null, + 'class_quality' => $data['class_quality'], + 'quality_report' => $data['quality_report'], + 'recommend_remark' => $data['recommend_remark'], + 'presell_type' => $data['presell_type'], + 'delivery_delay_day' => $data['delivery_delay_day'], + 'presell_delay' => $data['presell_delay'], + 'presell_end_time' => $data['presell_end_time'], + 'place_order_delay' => $data['place_order_delay'], + 'reduce_type' => $data['reduce_type'], + 'freight_template_id' => $data['freight_template_id'], + 'limit_per_buyer' => $data['limit_per_buyer'], + 'maximum_per_order' => $data['maximum_per_order'], + 'minimum_per_order' => $data['minimum_per_order'], + 'match_cid' => $data['match_cid'], + 'use_recommend_cid' => $data['use_recommend_cid'], + 'source_category_path' => $data['source_category_path'], + 'item_num' => $data['item_num'], + 'video_url' => !empty($data['video_url'])? $data['video_url'] : null, + 'material_video_id' => !empty($data['material_video_id']) ? $data['material_video_id'] : null, + 'video_upload_folder_id' => !empty($data['video_upload_folder_id']) ? $data['video_upload_folder_id'] : 0, + 'generate_long_pic_by_miaoshou_xiuxiu' => !empty($data['generate_long_pic_by_miaoshou_xiuxiu']) ? $data['generate_long_pic_by_miaoshou_xiuxiu'] : 0, + 'white_bg_img_url' => !empty($data['white_bg_img_url']) ? $data['white_bg_img_url'] : null, + 'long_pic_url' => !empty($data['long_pic_url']) ? $data['long_pic_url'] : null, + 'size_template_id' => $data['size_template_id'], + 'supply_7day_return' => $data['supply_7day_return'], + 'name_prefix' => $data['name_prefix'], + 'clue_id' => $data['clue_id'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + } + + public function deductMoveCopyCount($shopId, $useNum, $moveConfigId = null){ + if ($useNum <= 0) { + return CommonTool::failResult('额度参数错误'); + } + if (empty($moveConfigId)) { + $moveConfig = $this->getAvailableCopyCount($shopId); + + $isAvailable = ($moveConfig['available_total'] >= $useNum) ? true : false; + if(!$isAvailable){ + return CommonTool::failResult('搬家额度不足'); + } + $moveConfigId = $moveConfig['move_shop_config_id']; + } + + $affRow = $this->db->exec("update `move_shop_config` set used_total = used_total + %i where `shop_id` = %i and `move_shop_config_id` = %i", $useNum, $shopId, $moveConfigId); + return $affRow ? CommonTool::successResult() : CommonTool::failResult('扣除额度失败'); + } + + private function savePreviewCateAttrToOss($previewCateAttrData, $moveCollectTaskId, $shopId) { + $ossPreviewCateAttrData = serialize($previewCateAttrData); + $realUrl = "mct/{$shopId}/{$moveCollectTaskId}_previewCateAttr.txt"; + $ret = OssTool::uploadImmutableObjectByContent($realUrl, $ossPreviewCateAttrData); + if (CommonTool::isFailRet($ret)) { + return CommonTool::failResult('上传属性到Oss失败,失败原因'. $ret['reason']); + } else { + return CommonTool::successResult(); + } + } + + private function addTaskBuffer($shopId, $moveCollectTaskId, $moveCollectTaskDetailId, $productTotal, $limitSource = 'all', $tryTimes = 0, $gmtExec = null) { + $priority = $this->getTaskPriority($shopId, $productTotal); + $insertTaskBuffer = array( + 'move_collect_task_id' => $moveCollectTaskId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'shop_id' => $shopId, + 'priority' => $priority, + 'limit_source' => $limitSource, + 'try_times' => $tryTimes, + 'gmt_exec' => $gmtExec, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + return $this->db->insert('move_product_publish_buffer', $insertTaskBuffer); + } + + private function getTaskPriority($shopId, $extProductNum = 1) { + $bufferQueueCount = $this->countShopMoveBufferQueue($shopId); + $productTotal = $bufferQueueCount + $extProductNum; + if ($productTotal < 30) { + $priority = 98; + } elseif ($productTotal < 100) { + $priority = 99; + } elseif ($productTotal < 200) { + $priority = 100; + } elseif ($productTotal < 1000) { + $priority = 101; + } else { + $priority = 102; + } + return $priority; + } + + private function countShopMoveBufferQueue($shopId) { + $countBuffer = $this->db->queryFirstField("SELECT COUNT(*) FROM move_product_publish_buffer WHERE shop_id = %i", $shopId); + $countQueue = $this->db->queryFirstField("SELECT COUNT(*) FROM move_product_publish_queue WHERE shop_id = %i", $shopId); + return $countBuffer + $countQueue; + } + + public function getMoveProductPublishBufferShopMap($filter = [], $maxQueueCount = 500) { + $this->moveProductPublishBufferLog->info("start getMoveProductPublishBufferSelectedShopMap"); + $where = array(); + if (!empty($filter['excludeShopIds'])) { + $where[] = $this->db->prepare("AND shop_id not in %li", $filter['excludeShopIds']); + } + if (!empty($filter['includeShopIds'])) { + $where[] = $this->db->prepare("AND shop_id in %li", $filter['includeShopIds']); + } + $whereString = implode(' ', $where); + Zc::G('start moveProductPublishBufferToQueue'); + $queueCount = $this->db->queryFirstField("select count(*) from `move_product_publish_queue` where 1 %l", $whereString); + if ($queueCount >= $maxQueueCount) { + $this->moveProductPublishBufferLog->info("queueCount $queueCount, maxQueueCount $maxQueueCount, end."); + return false; + } + + $leftCount = $maxQueueCount - $queueCount; + $this->moveProductPublishBufferLog->info("current queueCount $queueCount, leftCount $leftCount"); + $selectedShopMap = $this->countSelectedProductPublishBufferShopMap($leftCount, $whereString); + $this->moveProductPublishBufferLog->info("end getMoveProductPublishBufferSelectedShopMap"); + return $selectedShopMap; + } + + public function countSelectedProductPublishBufferShopMap($leftCount, $whereString) { + Zc::G('start statProductPublishBuffer'); + list ($priorityShopsMap, $shopIds) = $this->statProductPublishBuffer($whereString); + Zc::G('end statProductPublishBuffer'); + +// $stopMoveShopIds = $this->db->queryFirstColumn('select shop_id from move_shop_stop where is_over_daily_total = 1 and is_continue_move = 0'); //不存在这个业务了 + $stopMoveShopIds = $this->db->queryFirstColumn('select shop_id from move_shop_stop where is_limit_publish = 1'); + $shopIds = array_diff($shopIds, $stopMoveShopIds); + foreach ($priorityShopsMap as $priority => $shopIdAndCountMap) { + foreach ($shopIdAndCountMap as $shopId => $count) { + if (in_array($shopId, $stopMoveShopIds)) { + unset($priorityShopsMap[$priority][$shopId]); + } + } + } + + $shopLimitQuotaArray = $this->getShopLimitQuota($shopIds); + Zc::G('start allocProductPublishQuota'); + $selectedShopMap = $this->allocProductPublishQuota($leftCount, $priorityShopsMap, $shopLimitQuotaArray); + Zc::G('end allocProductPublishQuota'); + return $selectedShopMap; + } + + private function statProductPublishBuffer($whereString) { + $priorityShopsMap = array(); + $shopIds = array(); + $rows = $this->db->query("SELECT shop_id, priority, COUNT(*) AS total FROM `move_product_publish_buffer` WHERE TRUE %l group by priority, shop_id ORDER BY priority ASC", $whereString); + foreach ($rows as $row) { + $curPriority = $row['priority']; + $currShopId= $row['shop_id']; + $shopIds[] = $currShopId; + $priorityShopsMap[$curPriority][$currShopId] = $row['total']; + } + + $shopIds = array_unique($shopIds); + return array($priorityShopsMap, $shopIds); + } + + private function getShopLimitQuota($shopIds) { + Zc::G('start getShopMonthQuotaMap'); + $shopMoveQuotaMap = $this->getShopMonthQuotaMap($shopIds); + Zc::G('end getShopMonthQuotaMap'); + $shopDayLimitMap = array(); + foreach ($shopMoveQuotaMap as $shopId => $moveQuotaDetail) { +// $thisMoveUsedTotal = $moveQuotaDetail['total'] + $moveQuotaDetail['attach_total']; +// if ($thisMoveUsedTotal >= 50000) { +// $thisDayLimit = 26000; +// } elseif ($thisMoveUsedTotal >= 10000) { +// $thisDayLimit = 15000; +// } else { +// $thisDayLimit = 10000; +// } + + $shopDayLimitMap[$shopId] = 30000; //背景,抖店修改不用传图,搬家很快,所以基本不用去限制每个客户搬家。 + } + Zc::G('start getShopLast24HoursCount'); + $shopPublishWareTotalList = $this->getShopLast24HoursCount($shopIds); + Zc::G('end getShopLast24HoursCount'); + $shopLimitQuotaArray = array(); + $moveShopLimitList = $this->getBizPerDayShopLimit(); + + Zc::G('start set shopDayLimitMap'); + foreach ($shopDayLimitMap as $shopId => $dayLimit) { + if ($moveShopLimitList[$shopId]['limit'] > 0) { + $dayLimit = $moveShopLimitList[$shopId]['limit']; + } + + $last24HoursCount = $shopPublishWareTotalList[$shopId]['total']; + $durationHour = $shopPublishWareTotalList[$shopId]['durationHour']; + $allowQuota = $this->countNewLimit($shopId, $dayLimit, $last24HoursCount, $durationHour); + $shopLimitQuotaArray[$shopId] = $allowQuota; + } + Zc::G('end set shopDayLimitMap'); + return $shopLimitQuotaArray; + } + + public function getShopMonthQuotaMap($shopIds) { + if (empty($shopIds)) { + return array(); + } + $curMonth = date('Y-m-t 23:59:59'); + $moveConfigList = $this->db->query("select * from `move_shop_config` where `shop_id` IN %li and `gmt_expire` >= now() and `gmt_expire` <= %s", $shopIds, $curMonth); + $moveConfigList = ZcArrayHelper::changeKeyRow($moveConfigList, 'shop_id'); + + $rows = $this->db->query('select shop_id, attach_total from move_attach_total where shop_id in %li', $shopIds); + foreach ($rows as $row) { + $shopId = $row['shop_id']; + $moveConfigList[$shopId]['attach_total'] += $row['attach_total'] ? $row['attach_total'] : 0; + } + return $moveConfigList; + } + + public function getShopLast24HoursCount($shopIds) { + if (empty($shopIds)) { + return array(); + } + $dateTimeStart = strtotime('-24 hour'); + $today = date('Y-m-d'); + $yesterday = date('Y-m-d', $dateTimeStart); + $theHour = date('H', $dateTimeStart); + $shopPublishProductCountList = $this->db->query("SELECT shop_id, the_day, MIN(the_hour) the_hour_min, sum(success_num) as total FROM move_shop_publish_count WHERE shop_id in %li AND success_num > 0 AND (the_day = %s OR (the_day = %s AND the_hour > %i)) GROUP BY shop_id, the_day", $shopIds, $today, $yesterday, $theHour); + $shopPublishProductTotalList = array(); + foreach ($shopPublishProductCountList as $shopPublishProductCountDetail) { + $currShopId = $shopPublishProductCountDetail['shop_id']; + $currTheDay = $shopPublishProductCountDetail['the_day']; + $minHour = $shopPublishProductCountDetail['the_hour_min']; + if ($currTheDay == $yesterday) { + $durationHour = 24 + $theHour - $minHour + 1; + } else { + $durationHour = $theHour - $minHour + 1; + } + $shopPublishProductTotalList[$currShopId]['total'] += $shopPublishProductCountDetail['total']; + + if ($durationHour > $shopPublishProductTotalList[$currShopId]['durationHour']) { + $shopPublishProductTotalList[$currShopId]['durationHour'] = $durationHour; + } + } + return $shopPublishProductTotalList; + } + + public function getBizPerDayShopLimit($filter) { + return $this->shopDao->getBizPerDayShopLimit($filter); + } + + public function deleteExpiryMoveShopLimit() { + return $this->db->delete('move_shop_limit', 'expiry_time <= %s', date('Y-m-d H:i:s')); + } + + public function deleteMoveShopLimit($shopIds) { + if (empty($shopIds)) { + return false; + } + + $ret = $this->db->delete('move_shop_limit', 'shop_id IN %li', $shopIds); + return $ret; + } + + private function countNewLimit($shopId, $dayLimit, $last24HoursCount, $durationHour) { + $limitThresholdNum = (int)($dayLimit * 0.7); + $leftHour = 24 - $durationHour + 1; + $leftHour = ($leftHour > 0) ? $leftHour : 1; + $perHourLimit = (int)(($dayLimit - $last24HoursCount) / $leftHour); + $getLastOneHourCount = $this->getLastOneHourCount($shopId); + + if ($last24HoursCount < $limitThresholdNum) { + $allowQuota = $limitThresholdNum - $last24HoursCount; + } elseif ($getLastOneHourCount < $perHourLimit) { + $allowQuota = $perHourLimit; + } else { + $allowQuota = 0; + } + return $allowQuota ; + } + + public function getLastOneHourCount($shopId) { + $theDay = date('Y-m-d'); + $theHour = date('H'); + $publishProductTotal = $this->db->queryFirstField('SELECT total_num FROM move_shop_publish_count WHERE shop_id = %i AND the_day = %s AND the_hour = %i', $shopId, $theDay, $theHour); + return ($publishProductTotal > 0) ? $publishProductTotal : 0; + } + + private function allocProductPublishQuota($leftCount, $priorityShopsMap, $shopLimitQuotaArray) { + $needSkipShopIdMap = $this->getNeedSkipShopIdMap($shopLimitQuotaArray); + $selectedShopMap = array(); + do { + if (empty($priorityShopsMap)) { + break; + } + + $priorityArr = $this->randPriority(); + list ($shopId, $priority) = $this->getMovePublishBufferRandShopIdByPriorityArr($priorityArr, $priorityShopsMap, $needSkipShopIdMap); + if (empty($shopId)) { + break; + } + + $shopLimitQuotaArray[$shopId]--; + if ($shopLimitQuotaArray[$shopId] <= 0) { + $needSkipShopIdMap[$shopId] = true; + } + + $selectedShopMap[$shopId] = isset($selectedShopMap[$shopId]) ? $selectedShopMap[$shopId] + 1 : 1; + $leftCount--; + if ($leftCount <= 0) { + break; + } + $priorityShopsMap[$priority][$shopId]--; + if (empty($priorityShopsMap[$priority][$shopId])) { + unset($priorityShopsMap[$priority][$shopId]); + } + } while (true); + + return $selectedShopMap; + } + + private function getNeedSkipShopIdMap($shopLimitQuotaArray) { + $needSkipShopIdMap = array(); + foreach ($shopLimitQuotaArray as $shopId => $count) { + if ($count <= 0) { + $needSkipShopIdMap[$shopId] = true; + } + } + return $needSkipShopIdMap; + } + + private function randPriority(){ + $pc = mt_rand(1, 100); + if (($pc >= 1) && ($pc <= 35)) { + $pl = array ( + 98, + 99, + 100, + 101, + 110 + ); + } elseif (($pc >= 36) && ($pc <= 50)) { + $pl = array ( + 99, + 100, + 101, + 103, + 110 + ); + } elseif (($pc >= 51) && ($pc <= 65)) { + $pl = array ( + 100, + 103, + 105, + 110 + ); + } elseif (($pc >= 66) && ($pc <= 75)) { + $pl = array ( + 101, + 103, + 105, + 110 + ); + } elseif (($pc >= 76) && ($pc <= 85)) { + $pl = array ( + 103, + 105, + 110 + ); + } elseif (($pc >= 86) && ($pc <= 95)) { + $pl = array ( + 105, + 110 + ); + } else { + $pl = array ( + 110 + ); + } + + return $pl; + } + + private function getMovePublishBufferRandShopIdByPriorityArr($priorityArr, $priorityShopsMap, $needSkipShopIdMap) { + $shopIds = array(); + $minPriority = min($priorityArr); + $shopIdPriorityMap = array(); + + foreach ($priorityShopsMap as $currPriority => $shopIdCountList) { + $priorityShopIds = array(); + foreach ($shopIdCountList as $shopId => $count) { + if ($needSkipShopIdMap[$shopId]) { + continue; + } + $priorityShopIds[] = $shopId; + $shopIdPriorityMap[$shopId][$currPriority] = true; + } + $shopIds = array_merge($shopIds, $priorityShopIds); + if (($currPriority >= $minPriority) && !empty($shopIds)) { + break; + } + } + $shopIds = array_unique($shopIds); + $shopId = $shopIds[array_rand($shopIds, 1)]; + $priority = current(array_keys($shopIdPriorityMap[$shopId])); + return array($shopId, $priority); + } + + public function moveProductPublishBufferToQueue($selectedShopMap) { + $allBufferRowList = array(); + Zc::G('start process selectedShopMap'); + $execWhere = $this->db->prepare('(gmt_exec < %s or gmt_exec is null)', ZcDateHelper::now()); + $shopBufferCountMap = []; + foreach ($selectedShopMap as $shopId => $count) { + if (empty($count)) { + continue; + } + + $this->moveProductPublishBufferLog->info("start selectBuffer shopId {$shopId} enableMaxCount[$count]"); + $bufferRows = $this->db->query("select * from `move_product_publish_buffer` where `shop_id` = %i and %l ORDER BY move_product_publish_buffer_id ASC limit %i", $shopId, $execWhere, $count); + $bufferRows = ZcArrayHelper::changeKeyRow($bufferRows, 'move_product_publish_buffer_id'); + $this->moveProductPublishBufferLog->info("end selectBuffer shopId {$shopId} count BufferRows is: " . count($bufferRows)); + $allBufferRowList += $bufferRows; + $shopBufferCountMap[$shopId] = count($bufferRows); + } + Zc::G("end process selectedShopMap"); + if (empty($allBufferRowList)) { + $this->moveProductPublishBufferLog->info("end moveShopBufferToQueue for empty bufferRows cost times " . print_r(Zc::G(), true)); + return false; + } + + $chunkBufferRowList = array_chunk($allBufferRowList, 50); + foreach ($chunkBufferRowList as $bufferRowList) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->moveProductPublishBufferLog->info("start addPublishQueueBatch move_product_publish_buffer bufferRowList total:" . count($bufferRowList)); + $affRet = $this->addPublishQueueBatch($bufferRowList); + $this->moveProductPublishBufferLog->info("end addPublishQueueBatch move_product_publish_buffer affRet[$affRet]"); + $bufferIds = ZcArrayHelper::getSub($bufferRowList, 'move_product_publish_buffer_id'); + + if ($affRet) { + $this->moveProductPublishBufferLog->info("start delete move_product_publish_buffer"); + $delRet = $this->db->delete('move_product_publish_buffer', 'move_product_publish_buffer_id in %li', $bufferIds); + $this->moveProductPublishBufferLog->info("end delete move_product_publish_buffer delRet[$delRet] bufferIds total:" . count($bufferIds)); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + $this->moveProductPublishBufferLog->info("start addPublishQueueToRedis"); + + $redisTotal = 0; + foreach ($bufferRowList as $row) { + $redisTotal = $this->addPublishQueueToRedis($row['shop_id'], $row['priority'], $row['move_collect_task_detail_id']); + } + $this->moveProductPublishBufferLog->info("end addPublishQueueToRedis redis Queue Total[$redisTotal]"); + } catch (Exception $ex) { + $shopBufferCountMap = []; + $this->moveProductPublishBufferLog->info($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + } + } + Zc::G('end moveProductPublishBufferToQueue'); + $this->moveProductPublishBufferLog->info("end moveShopBufferToQueue cost times " . print_r(Zc::G(), true)); + return $shopBufferCountMap; + } + + private function addPublishQueueBatch($productDataList){ + $insertListNew = array(); + foreach ($productDataList as $productData) { + $insert = array(); + $insert['shop_id'] = $productData['shop_id']; + $insert['move_collect_task_id'] = $productData['move_collect_task_id']; + $insert['move_collect_task_detail_id'] = $productData['move_collect_task_detail_id']; + $insert['priority'] = $productData['priority']; + $insert['try_times'] = $productData['try_times']; + $insert['gmt_create'] = ZcDbEval::now(); + $insert['gmt_modified'] = ZcDbEval::now(); + $insertListNew[] = $insert; + } + return $this->db->insert('move_product_publish_queue', $insertListNew); + } + + private function addPublishQueueToRedis($shopId, $priority, $moveCollectTaskDetailId) { + if (in_array($shopId, CommonTool::adminSelfShopIds())) { + $moveProductPublishQueueName = RedisKeyConst::moveProductPublishQueueSelf; + } else { + $moveProductPublishQueueName = RedisKeyConst::moveProductPublishQueue; + } + + if ($priority >= 99) { + return $this->solidRedis->lPush($moveProductPublishQueueName, $moveCollectTaskDetailId); + } else { + return $this->solidRedis->rPush($moveProductPublishQueueName, $moveCollectTaskDetailId); + } + } + + public function getLtaoProductInfoFromLtao($sourceItemId, $ltaoAccessToken, $shopId = '') { + for ($i = 0; $i < 10; $i++) { + $ret = $this->ltaoTool->getLtaoProductInfoFromLtao($sourceItemId, $ltaoAccessToken, $shopId); + if (CommonTool::isSuccessRet($ret)) { + return $ret; + } + + if (strpos($ret['reason'], 'frequency limit') !== false || strpos($ret['reason'], '限流') !== false) { + usleep(rand(1000000, 5000000)); + continue; + } else { + return $ret; + } + } + return $ret; + } + + public function getLtaoProductDescFromLtao($sourceItemId, $ltaoAccessToken, $shopId = '') { + for ($i = 0; $i < 10; $i++) { + $ret = $this->ltaoTool->getLtaoProductDescFromLtao($sourceItemId, $ltaoAccessToken, $shopId); + if (CommonTool::isSuccessRet($ret)) { + return $ret; + } + + if (strpos($ret['reason'], 'frequency limit') !== false || strpos($ret['reason'], '限流') !== false) { + usleep(rand(1000000, 5000000)); + continue; + } else { + return $ret; + } + } + return $ret; + } + + public function lockProductPublishQueue($timerLockId, $filter){ + if ($filter['includeShopIds']) { + $moveProductPublishQueueName = RedisKeyConst::moveProductPublishQueueSelf; + } else { + $moveProductPublishQueueName = RedisKeyConst::moveProductPublishQueue; + } + + $taskDetailId = $this->solidRedis->rPop($moveProductPublishQueueName); + if (empty($taskDetailId)) { + $this->productPublishLockRedisLog->info("timerLockId [$timerLockId] move_product_publish_queueName[$moveProductPublishQueueName] taskDetailId $taskDetailId getEmpty"); + return array(); + } + + $affectRows = $this->db->update('move_product_publish_queue', array ( + 'locked' => $timerLockId, + 'gmt_locked' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "move_collect_task_detail_id = %i AND locked = 0", $taskDetailId); + if ($affectRows != 1) { + $this->productPublishLockRedisLog->info("timerLockId [$timerLockId] taskDetailId $taskDetailId move_product_publish_queueName[$moveProductPublishQueueName] locked empty"); + return array(); + } + $lockMsg = $this->db->queryFirstRow("select * from `move_product_publish_queue` where move_collect_task_detail_id = %i", $taskDetailId); + if (empty($lockMsg)) { + return $lockMsg; + } + + return $this->buildMoveTaskDetailInfoToQueue($lockMsg); + } + + public function getImportProductDetail($shopId, $taskId, $detailId) { + $ossPath = "move_import/$shopId/$taskId/$detailId.txt"; + $ret = OssTool::getImmutableObjectByContent($ossPath); + return unserialize($ret['body']); + } + + public function buildMoveTaskDetailInfoToQueue($lockMsg) { + $shopId = $lockMsg['shop_id']; + $moveCollectTaskId = $lockMsg['move_collect_task_id']; + $moveCollectTaskDetailId = $lockMsg['move_collect_task_detail_id']; + + $moveCollectTask = $this->getMoveCollectTask($moveCollectTaskId, $shopId); + $moveCollectTask['condition'] = $this->restoreConditionsBigField($moveCollectTask['condition'], $shopId); + $moveCollectTaskDetail = $this->getMoveCollectTaskDetail($shopId, $moveCollectTaskDetailId); + $moveCollectTaskDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $moveCollectTaskDetailId); + + $lockMsg['copy_type'] = $moveCollectTask['copy_type']; + $lockMsg['condition'] = $moveCollectTask['condition']; + if ($lockMsg['condition']) { + $lockMsg['condition']['is_fast_mode'] = $moveCollectTaskDetail['is_fast_mode']; + } + + $lockMsg['is_fast_mode'] = $moveCollectTaskDetail['is_fast_mode']; + $lockMsg['source'] = $moveCollectTaskDetail['source']; + $lockMsg['site'] = $moveCollectTaskDetail['site']; + $lockMsg['source_item_id'] = $moveCollectTaskDetail['source_item_id']; + $lockMsg['source_title'] = $moveCollectTaskDetail['source_title']; + $lockMsg['source_shop_name'] = $moveCollectTaskDetail['source_shop_name']; + $lockMsg['source_img_url'] = $moveCollectTaskDetail['source_img_url']; + $lockMsg['cid'] = $moveCollectTaskDetail['cid']; + $lockMsg['auth_shop_id'] = $moveCollectTaskDetail['auth_shop_id']; + $lockMsg['publish_hostname'] = $moveCollectTaskDetail['publish_hostname']; + + $lockMsg['product_image_urls'] = $moveCollectTaskDetailExt['product_image_urls']; + $lockMsg['need_shift_img'] = $moveCollectTaskDetailExt['need_shift_img']; + $lockMsg['has_change_img'] = $moveCollectTaskDetailExt['has_change_img']; + $lockMsg['del_img_urls'] = $moveCollectTaskDetailExt['del_img_urls']; + $lockMsg['notes'] = $moveCollectTaskDetailExt['notes']; + $lockMsg['has_save_notes'] = $moveCollectTaskDetailExt['has_save_notes']; + $lockMsg['move_import_task_id'] = $moveCollectTaskDetailExt['move_import_task_id']; + $lockMsg['move_import_task_detail_id'] = $moveCollectTaskDetailExt['move_import_task_detail_id']; + + $lockMsg['price'] = $moveCollectTaskDetailExt['price']; + $lockMsg['market_price'] = $moveCollectTaskDetailExt['market_price']; + + $lockMsg['skus'] = $moveCollectTaskDetailExt['skus']; + $lockMsg['props'] = $moveCollectTaskDetailExt['props']; + $lockMsg['brand_id'] = $moveCollectTaskDetailExt['brand_id']; + $lockMsg['class_quality'] = $moveCollectTaskDetailExt['class_quality']; + $lockMsg['quality_report'] = $moveCollectTaskDetailExt['quality_report']; + $lockMsg['fetch_bank_detail_id'] = $moveCollectTaskDetailExt['fetch_bank_detail_id']; + $lockMsg['recommend_remark'] = $moveCollectTaskDetailExt['recommend_remark']; + $lockMsg['move_group_task_detail_id'] = $moveCollectTaskDetailExt['move_group_task_detail_id']; + $lockMsg['cnali_ds_detail_id'] = $moveCollectTaskDetailExt['cnali_ds_detail_id']; + $lockMsg['presell_type'] = $moveCollectTaskDetailExt['presell_type']; + $lockMsg['delivery_delay_day'] = $moveCollectTaskDetailExt['delivery_delay_day']; + $lockMsg['presell_delay'] = $moveCollectTaskDetailExt['presell_delay']; + $lockMsg['presell_end_time'] = $moveCollectTaskDetailExt['presell_end_time']; + $lockMsg['place_order_delay'] = $moveCollectTaskDetailExt['place_order_delay']; + $lockMsg['freight_template_id'] = $moveCollectTaskDetailExt['freight_template_id']; + $lockMsg['reduce_type'] = $moveCollectTaskDetailExt['reduce_type']; + $lockMsg['limit_per_buyer'] = $moveCollectTaskDetailExt['limit_per_buyer']; + $lockMsg['maximum_per_order'] = $moveCollectTaskDetailExt['maximum_per_order']; + $lockMsg['minimum_per_order'] = $moveCollectTaskDetailExt['minimum_per_order']; + $lockMsg['item_num'] = $moveCollectTaskDetailExt['item_num']; + $lockMsg['quality_map'] = $moveCollectTaskDetailExt['quality_map']; + $lockMsg['size_template_id'] = $moveCollectTaskDetailExt['size_template_id']; + $lockMsg['sku_presell_child_sku_detail'] = $moveCollectTaskDetailExt['skus']['skuPresellChildSkuDetail']; + $lockMsg['presell_time_sku_spec_name_and_stock_percent_map'] = $moveCollectTaskDetailExt['skus']['presellTimeSkuSpecNameAndStockPercentMap']; + $lockMsg['video_url'] = $moveCollectTaskDetailExt['video_url']; + $lockMsg['material_video_id'] = $moveCollectTaskDetailExt['material_video_id']; + $lockMsg['video_upload_folder_id'] = $moveCollectTaskDetailExt['video_upload_folder_id']; + $lockMsg['white_bg_img_url'] = $moveCollectTaskDetailExt['white_bg_img_url']; + $lockMsg['long_pic_url'] = $moveCollectTaskDetailExt['long_pic_url']; + $lockMsg['generate_long_pic_by_miaoshou_xiuxiu'] = $moveCollectTaskDetailExt['generate_long_pic_by_miaoshou_xiuxiu']; + $lockMsg['match_cid'] = $moveCollectTaskDetailExt['match_cid']; + $lockMsg['use_recommend_cid'] = $moveCollectTaskDetailExt['use_recommend_cid']; + $lockMsg['source_category_path'] = $moveCollectTaskDetailExt['source_category_path']; + $lockMsg['supply_7day_return'] = $moveCollectTaskDetailExt['supply_7day_return']; + $lockMsg['clue_id'] = $moveCollectTaskDetailExt['clue_id']; + $lockMsg['source_attrs'] = $moveCollectTaskDetailExt['source_attrs']; + $lockMsg['name_prefix'] = $moveCollectTaskDetailExt['name_prefix']; + return $lockMsg; + } + + public function checkAndGetSupportSkuPresellType($presellType, $cid, $shopId) { + $shopInfo = $this->shopDao->getShop($shopId); + $ruleRet = $this->productDao->getProductUpdateRule($shopId, $cid, $shopInfo['access_token']); + + $supportPresellTypeList = []; + foreach ($ruleRet['rule'] as $key => $support) { + if (!$support) { + continue; + } + + switch ($key) { + case 'normal_rule' : + $supportPresellTypeList[] = MoveConst::presellTypeNow; + break; + case 'product_presell_rule' : + $supportPresellTypeList[] = MoveConst::presellTypePresell; + break; + case 'step_rule' : + $supportPresellTypeList[] = MoveConst::presellTypeStair; + break; + case 'time_sku_presell_with_normal_rule' : + $supportPresellTypeList[] = MoveConst::presellConfigLevelNowAndPresell; + break; + } + } + + if (in_array($presellType, $supportPresellTypeList)) { + return $presellType; + } + return in_array(MoveConst::presellTypeNow, $supportPresellTypeList) ? MoveConst::presellTypeNow : array_shift($supportPresellTypeList); + } + + public function getMoveCollectTask($moveCollectTaskId, $shopId) { + $moveCollectTask = $this->db->queryFirstRow("SELECT * FROM move_collect_task WHERE move_collect_task_id = %i AND shop_id = %i", $moveCollectTaskId, $shopId); + if (empty($moveCollectTask)) { + return $moveCollectTask; + } + + $moveCollectTask['condition'] = unserialize($moveCollectTask['condition']); + return $moveCollectTask; + } + + public function restoreConditionsBigField($condition, $shopId) { + $bigFieldIds = []; + if(!empty($condition['desc']['descPrefixId'])){ + $bigFieldIds[] = $condition['desc']['descPrefixId']; + } + if(!empty($condition['desc']['descSuffixId'])){ + $bigFieldIds[] = $condition['desc']['descSuffixId']; + } + if(!empty($condition['desc']['descPrefixImgId'])){ + $bigFieldIds[] = $condition['desc']['descPrefixImgId']; + } + if(!empty($condition['desc']['descSuffixImgId'])){ + $bigFieldIds[] = $condition['desc']['descSuffixImgId']; + } + if(!empty($condition['title']['titleDeleteId'])){ + $bigFieldIds[] = $condition['title']['titleDeleteId']; + } + if (!empty($condition['skipTitleKeywordId'])) { + $bigFieldIds[] = $condition['skipTitleKeywordId']; + } + if (!empty($condition['skipSkuAliasKeywordId'])) { + $bigFieldIds[] = $condition['skipSkuAliasKeywordId']; + } + if (!empty($condition['skipSendCityInfoId'])) { + $bigFieldIds[] = $condition['skipSendCityInfoId']; + } + if (!empty($condition['recommendRemarkSearchId'])) { + $bigFieldIds[] = $condition['recommendRemarkSearchId']; + } + if (!empty($condition['recommendRemarkReplaceId'])) { + $bigFieldIds[] = $condition['recommendRemarkReplaceId']; + } + if (!empty($condition['recommendRemarkPrefixId'])) { + $bigFieldIds[] = $condition['recommendRemarkPrefixId']; + } + if (!empty($condition['recommendRemarkSuffixId'])) { + $bigFieldIds[] = $condition['recommendRemarkSuffixId']; + } + if (!empty($condition['skipBrandKeywordId'])) { + $bigFieldIds[] = $condition['skipBrandKeywordId']; + } + if (!empty($condition['qualityReportId'])) { + $bigFieldIds[] = $condition['qualityReportId']; + } + if (!empty($condition['classQualityId'])) { + $bigFieldIds[] = $condition['classQualityId']; + } + if (!empty($condition['skuAliasDeleteId'])) { + $bigFieldIds[] = $condition['skuAliasDeleteId']; + } + if (!empty($condition['sku']['skuSearchId'])) { + $bigFieldIds[] = $condition['sku']['skuSearchId']; + } + if (!empty($condition['sku']['skuReplaceId'])) { + $bigFieldIds[] = $condition['sku']['skuReplaceId']; + } + if (!empty($condition['skipShopNameId'])) { + $bigFieldIds[] = $condition['skipShopNameId']; + } + if(!empty($condition['presetCateAttrsId'])) { + $bigFieldIds[] = $condition['presetCateAttrsId']; + } + if (!empty($condition['title']['titleSearchId'])) { + $bigFieldIds[] = $condition['title']['titleSearchId']; + } + if (!empty($condition['title']['titleReplaceId'])) { + $bigFieldIds[] = $condition['title']['titleReplaceId']; + } + if (empty($bigFieldIds)) { + return $condition; + } + + $fieldData = $this->db->query('SELECT field_name ,content FROM move_shop_setting_big_field WHERE move_shop_setting_big_field_id IN %li AND shop_id = %i', $bigFieldIds, $shopId); + $fieldData = ZcArrayHelper::changeKeyRow($fieldData, 'field_name'); + if(!empty($fieldData['skip_title_keyword'])){ + $condition['skipTitleKeyword'] = str_replace(',', ',', $fieldData['skip_title_keyword']['content']); + } + if(!empty($fieldData['skip_sku_alias_keyword'])){ + $condition['skipSkuAliasKeyword'] = str_replace(',', ',', $fieldData['skip_sku_alias_keyword']['content']); + } + if(!empty($fieldData['skip_brand_keyword'])){ + $condition['skipBrandKeyword'] = str_replace(',', ',', $fieldData['skip_brand_keyword']['content']); + } + if (!empty($fieldData['skip_send_city_info'])) { + $condition['skipSendCityInfo'] = json_decode($fieldData['skip_send_city_info']['content'], true); + } + if(!empty($fieldData['title_delete'])){ + $condition['title']['titleDelete'] = str_replace([',', '、'], ',', $fieldData['title_delete']['content']); + } + if(!empty($fieldData['desc_suffix'])){ + $condition['desc']['descSuffix'] = rtrim($fieldData['desc_suffix']['content']); + } + if (!empty($fieldData['desc_prefix'])) { + $condition['desc']['descPrefix'] = ltrim($fieldData['desc_prefix']['content']); + } + if(!empty($fieldData['desc_suffix_img'])){ + $condition['desc']['descSuffixImg'] = rtrim($fieldData['desc_suffix_img']['content']); + } + if (!empty($fieldData['desc_prefix_img'])) { + $condition['desc']['descPrefixImg'] = ltrim($fieldData['desc_prefix_img']['content']); + } + if (!empty($fieldData['quality_report'])) { + $condition['qualityReport'] = ltrim($fieldData['quality_report']['content']); + } + if (!empty($fieldData['class_quality'])) { + $condition['classQuality'] = ltrim($fieldData['class_quality']['content']); + } + if (!empty($fieldData['recommend_remark_search'])) { + $condition['recommendRemarkSearch'] = unserialize($fieldData['recommend_remark_search']['content']); + } + if (!empty($fieldData['recommend_remark_replace'])) { + $condition['recommendRemarkReplace'] = unserialize($fieldData['recommend_remark_replace']['content']); + } + if (!empty($fieldData['recommend_remark_prefix'])) { + $condition['recommendRemarkPrefix'] = $fieldData['recommend_remark_prefix']['content']; + } + if (!empty($fieldData['recommend_remark_suffix'])) { + $condition['recommendRemarkSuffix'] = $fieldData['recommend_remark_suffix']['content']; + } + if (!empty($fieldData['sku_alias_delete'])) { + $condition['skuAliasDelete'] = str_replace([',', '、'], ',', $fieldData['sku_alias_delete']['content']); + } + if (!empty($fieldData['sku_search'])) { + $condition['sku']['skuSearch'] = unserialize($fieldData['sku_search']['content']); + } + if (!empty($fieldData['sku_replace'])) { + $condition['sku']['skuReplace'] = unserialize($fieldData['sku_replace']['content']); + } + if (!empty($fieldData['skip_shop_name'])) { + $condition['skipShopName'] = str_replace(',', ',', $fieldData['skip_shop_name']['content']); + } + if (!empty($fieldData['preset_cate_attrs'])) { + $condition['presetCateAttrs'] = unserialize($fieldData['preset_cate_attrs']['content']); + } + if (!empty($fieldData['title_search'])) { + $condition['title']['titleSearch'] = unserialize($fieldData['title_search']['content']); + } + if (!empty($fieldData['title_replace'])) { + $condition['title']['titleReplace'] = unserialize($fieldData['title_replace']['content']); + } + return $condition; + } + + public function getMoveCollectTaskDetail($shopId, $detailId) { + return $this->db->queryFirstRow("SELECT * FROM move_collect_task_detail WHERE move_collect_task_detail_id = %i AND shop_id = %i", $detailId, $shopId); + } + + public function getMoveCollectTaskDetailByIds($shopId, $detailIds) { + return $this->db->query("select * from move_collect_task_detail where shop_id = %i and move_collect_task_detail_id in %li", $shopId, $detailIds); + } + + public function getMoveProductLogByDetailIds($shopId, $detailIds) { + return $this->db->query("select * from move_product_log where shop_id = %i and move_collect_task_detail_id in %li", $shopId, $detailIds); + } + + public function getCollectTaskSourceAttrs($shopId, $productId) { + $moveLog = $this->db->queryFirstRow("SELECT * FROM move_product_log WHERE product_id = %i", strval($productId)); + $moveCollectTaskDetailId = $moveLog ? $moveLog['move_collect_task_detail_id'] : 0; + $sourceAttrs = []; + if ($moveCollectTaskDetailId) { + $moveCollectTaskDetailExt = $this->getMoveCollectTaskDetailExt($moveLog['shop_id'], $moveCollectTaskDetailId); + $sourceAttrs = $moveCollectTaskDetailExt['source_attrs'] ? $moveCollectTaskDetailExt['source_attrs'] : []; + + $dsSourceAttrs = $this->tryGetSourceAttrsFromDs($shopId, $productId); + if ($dsSourceAttrs) { + $sourceAttrs = $dsSourceAttrs; + } + } + return $sourceAttrs; + } + + private function tryGetSourceAttrsFromDs($shopId, $productId) { + $productInfo = $this->tryGetDsProductInfo($shopId, $productId); + if (empty($productInfo)) { + return []; + } + + return $productInfo['sourceAttrs']; + } + + private function tryGetDsProductInfo($shopId, $productId) { + $sourceItemId = $this->getDsSourceItemId($shopId, $productId); + if (empty($sourceItemId)) { + return []; + } + + $memberId = $this->getAlibabaMemberId($shopId); + $sourceProductDataRet = $this->dsClient->getSourceProductData($shopId, AppConst::getDsPlatform(), 0, $memberId, $sourceItemId); + if (CommonTool::isFailRet($sourceProductDataRet)) { + return []; + } + + $productInfo = $sourceProductDataRet['productInfo']; + $productInfo['productId'] = $sourceItemId; + return $productInfo; + } + + public function getMoveCollectTaskDetailExt($shopId, $moveCollectTaskDetailId, $onlyReadDb = false) { + $moveCollectTaskDetailExt = $this->db->queryFirstRow("SELECT * FROM move_collect_task_detail_ext WHERE move_collect_task_detail_id = %i AND shop_id = %i", $moveCollectTaskDetailId, $shopId); + + if (!empty($moveCollectTaskDetailExt['product_image_urls'])) { + $moveCollectTaskDetailExt['product_image_urls'] = unserialize($moveCollectTaskDetailExt['product_image_urls']); + } + if (!empty($moveCollectTaskDetailExt['del_img_urls'])) { + $moveCollectTaskDetailExt['del_img_urls'] = unserialize($moveCollectTaskDetailExt['del_img_urls']); + } + + if (!empty($moveCollectTaskDetailExt['props'])) { + $moveCollectTaskDetailExt['props'] = unserialize($moveCollectTaskDetailExt['props']); + } + + if (!empty($moveCollectTaskDetailExt['source_attrs'])) { + $moveCollectTaskDetailExt['source_attrs'] = unserialize($moveCollectTaskDetailExt['source_attrs']); + } + + if (!empty($moveCollectTaskDetailExt['skus'])) { + $moveCollectTaskDetailExt['skus'] = unserialize($moveCollectTaskDetailExt['skus']); + } + + if (!empty($moveCollectTaskDetailExt['quality_map'])) { + $moveCollectTaskDetailExt['quality_map'] = unserialize($moveCollectTaskDetailExt['quality_map']); + } + + if (empty($moveCollectTaskDetailExt) && !$onlyReadDb) { + $moveCollectTaskDetailExt = $this->getMoveProductAndSkusFromOss($shopId, $moveCollectTaskDetailId); + } + + return $moveCollectTaskDetailExt; + } + + public function updateMoveCollectTaskDetailExt($shopId, $moveCollectTaskDetailId, $product) { + $moveCollectTaskDetailExt = $this->db->queryFirstRow("SELECT * FROM move_collect_task_detail_ext WHERE move_collect_task_detail_id = %i AND shop_id = %i", $moveCollectTaskDetailId, $shopId); + $updateTaskDetailExt = array( + 'product_image_urls' => !empty($product['product_image_urls']) ? $product['product_image_urls'] : null, + 'price' => $product['price'], + 'pingou_price' => $product['pingou_price'], + 'market_price' => $product['market_price'], + 'cost_price' => $product['cost_price'], + 'skus' => !empty($product['skus']) ? $product['skus'] : null, + 'has_change_img' => $product['has_change_img'] ? MoveConst::settingBoolTrue : null, + 'need_shift_img' => $product['need_shift_img'] ? MoveConst::settingBoolTrue : null, + 'props' => !empty($product['props']) ? $product['props'] : null, + 'del_img_urls' => !empty($product['del_img_urls']) ? $product['del_img_urls'] : null, + 'notes' => !empty($product['notes']) ? $product['notes'] : null, + 'has_save_notes' => $product['has_save_notes'], + 'source_attrs' => !empty($product['source_attrs']) ? $product['source_attrs'] : null, + 'quality_map' => !empty($product['quality_map']) ? $product['quality_map'] : null, + 'has_change_color_map' => $product['has_change_color_map'], + 'has_change_size_map' => $product['has_change_size_map'], + 'has_change_title' => $product['has_change_title'], + 'brand_id' => $product['brand_id'], + 'fetch_bank_detail_id' => $product['fetch_bank_detail_id'], + 'class_quality' => $product['class_quality'], + 'quality_report' => $product['quality_report'], + 'recommend_remark' => $product['recommend_remark'], + 'presell_type' => $product['presell_type'], + 'delivery_delay_day' => $product['delivery_delay_day'], + 'presell_delay' => $product['presell_delay'], + 'presell_end_time' => $product['presell_end_time'], + 'place_order_delay' => $product['place_order_delay'], + 'reduce_type' => $product['reduce_type'], + 'freight_template_id' => $product['freight_template_id'], + 'limit_per_buyer' => $product['limit_per_buyer'], + 'maximum_per_order' => $product['maximum_per_order'], + 'minimum_per_order' => $product['minimum_per_order'], + 'match_cid' => $product['match_cid'], + 'source_category_path' => $product['source_category_path'], + 'item_num' => $product['item_num'], + 'video_url' => !empty($product['video_url']) ? $product['video_url'] : null, + 'material_video_id' => !empty($product['material_video_id']) ? $product['material_video_id'] : null, + 'video_upload_folder_id' => !empty($product['video_upload_folder_id']) ? $product['video_upload_folder_id'] : 0, + 'generate_long_pic_by_miaoshou_xiuxiu' => !empty($product['generate_long_pic_by_miaoshou_xiuxiu']) ? $product['generate_long_pic_by_miaoshou_xiuxiu'] : 0, + 'white_bg_img_url' => !empty($product['white_bg_img_url']) ? $product['white_bg_img_url'] : null, + 'long_pic_url' => !empty($product['long_pic_url']) ? $product['long_pic_url'] : null, + 'size_template_id' => $product['size_template_id'], + 'gmt_modified' => ZcDbEval::now(), + ); + + if ($moveCollectTaskDetailExt) { + if (!empty($updateTaskDetailExt['product_image_urls'])) { + $updateTaskDetailExt['product_image_urls'] = serialize($updateTaskDetailExt['product_image_urls']); + } + if (!empty($updateTaskDetailExt['del_img_urls'])) { + $updateTaskDetailExt['del_img_urls'] = serialize($moveCollectTaskDetailExt['del_img_urls']); + } + if (!empty($updateTaskDetailExt['props'])) { + $updateTaskDetailExt['props'] = serialize($updateTaskDetailExt['props']); + } + if (!empty($updateTaskDetailExt['source_attrs'])) { + $updateTaskDetailExt['source_attrs'] = serialize($updateTaskDetailExt['source_attrs']); + } + if (!empty($updateTaskDetailExt['skus'])) { + $updateTaskDetailExt['skus'] = serialize($updateTaskDetailExt['skus']); + } + if (!empty($updateTaskDetailExt['quality_map'])) { + $updateTaskDetailExt['quality_map'] = serialize($updateTaskDetailExt['quality_map']); + } + $this->db->update('move_collect_task_detail_ext', $updateTaskDetailExt, "move_collect_task_detail_id = %i", $moveCollectTaskDetailId); + } else { + $taskDetailExt = $this->getMoveProductAndSkusFromOss($shopId, $moveCollectTaskDetailId); + $taskDetailExt = $updateTaskDetailExt + $taskDetailExt; + + $saveOssRet = $this->saveMoveProductAndSkusToOss($shopId, $moveCollectTaskDetailId, $taskDetailExt); + if (CommonTool::isFailRet($saveOssRet)) { + return $saveOssRet; + } + } + return CommonTool::successResult(); + } + + public function getMoveProductAndSkusFromOss($shopId, $moveCollectTaskDetailId) { + return $this->productDao->getMoveProductAndSkusFromOss($shopId, $moveCollectTaskDetailId); + } + + public function insertUpdateMoveCollectTaskDetailRetry($shopId, $moveCollectTaskDetailId) { + return $this->productDao->insertUpdateMoveCollectTaskDetailRetry($shopId, $moveCollectTaskDetailId); + } + + public function updateMoveCollectTaskDetail ($updateData, $shopId, $detailId) { + $updateData['gmt_modified'] = ZcDbEval::now(); + + return $this->db->update('move_collect_task_detail', $updateData, 'shop_id = %i AND move_collect_task_detail_id = %i', $shopId, $detailId); + } + + public function insertMoveSiblingSkuIdTemp($shopId, $taskDetailId, $skuId, $siblingSkuIds) { + if (empty($siblingSkuIds)) { + return ; + } + $skuId = $this->rebuildSourceItemId($skuId); + $res = $this->db->query("SELECT move_sku_temps_id FROM move_sku_temps WHERE shop_id = %i AND sibling_sku_id = %i", $shopId, $skuId); + if (!empty($res)) { + return false; + } + $insert = array(); + foreach ($siblingSkuIds as $siblingSkuId) { + $siblingSkuId = $this->rebuildSourceItemId($siblingSkuId); + + $insert[] = array( + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $taskDetailId, + 'sku_id' => $skuId, + 'sibling_sku_id' => $siblingSkuId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + } + return $this->db->insert('move_sku_temps', $insert); + } + + public function deleteMoveSiblingSkuIdTemp($shopId, $skuId) { + $skuId = $this->rebuildSourceItemId($skuId); + $ret = $this->db->delete('move_sku_temps', 'shop_id = %i AND sku_id = %i', $shopId, $skuId); + if ($ret === false) { + $this->moveLog->info("deleteMoveSiblingSkuIdTemp fail, sql[" . $this->db->lastSql() . '], msg[' . $this->db->lastException()->getMessage() . ']'); + } + return $ret; + } + + public function rebuildSourceItemId($sourceItemId) { + if (empty($sourceItemId)) { + return $sourceItemId; + } + + $sourceItemIdList = explode('_', $sourceItemId); + if (count($sourceItemIdList) == 2 && is_numeric($sourceItemIdList[1])) { + return $sourceItemIdList[1]; + } + + return $sourceItemId; + } + + public function updateSourceAttrsToDetailExt($sourceAttrs, $moveCollectTaskDetailId, $shopId) { + if (CommonTool::anyEmpty($sourceAttrs, $moveCollectTaskDetailId, $shopId)) { + return false; + } + + return $this->db->update('move_collect_task_detail_ext', array( + 'source_attrs' => serialize($sourceAttrs), + ), 'move_collect_task_detail_id = %i AND shop_id = %i', $moveCollectTaskDetailId, $shopId); + } + + public function setMoveDetailNotice($notice, $moveCollectTaskDetailId, $publishTips = '') { + $data = [ + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + ]; + + if(!empty($publishTips)) { + $data['publish_tips'] = json_encode($publishTips); + } + + if(!empty($notice)) { + $data['notice'] = $notice; + } + + return $this->db->insertUpdate('move_collect_task_detail_notice', $data, $data); + } + + public function archiveMoveDetailExtDataToOss($shopId, $moveCollectTaskDetailId, $sourceAttrs = [], $logObj = null) { + if (!($logObj instanceof ZcLog)) { + $logObj = Zc::getLog('move/archive_move_collect_task_detail_ext', ZcLog::INFO); + } + $onlyReadDb = empty($sourceAttrs); + $taskDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $moveCollectTaskDetailId, $onlyReadDb); + if (empty($taskDetailExt)) { + return CommonTool::successResult(); + } + + if (!empty($sourceAttrs)) { + $taskDetailExt['source_attrs'] = $sourceAttrs; + } + + $saveOssRet = $this->saveMoveProductAndSkusToOss($shopId, $moveCollectTaskDetailId, $taskDetailExt); + if (CommonTool::isFailRet($saveOssRet)) { + $logObj->info("archiveMoveDetailExtDataToOss saveMoveProductAndSkusToOss shopId[{$shopId}] mctdId[{$moveCollectTaskDetailId}] archiveMoveDetailData " . print_r($taskDetailExt, true) . '\n ret : ' . print_r($saveOssRet, true)); + return $saveOssRet; + } + + $delRet = $this->delMoveTaskCollectTaskDetailExtById($moveCollectTaskDetailId, $shopId); + $logObj->info("del task detail ext data [{$delRet}]"); + return CommonTool::successResult(); + } + + public function saveMoveProductAndSkusToOss($shopId, $moveCollectTaskDetailId, $ossProductAndSkuData) { + $ossProductAndSkuData = serialize($ossProductAndSkuData); + $objectPath = "dd_mctd/{$shopId}/{$moveCollectTaskDetailId}.txt"; + + $ret = OssTool::uploadImmutableObjectByContent($objectPath, $ossProductAndSkuData); + if (CommonTool::isFailRet($ret)) { + return CommonTool::failResult('备份数据到Oss失败, ' . $ret['reason']); + } else { + return CommonTool::successResult(); + } + } + + public function delMoveTaskCollectTaskDetailExtById($moveCollectTaskDetailId, $shopId) { + return $this->db->delete('move_collect_task_detail_ext', 'move_collect_task_detail_id = %i AND shop_id = %i', $moveCollectTaskDetailId, $shopId); + } + + + public function updateMoveGroupPublishStatus($processRet, $moveGroupTaskDetailId, $shopId, $log) { + if ($moveGroupTaskDetailId > 0) { + $updateRet = $this->updateMoveGroupTaskDetailResult($processRet, $moveGroupTaskDetailId); + $this->statisticMoveGroupMoveStatus($processRet, $moveGroupTaskDetailId, $shopId); + $log->info('updateMoveGroupTaskDetailResult ->' . print_r($updateRet, true)); + } + } + + public function addMovePriceExceptionLog($detailId, $shopId, $reason) { + $this->db->insert('move_price_exception_log', [ + 'move_collect_task_detail_id' => $detailId, + 'shop_id' => $shopId, + 'reason' => $reason, + 'gmt_create' => date('Y-m-d H:i:s'), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]); + } + + private function checkAndStopShopMove($queueMsg, $addProductRet) { + if ($this->isShopLimitPublishReason($addProductRet['reason'])) { + $shopId = $queueMsg['shop_id']; + $this->insertMoveShopStop($shopId, $addProductRet['reason']); + $this->syncDsMoveStopInfo($shopId, $addProductRet['reason']); + } + } + + private function syncDsMoveStopInfo($shopId, $reason) { + $moveShopStopInfo = $this->getMoveShopStopInfoByShopId($shopId); + $moveShopStopInfo['reason'] = HtmlTool::transitionErrReason($reason, $moveShopStopInfo, StatusConst::process, 0); + $this->dsClient->batchUpdateDsMovePlatformShopStop(AppConst::getDsPlatform(), array($shopId => $moveShopStopInfo)); + } + + private function isShopLimitPublishReason($reason) { + return strpos($reason, '因为店铺受到处罚,限制发品') !== false; + } + + public function processMovePublishQueueRet($queueMsg, $addProductRet, $publishCostSeconds) { + $sourceItemId = $queueMsg['source_item_id']; + $shopId = $queueMsg['shop_id']; + $detailId = $queueMsg['move_collect_task_detail_id']; + $cnaliDsDetailId = $queueMsg['cnali_ds_detail_id']; + $taskId = $queueMsg['move_collect_task_id']; + $tryTimes = $queueMsg['try_times'] ?: 0; + + if (CommonTool::isSuccessRet($addProductRet)) { + $productDetailBase = $addProductRet['productDetailBase']; + $imgUrls = $this->getMovePublishAllImgs($productDetailBase); + + $urlAndMaterialIdMap = $this->materialDao->getUrlAndMaterialIdMapBySourceUrl($shopId, $imgUrls); + + $updateMoveCollectTaskDetailData = [ + 'reason' => '铺货数据组装完毕,等待抖店审核图片通过', + 'publish_cost_seconds' => $publishCostSeconds + ]; + $queueId = $this->moveDao->createMoveProductPublishToPicQueue($queueMsg); + if(empty($queueId)) { + $updateMoveCollectTaskDetailData = [ + 'reason' => '写入图片处理队列失败,请重试任务', + 'status' => StatusConst::fail + ]; + } + $saveMaterialBizRet = $this->materialDao->saveMaterialBiz($shopId, BizConst::bizMove, $queueId, array_values($urlAndMaterialIdMap), []); + if(CommonTool::isFailRet($saveMaterialBizRet)) { + $updateMoveCollectTaskDetailData = [ + 'reason' => '图片业务处理失败,请重试任务', + 'status' => StatusConst::fail + ]; + } + $this->updateMoveCollectTaskDetail($updateMoveCollectTaskDetailData, $shopId, $detailId); + } else { + if (CommonTool::checkIsFrequencyLimitReason($addProductRet['reason']) && $queueMsg['try_times'] < 3) { + $this->addTaskBuffer($shopId, $taskId, $detailId, 1, $queueMsg['limit_source'], $tryTimes + 1, date('Y-m-d H:i:s', time() + rand(60, 600))); + return; + } + + $publishLoger = Zc::getLog('timer/move/publish/' . date('Y-m-d') . '/' . $sourceItemId . '_' . $shopId); + $publishStat = $addProductRet['code'] == ErrorCodeConst::skip ? 'skip' : 'error'; + $publishLoger->info('------queueMsg---' . print_r($queueMsg, true)); + if (empty($cnaliDsDetailId)) { + $this->revertMoveCopyCount($shopId, $detailId, 'processMovePublishQueueRet'); + } + + $this->updateMoveCollectTaskDetail(array( + 'status' => $addProductRet['code'] == ErrorCodeConst::skip ? ErrorCodeConst::skip : StatusConst::fail, + 'reason' => $addProductRet['reason'], + 'publish_cost_seconds' => $publishCostSeconds + ), $shopId, $detailId); + $this->processCreateProductRetCommonPart($queueMsg, StatusConst::fail, $addProductRet, $publishCostSeconds, $publishStat, $publishLoger); + } + } + + public function processCreateProductRet($queueMsg, $addProductRet, $parseCostSeconds) { + $sourceItemId = $queueMsg['source_item_id']; + $shopId = $queueMsg['shop_id']; + $detailId = $queueMsg['move_collect_task_detail_id']; + $title = $queueMsg['source_title']; + $cnaliDsDetailId = $queueMsg['cnali_ds_detail_id']; + $this->checkAndStopShopMove($queueMsg, $addProductRet); + + $isMoveToBuffer = false; + $publishLoger = Zc::getLog('timer/move/publish/' . date('Y-m-d') . '/' . $sourceItemId . '_' . $shopId); + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + if (CommonTool::isSuccessRet($addProductRet)) { + $this->insertMoveProductLog($addProductRet, $shopId, $detailId, $title); + $status = StatusConst::success; + $publishStat = 'success'; + } else { + $retryQueueRet = $this->checkAndRetryMoveProductPublishQueue($queueMsg, $addProductRet); + $publishLoger->info(sprintf('checkAndRetryMoveProductPublishQueue with reason: %s, and ret: %s', $addProductRet['reason'], print_r($retryQueueRet, true))); + if (CommonTool::isSuccessRet($retryQueueRet)) { + $isMoveToBuffer = true; + } + if (!$isMoveToBuffer && empty($cnaliDsDetailId)) { + $ret = $this->revertMoveCopyCount($shopId, $detailId, 'processCreateProductRet'); + } + + $status = StatusConst::fail; + $publishStat = $addProductRet['code'] == ErrorCodeConst::skip ? 'skip' : 'error'; + $publishLoger->info('do fail clear revertMoveCopyCount: ' . $ret); + } + + if (!$isMoveToBuffer) { + $this->updateMoveCollectTaskDetail(array( + 'status' => $status, + 'reason' => $addProductRet['reason'], + 'parse_cost_seconds' => $parseCostSeconds + ), $shopId, $detailId); + + $this->addAuthPlatformSourceItem($shopId, $queueMsg, $addProductRet, $publishLoger); + + $this->tryAddMoveAuthPlatformProductLog($queueMsg['source'], $queueMsg['auth_shop_id'], $sourceItemId, $detailId, $addProductRet['data']['product_id'], $shopId, $status); + + if (FetchClientTool::isMultiSkuPageSource($queueMsg['source'])) { + $delSkuTempRet = $this->deleteMoveSiblingSkuIdTemp($shopId, $queueMsg['source_item_id']); + $publishLoger->info("deleteMoveSiblingSkuIdTemp delSkuTempRet[" . ZcArrayHelper::sp($delSkuTempRet) . "] shopId[$shopId] sourceItemId[" . $queueMsg['source_item_id'] . "]"); + } + } + + $publishLoger->info("do clear updateMoveCollectTaskDetail ret[{$ret}]"); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + $respResult = CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + $respResult = CommonTool::failResult("清空数据失败,原因:" . $ex->getMessage()); + } + + if (!$isMoveToBuffer) { + $this->processCreateProductRetCommonPart($queueMsg, $status, $addProductRet, $parseCostSeconds, $publishStat, $publishLoger); + + if (($status == StatusConst::success) && $queueMsg['fetch_bank_detail_id']) { + $this->fetchBankClient->addFetchBankDetailMoveLog($shopId, AppConst::isddmsV2() ? FetchBankConst::platformddmsV2 : FetchBankConst::platformDd, $queueMsg['fetch_bank_detail_id'], $queueMsg['source']); + } + } + + return $respResult; + } + + public function deleteShopCategoryBrand($shopId, $productDetailBase, $addProductRet, $log = null) { + if(CommonTool::isSuccessRet($addProductRet)) { + return ; + } + + $standBrandId = $productDetailBase['standardBrandId']; + $reason = $addProductRet['reason']; + $cid = $productDetailBase['categoryLeafId']; + if($standBrandId == MoveConst::noBrandId) { + return; + } + + if (strpos($reason, '请重新选择品牌') !== false || strpos($reason, '该类目下无品牌') !== false || strpos($reason, '品牌不属于该类目') !== false) { + $affRow = $this->db->delete('shop_category_brand', 'shop_id = %i and category_id = %i and brand_id = %i', $shopId, $cid, $standBrandId); + if($log) { + $log->info("deleteShopCategoryBrand shopId=$shopId, cid=$cid,standBrandId = $standBrandId, affRow=$affRow"); + } + } + } + + public function processCreateProductRetCommonPart($queueMsg, $status, $addProductRet, $publishCostSeconds, $publishStat, $publishLoger) { + $sourceItemId = $queueMsg['source_item_id']; + $shopId = $queueMsg['shop_id']; + $priority = $queueMsg['priority']; + $detailId = $queueMsg['move_collect_task_detail_id']; + $cnaliDsDetailId = $queueMsg['cnali_ds_detail_id']; + $moveGroupTaskDetailId = $queueMsg['move_group_task_detail_id']; + + if (CommonTool::isFailRet($addProductRet)) { + if ($addProductRet['code'] == ErrorCodeConst::skip) { + $this->logSkipMoveError($addProductRet['reason'], $shopId, $detailId, $cnaliDsDetailId); + } else { + $this->logLastMoveError($addProductRet['reason'], $shopId, $detailId, $cnaliDsDetailId); + } + } + + if ($this->checkShopIsMoveStopLimit($shopId) && !$this->isShopLimitPublishReason($addProductRet['reason'])) { + $this->resetMoveShopStopLimit($shopId); + } + + $this->processNeedFailUserTasks($addProductRet, $shopId, $queueMsg['cid'], $publishLoger); + + $this->updateMoveShopPublishCount($shopId, $publishStat, $priority, $publishCostSeconds, $queueMsg['source']); + + //更新群控复制状态 + $this->updateMoveGroupPublishStatus($addProductRet, $moveGroupTaskDetailId, $shopId, $publishLoger); + + $this->processDsProduct($shopId, $cnaliDsDetailId, $detailId, $status, $sourceItemId, $addProductRet); + + $this->processLtaoProduct($shopId, $detailId, $status, $sourceItemId, $addProductRet); + + $this->processSkuMinPriceRelation($shopId, $sourceItemId, $addProductRet); + } + + private function processSkuMinPriceRelation($shopId, $sourceItemId, $addProductRet) { + if (CommonTool::isFailRet($addProductRet)) { + return; + } + + if (empty($addProductRet['productDetailBase']['updateSkuMinPriceInfo'])) { + return; + } + + $productId = $addProductRet['data']['product_id']; + $params = array( + 'shopId' => $shopId, + 'productId' => $productId, + 'sourceItemId' => $sourceItemId, + 'moveColorMap' => $addProductRet['productDetailBase']['newColorNameAndOldColorNameMap'], + 'moveSizeMap' => $addProductRet['productDetailBase']['newSizeNameAndOldSizeNameMap'], + 'updateSkuMinPriceInfo' => $addProductRet['productDetailBase']['updateSkuMinPriceInfo'], + ); + $this->addMoveAfterProductAddQueue($productId, $shopId, MoveConst::moveAfterProductProcessAddSkuMinPriceRelation, json_encode($params), date('Y-m-d H:i:s')); + } + + public function insertMoveShopStop($shopId, $reason = null) { + $update['shop_id'] = $shopId; + $update['is_limit_publish'] = 1; + $update['gmt_over_daily_total_start'] = date('Y-m-d H:i:s'); + $update['gmt_modified'] = date('Y-m-d H:i:s'); + $update['gmt_retry_limit_publish'] = date('Y-m-d H:i:s'); + $update['retry_limit_publish_fail_reason'] = $reason; + + $insert = $update; + $insert['gmt_create'] = date('Y-m-d H:i:s'); + $this->db->insertUpdate('move_shop_stop', $insert, $update); + } + + public function getProcessingMoveCollectTaskDetailIds($shopId) { + return $this->db->queryFirstColumn('select move_collect_task_detail_id from move_collect_task_detail where shop_id = %i and status in %ls', $shopId, [StatusConst::processing, StatusConst::wait]); + } + + private function addAuthPlatformSourceItem($shopId, $queueMsg, $addProductRet, ZcLog $publishLogger) { + $productId = $addProductRet['data']['product_id']; + $realSource = RuntimeCacheTool::getRealSource(); + $realSourceItemId = RuntimeCacheTool::getRealSourceItemId(); + $authPlatform = $queueMsg['source']; + $authPlatformItemId = $queueMsg['source_item_id']; + + $publishLogger->info('----start addAuthPlatformSourceItem---'); + $publishLogger->info("shopId : {$shopId}, productId : {$productId}, realSource : {$realSource}, realSourceItemId : {$realSourceItemId}, authPlatform: {$authPlatform}, authPlatformItemId : {$authPlatformItemId}"); + + if (CommonTool::isFailRet($addProductRet)) { + $publishLogger->info('----addAuthPlatformSourceItem---addProduct fail'); + return; + } + + if (CommonTool::anyEmpty($productId, $realSource, $realSourceItemId, $authPlatform, $authPlatformItemId)) { + $publishLogger->info('----addAuthPlatformSourceItem---param error'); + return; + } + + if (!in_array($authPlatform, PlatformAuthConst::getPlatformAuthPlatforms())) { + $publishLogger->info('----addAuthPlatformSourceItem---platform error'); + return; + } + + return $this->db->insert('auth_platform_source_item', array( + 'shop_id' => $shopId, + 'product_id' => $productId, + 'auth_platform' => $authPlatform, + 'auth_platform_item_id' => $authPlatformItemId, + 'real_source' => $realSource, + 'real_source_item_id' => $realSourceItemId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + + protected function processNeedFailUserTasks($failRet, $shopId, $cid, ZcLog $publishLogger) { + $processCount = 0; + if (CommonTool::isSuccessRet($failRet)) { + return $processCount; + } + + $publishLogger->info("processNeedCancelUserTasks publishRet : " . print_r($failRet, true)); + $reason = $failRet['reason']; + if ($this->checkFailRetIsCateRelatedError($reason)) { + $publishLogger->info("processNeedCancelUserTasks IsCateRelatedError"); + $this->addMoveCancelTaskQueue($shopId, $cid, $reason); + } else if ($this->checkFailRetIsShopRelatedError($reason)) { + $publishLogger->info("processNeedCancelUserTasks isShopRelatedError"); + $this->addMoveCancelTaskQueue($shopId, 0, $reason); + } + } + + public function addMoveCancelTaskQueue($shopId, $cid, $reason) { + $isExistQueue = $this->db->queryFirstField('select 1 from move_cancel_task_queue where shop_id = %i and cid = %i limit 1', $shopId, $cid); + if ($isExistQueue) { + return; + } + + $update = array( + 'shop_id' => $shopId, + 'cid' => $cid, + 'reason' => $reason, + 'locked' => 0, + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + return $this->db->insertUpdate('move_cancel_task_queue', $insert, $update); + } + + private function checkFailRetIsCateRelatedError($reason) { + $errorPartCodeList = array( + '读取类目资质信息失败', + '读取类目信息失败', + '此类目已调整升级,请重新选择类目进行商品发布', + '读取类目标失败', + ); + + foreach ($errorPartCodeList as $errorPartCode) { + if (false !== strpos($reason, $errorPartCode)) { + return true; + } + } + return false; + } + + private function checkFailRetIsShopRelatedError($reason) { + $errorPartCodeList = array( + '由于您尚未进行店铺官方账号绑定,店铺部分功能不可用', + '素材库容量不足', + ); + + foreach ($errorPartCodeList as $errorPartCode) { + if (false !== strpos($reason, $errorPartCode)) { + return true; + } + } + return false; + } + + public function delCreateProductV2DataFromOss($moveCollectTaskDetailId) { + $ossPath = sprintf('move/publish/%s/%s.txt', date('Y-m-d'), $moveCollectTaskDetailId); + $exportDataListStrRet = OssTool::getImmutableObjectByContent($ossPath); + OssTool::deleteImmutableObject($exportDataListStrRet); + return CommonTool::successResult(); + } + + public function logSkipMoveError($reason, $shopId, $taskDetailId, $cnaliDsDetailId){ + $errorCode = $reason; + $dt = date('Ymd'); + $update = [ + 'shop_id' => $shopId, + 'error_code' => $errorCode, + 'dt' => $dt, + 'is_ds' => $cnaliDsDetailId ? 1 : 0, + 'gmt_modified' => ZcDbEval::now(), + ]; + + $insert = $update; + $update['count'] = new ZcDbEval('count + 1'); + $insert['count'] = 1; + $insert['gmt_create'] = ZcDbEval::now(); + + $res = $this->db->insertUpdate('move_skip_error_code', $insert, $update); + if ($res == 2) { + $row = $this->db->queryFirstRow('select move_skip_error_code_id from move_skip_error_code where shop_id = %i and error_code = %s and dt = %i ', $shopId, $errorCode, $dt); + $errorCodeId = $row['move_skip_error_code_id']; + } else { + $errorCodeId = $this->db->lastInsertId(); + } + + if (!empty($errorCodeId)) { + $errorDetailInsert = [ + 'move_skip_error_code_id' => $errorCodeId, + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $taskDetailId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->insert('move_skip_error_code_detail', $errorDetailInsert); + } + } + + private function processLtaoProduct($shopId, $detailId, $status, $sourceItemId, $addProductRet) { + if ($status != StatusConst::success) { + return ; + } + + $isLtaoItem = $this->db->queryFirstField('select 1 from move_collect_task_detail_ltao_log where move_collect_task_detail_id = %i', $detailId); + if (empty($isLtaoItem)) { + return ; + } + + $moveColorMap = $addProductRet['productDetailBase']['newColorNameAndOldColorNameMap']; + $moveSizeMap = $addProductRet['productDetailBase']['newSizeNameAndOldSizeNameMap']; + $productId = $addProductRet['data']['product_id']; + $skuRelationList = $this->buildLtaoSkuRelationList($shopId, $productId, $sourceItemId, $moveColorMap, $moveSizeMap); + $ltaoAuthInfo = $this->shopDao->getLtaoAuthInfo($shopId); + + return $this->productDao->setMoveProductManualSource($shopId, $ltaoAuthInfo['ltao_user_id'], $productId, $sourceItemId, $skuRelationList, $addProductRet['sourceSellerId']); + } + + private function buildLtaoSkuRelationList($shopId, $productId, $sourceItemId, $moveColorMap, $moveSizeMap) { + $skuRelationList = []; + + $ltaoAccessToken = $this->shopDao->getLtaoAccessToken($shopId); + $sourceProductData = $this->ltaoTool->getLtaoProductInfoFromLtao($sourceItemId, $ltaoAccessToken, $shopId); + if (empty($sourceProductData) || CommonTool::isFailRet($sourceProductData)) { + return $skuRelationList; + } + $sourceProductInfo = $this->getSourceProductInfoByManualSource($sourceProductData); + $skuIdMap = $sourceProductInfo['skuIdMap']; + $accessToken = $this->shopDao->getShopAccessToken($shopId); + $getProductRet = $this->productDao->getProductFromDd($productId, $accessToken); + if (CommonTool::isFailRet($getProductRet)) { + return []; + } + $productInfo = $getProductRet['product']; + + $moveColorMap = $moveColorMap ? array_flip($moveColorMap) : []; + $moveSizeMap = $moveSizeMap ? array_flip($moveSizeMap) : []; + foreach ($skuIdMap as $skuId => $skuInfo) { + $skuStr = ';' . implode(';', array_values($skuInfo)) . ';'; + $findNewDdSkuIds = $this->findDsNewDdSkuId($skuStr, $productInfo, $moveColorMap, $moveSizeMap); + if ($findNewDdSkuIds) { + foreach ($findNewDdSkuIds as $findNewDdSkuId) { + $skuRelationList[] = array( + 'platformSkuId' => $findNewDdSkuId, + 'sourceSkuId' => $skuId, + 'sourceNum' => 1 + ); + } + } + } + + return $skuRelationList; + } + + private function processDsProduct($shopId, $cnaliDsDetailId, $detailId, $status, $sourceItemId, $addProductRet) { + if (empty($cnaliDsDetailId)) { + return false; + } + + $moveShopStopInfo = $this->getMoveShopStopInfoByShopId($shopId); + $addProductRet['reason'] = HtmlTool::transitionErrReason($addProductRet['reason'], $moveShopStopInfo, $status, 0); + + $productId = $addProductRet['data']['product_id']; + $dsStatus = $status ? : StatusConst::skip; + $ret = $this->dsClient->updateDsMoveCollectTaskDetail($shopId, AppConst::getDsPlatform(), $cnaliDsDetailId, $detailId, array( + 'status' => $dsStatus, + 'reason' => $addProductRet['reason'], + 'platformItemId' => $productId, + 'type' => DsConst::updateDsDetailTypeStatus, + 'sourceSellerId' => $addProductRet['sourceSellerId'], + 'sourceSellerLoginId' => $addProductRet['sourceSellerLoginId'], + )); + if (empty($ret) || CommonTool::isFailRet($ret)) { + $params = array( + 'shopId' => $shopId, + 'cnaliDsDetailId' => $cnaliDsDetailId, + 'detailId' => $detailId, + 'status' => $dsStatus, + 'reason' => $addProductRet['reason'], + 'platformItemId' => $productId, + 'type' => DsConst::updateDsDetailTypeStatus, + 'sourceSellerId' => $addProductRet['sourceSellerId'], + 'sourceSellerLoginId' => $addProductRet['sourceSellerLoginId'], + ); + $this->moveDao->insertDsAsyncNoticeTask($shopId, MoveConst::syncUpdateMoveDetailToDs, $params); + } + + if ($status == StatusConst::success && $productId) { + $insert = [ + 'shop_id' => $shopId, + 'product_id' => $productId, + 'source_item_id' => $sourceItemId, + 'source_seller_id' => $addProductRet['sourceSellerId'], + 'gmt_create' => date('Y-m-d H:i:s'), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]; + $this->db->insert('product_to_ds_item', $insert); + + $params = array( + 'shopId' => $shopId, + 'productId' => $productId, + 'sourceItemId' => $sourceItemId, + 'sourceSellerId' => $addProductRet['sourceSellerId'], + 'moveColorMap' => $addProductRet['productDetailBase']['newColorNameAndOldColorNameMap'], + 'moveSizeMap' => $addProductRet['productDetailBase']['newSizeNameAndOldSizeNameMap'], + ); + $this->moveDao->insertDsAsyncNoticeTask($shopId, MoveConst::moveAfterProductPostAddItemRelationToDdOd, $params); + } + } + + private function checkAndRetryMoveProductPublishQueue($queueMsg, $addProductRet) { + if (CommonTool::isSuccessRet($addProductRet)) { + return CommonTool::failResult('不在重试条件范围(搬家成功)'); + } + + $retryQueueCodeMap = [ + 'spuIdChecking' => 10, + ]; + $retryQueueReasonsMap = [ + '请求太频繁,请稍后重试' => 5, +// '服务内部访问超时,请重试' => 5, + '上传主图有缺失' => 2, + '上传产品详情有缺失' => 2, + '连接服务器出错,请重试~' => 5, + '服务调用太频繁' => 5, + '创建审核任务失败' => 3, + '图片转链失败' => 2, + '提审失败,请重试' => 3, + '请前往店铺后台申请品牌' => 1, + '提审失败' => 3, + '因为店铺受到处罚,限制发品' => 24, + ]; + $maxTryTimes = 2; + $needRetry = false; + foreach ($retryQueueReasonsMap as $reason => $maxTimes) { + if (stripos($addProductRet['reason'], $reason) !== false || $retryQueueCodeMap[$addProductRet['code']]) { + $needRetry = true; + $maxTryTimes = $maxTimes; + break; + } + } + if (!$needRetry) { + return CommonTool::failResult('reason不在重试条件范围'); + } + + $shopId = $queueMsg['shop_id']; + $tryTimes = $queueMsg['try_times'] + 1; + $taskId = $queueMsg['move_collect_task_id']; + $detailId = $queueMsg['move_collect_task_detail_id']; + + if ($tryTimes >= $maxTryTimes) { + return CommonTool::failResult('达到重试限制次数'); + } + + $gmtExec = ''; + if ($addProductRet['code'] == MoveConst::moveFailCodeSpuIdChecking) { + $gmtExec = date('Y-m-d H:i:s', time() + 5 * 60); + } + + $af = $this->moveProductPublishQueueToBuffer($shopId, $detailId, $taskId, $tryTimes, $gmtExec); + return $af ? CommonTool::successResult() : CommonTool::failResult('移buffer失败:' . $this->db->lastSql()); + } + + private function moveProductPublishQueueToBuffer($shopId, $detailId, $taskId, $tryTimes, $gmtExec) { + $priority = $this->getTaskPriority($shopId); + if (empty($gmtExec)) { + $gmtExec = date('Y-m-d H:i:s', time() + mt_rand(1, 10) * $tryTimes * 60); + } + $insertPublishBuffer = [ + 'shop_id' => $shopId, + 'move_collect_task_id' => $taskId, + 'move_collect_task_detail_id' => $detailId, + 'try_times' => $tryTimes, + 'gmt_exec' => $gmtExec, + 'priority' => $priority, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ]; + return $this->db->insert('move_product_publish_buffer', $insertPublishBuffer); + } + + public function insertMoveProductLog($addProductRet, $shopId, $detailId, $title) { + $insertData = array( + 'product_id' => $addProductRet['data']['product_id'], + 'out_product_id' => $addProductRet['data']['out_product_id'], + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $detailId, + 'title' => $title, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + return $this->db->insert('move_product_log', $insertData); + } + + public function revertMoveCopyCount($shopId, $detailId, $funcName = '') { + if (CommonTool::anyEmpty($shopId)) { + return false; + } + $deductMoveShopConfigId = $this->getMoveShopConfigIdByDetailId($shopId, $detailId); + $currentMonthMoveConfig = $this->getAvailableCopyCount($shopId); + $currentMoveShopConfigId = $currentMonthMoveConfig['move_shop_config_id']; + + $detail = $this->getCollectTaskDetail($detailId); + if ($detail['copy_type'] == MoveConst::collectDsCopy) { + $this->logRevertDsCopyMoveCnt($shopId, $detailId, $funcName); + if ($detail['cnali_ds_detail_id']) { + return false; + } + } + +// if (empty($currentMoveShopConfigId)) { +// +// return false; +// } + +// if ($this->deductIsCurrentMonthNum($deductMoveShopConfigId, $currentMoveShopConfigId)) { +// return $this->updateMoveShopConfig($shopId, $currentMoveShopConfigId, array( +// 'fail_total' => new ZcDbEval('fail_total + 1'), +// )); +// } + + if ($this->isUseRechargeNum($shopId, $deductMoveShopConfigId)) { + return $this->updateMoveShopConfig($shopId, $currentMoveShopConfigId, array( + 'pre_paid_fail_total' => new ZcDbEval('pre_paid_fail_total + 1'), + )); + } else { + return $this->updateMoveShopConfig($shopId, $deductMoveShopConfigId, array( + 'fail_total' => new ZcDbEval('fail_total + 1'), + )); + } + } + + private function logRevertDsCopyMoveCnt($shopId, $detailId, $funcName) { + return $this->db->useDbIdOnce('ac')->insert('ds_revert_log', array( + 'shop_id' => $shopId, + 'detail_id' => $detailId, + 'func_name' => $funcName, + 'hostname' => gethostname(), + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + + private function getMoveShopConfigIdByDetailId($shopId, $detailId) { + return $this->db->queryFirstField("SELECT move_shop_config_id FROM move_collect_task_detail WHERE shop_id = %i AND move_collect_task_detail_id = %i", $shopId, $detailId); + } + + private function deductIsCurrentMonthNum($deductMoveMallConfigId, $currentMoveMallConfigId) { + if ($deductMoveMallConfigId == $currentMoveMallConfigId) { + return true; + } + + if (empty($deductMoveMallConfigId)) { + return true; + } + + return false; + } + + private function isUseRechargeNum($shopId, $moveShopConfigId) { + $moveShopConfig = $this->getMoveShopConfigByConfigId($shopId, $moveShopConfigId); + //异常偏向客户 + if (empty($moveShopConfig)) { + return true; + } + + $presentNumSurplus = $this->getPresentNumSurplus($moveShopConfig); + $isUseRechargeNum = ($presentNumSurplus > 0) ? false : true; + + return $isUseRechargeNum; + } + + private function getMoveShopConfigByConfigId($shopId, $configId) { + return $this->db->queryFirstRow("SELECT * FROM move_shop_config WHERE shop_id = %i AND move_shop_config_id = %s", $shopId, $configId); + } + + + private function updateMoveShopPublishCount($shopId, $publishStat, $priority, $publishCostSeconds, $source) { + $this->log = Zc::getLog('move/move_shop_publish_count/update', ZcLog::INFO); + $theDay = date('Ymd'); + $theHour = date('H'); + $theMinute = date('i'); + + $publishCountKey = RedisKeyConst::shopMovePublishCount; + $publishCostTimeCountKey = RedisKeyConst::shopMovePublishCostTimeCount; + + $realSource = RuntimeCacheTool::getRealSource(); + if ($realSource) { + $source = "{$source}({$realSource})"; + } + + $shopPublishCountKey = sprintf('%s_%s_%s_%s_%s_%s_%s', $shopId, $theDay, $theHour, $theMinute, $priority, $source, $publishStat); + + $incRet = $this->solidRedis->hIncrBy($publishCountKey, $shopPublishCountKey, 1); + $incShopPublishRet = $this->solidRedis->hIncrBy($publishCostTimeCountKey, $shopPublishCountKey, $publishCostSeconds); + $this->log->info("$shopPublishCountKey : $incRet $incShopPublishRet"); + + $this->solidRedis->expire($publishCountKey, 86400); + $this->solidRedis->expire($publishCostTimeCountKey, 86400); + } + + public function getMoveShopPublishCountMap() { + $publishCountKey = RedisKeyConst::shopMovePublishCount; + $publishCostTimeCountKey = RedisKeyConst::shopMovePublishCostTimeCount; + + $publishCountMap = $this->solidRedis->hGetAll($publishCountKey); + $publishCostTimeCountMap = $this->solidRedis->hGetAll($publishCostTimeCountKey); + + return array($publishCountMap, $publishCostTimeCountMap); + } + + public function clearMoveShopPublishCount() { + $this->log = Zc::getLog('timer/clear/move_publish_count_redis', ZcLog::INFO); + $this->log->info("start clearMoveShopPublishCount"); + + $currDay = date('Ymd'); + $currHour = date('H'); + $currMinute = date('i'); + list($publishCountMap, $publishCostTimeCountMap) = $this->getMoveShopPublishCountMap(); + + $insertMap = array(); + foreach ($publishCountMap as $currKey => $num) { + list ($shopId, $theDay, $theHour, $theMinute, $priority, $source, $status) = explode('_', $currKey); + if (($currDay == $theDay) && ($currHour == $theHour) && ($currMinute == $theMinute)) { + continue; + } + $this->solidRedis->hDel(RedisKeyConst::shopMovePublishCount, $currKey); + + switch ($status) { + case 'success' : + $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['success_num'] += $num; + $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['total_num'] += $num; + break; + case 'error' : + $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['error_num'] += $num; + $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['total_num'] += $num; + break; + case 'skip' : + $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['skip_num'] += $num; + $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['total_num'] += $num; + break; + } + } + + foreach ($publishCostTimeCountMap as $publishCostTimeCountKey => $second) { + list ($shopId, $theDay, $theHour, $theMinute, $priority, $source, $status) = explode('_', $publishCostTimeCountKey); + if (($currDay == $theDay) && ($currHour == $theHour) && ($currMinute == $theMinute)) { + continue; + } + $this->solidRedis->hDel(RedisKeyConst::shopMovePublishCostTimeCount, $publishCostTimeCountKey); + + $successNum = 0; + $errorNum = 0; + $skipNum = 0; + $totalNum = 0; + switch ($status) { + case 'success' : + $totalNum = $successNum = $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['success_num']; + break; + case 'error' : + $totalNum = $errorNum = $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['error_num']; + break; + case 'skip' : + $totalNum = $skipNum = $insertMap[$theDay][$shopId][$theHour][$theMinute][$priority][$source]['skip_num']; + break; + } + + $this->doInsertUpdateMoveShopPublishCount($shopId, $theDay, $theHour, $theMinute, $priority, $totalNum, $successNum, $errorNum, $skipNum, $second, $source); + } + + $this->log->info("end clearMoveShopPublishCount"); + } + + private function doInsertUpdateMoveShopPublishCount($currShopId, $currDay, $currHour, $currMinute, $currPriority, $totalNum, $successNum, $errorNum, $skipNum, $costSeconds, $source) { + $update = array ( + 'shop_id' => $currShopId, + 'the_day' => $currDay, + 'the_hour' => $currHour, + 'priority' => $currPriority, + 'source' => $source, + 'gmt_modified' => ZcDbEval::now() + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + $insert['total_num'] = $totalNum; + $insert['success_num'] = (int)$successNum; + $insert['error_num'] = (int)$errorNum; + $insert['skip_num'] = (int)$skipNum; + $insert['publish_cost_seconds'] = $costSeconds; + + $update['total_num'] = new ZcDbEval('total_num + %i', $totalNum); + $update['success_num'] = new ZcDbEval('success_num + %i', $successNum); + $update['error_num'] = new ZcDbEval('error_num + %i', $errorNum); + $update['skip_num'] = new ZcDbEval('skip_num + %i', $skipNum); + $update['publish_cost_seconds'] = new ZcDbEval('publish_cost_seconds + %i', $costSeconds); + + $ret = $this->db->insertUpdate('move_shop_publish_count', $insert, $update); + if ($ret) { + $shopPublishCountSuccessKey = sprintf('%s_%s_%s_%s_%s_%s', $currShopId, $currDay, $currHour, $currMinute, $currPriority, $source); + + $this->log->info("clearMoveShopPublishCount shopPublishCountSuccessKey $shopPublishCountSuccessKey successNum $successNum errorNum $errorNum skipNum $skipNum costSeconds $costSeconds insertUpdateSqlRet $ret "); + } else { + $this->log->info('insertUpdate move_shop_publish_count fail'); + } + } + + public function getWaitProcessTaskCount($shopId, $filter) { + $where = []; + if ($filter['isSearchDsHistory']) { + $where[] = $this->db->prepare("and exists (select 1 from move_collect_task_detail_ds_log as mctddl where mctddl.move_collect_task_detail_id = mctd.move_collect_task_detail_id)"); + } + $whereStr = $where ? implode(' ', $where) : ''; + + $processStatus = array(StatusConst::wait, StatusConst::processing); + return $this->db->queryFirstField("select count(*) from `move_collect_task_detail` mctd where `status` in %ls and shop_id = %i %l", $processStatus, $shopId, $whereStr); + } + + public function searchTaskDetail($shopId, $filter, $pageNo, $pageSize){ + list($taskDetailList, $total) = $this->getTaskDetailList($shopId, $filter, $pageNo, $pageSize); + + $taskDetailList = $this->appendMoveProductIdToTaskDetailList($taskDetailList, $filter); + $taskDetailList = $this->appendMoveTaskInfoToTaskDetailList($taskDetailList, $filter); + $taskDetailList = $this->appendVideoMoveInfoToTaskDetailList($taskDetailList, $shopId); + $taskDetailList = $this->appendNoticeToTaskDetailList($taskDetailList); + + return array($taskDetailList, $total); + } + + public function appendProductClueAuditStatusToTaskDetailList($taskDetailList, $shopId, $accessToken) { + $productIds = array_column($taskDetailList, 'product_id'); + if (empty($productIds)) { + return $taskDetailList; + } + + $clueInfoList = $this->db->query('select product_id, clue_id, clue_audit_status, reason from product_clue_log where shop_id = %i and product_id in %li', $shopId, $productIds, ProductStatusConst::clueAuditWail); + $clueInfoMap = array_column($clueInfoList, null, 'product_id'); + $productIdClueIdPair = []; + foreach ($clueInfoList as $clueInfo) { + if (in_array($clueInfo['clue_audit_status'], [ProductStatusConst::clueAuditWail, ProductStatusConst::clueComplaint])) { + $productIdClueIdPair[] = [ + 'clue_id' => $clueInfo['clue_id'], + 'product_id' => $clueInfo['product_id'], + ]; + } + } + + if (!empty($productIdClueIdPair)) { + $ret = $this->productDao->batchGetClueSubmitStatusFromDd(['productidClueidPair' => $productIdClueIdPair], $accessToken); + if (CommonTool::isFailRet($ret)) { + return $taskDetailList; + } + foreach ($ret['data'] as $data) { + $clueInfoMap[$data['product_id']]['clue_audit_status'] = $data['audit_status']; + $clueInfoMap[$data['product_id']]['reason'] = $data['refused_reason']; + } + } + + foreach ($taskDetailList as &$taskDetail) { + $productId = $taskDetail['product_id']; + if ($productId && isset($clueInfoMap[$productId])) { + $auditStatus = $clueInfoMap[$productId]['clue_audit_status']; + $taskDetail['is_clue_product'] = true; + $taskDetail['clue_audit_status_txt'] = ProductStatusConst::getProductClueStatusName($auditStatus); + $taskDetail['clue_audit_status'] = $auditStatus; + $taskDetail['clue_reason'] = $clueInfoMap[$productId]['reason']; + } + } + + return $taskDetailList; + } + + private function appendNoticeToTaskDetailList($taskDetailList) { + if (empty($taskDetailList)) { + return $taskDetailList; + } + $taskDetailIds = array_column($taskDetailList, 'move_collect_task_detail_id'); + + $noticeList = $this->db->query('SELECT * FROM move_collect_task_detail_notice WHERE move_collect_task_detail_id IN %li', $taskDetailIds); + $noticeList = array_column($noticeList, null, 'move_collect_task_detail_id'); + + foreach ($taskDetailList as &$taskDetail) { + $noticeInfo = $noticeList[$taskDetail['move_collect_task_detail_id']]; + $notice = []; + if (isset($noticeInfo)) { + if(!empty($noticeInfo['notice'])) { + $notice[] = ['notice' => $noticeInfo['notice']]; + } + + if(!empty($noticeInfo['publish_tips'])) { + $notice = array_merge(json_decode($noticeInfo['publish_tips'], true), $notice); + } + } + + if(!empty($notice)) { + $taskDetail['notice'] = json_encode($notice); + } + } + + return $taskDetailList; + } + + public function getTaskDetailList($shopId, $filter, $pageNo, $pageSize) { + $where = array(); + if($filter['status']){ + $where[] = $this->db->prepare("and mctd.`status` in %ls", $filter['status']); + } + if($filter['source']){ + $where[] = $this->db->prepare("and mctd.`source` = %s", $filter['source']); + } + + if (!empty($filter['productId'])) { + $productIds = CommonTool::analyzeProductId($filter['productId']); + if ($filter['moveHistorySource'] == MoveConst::moveHistorySourceAc) { + $taskDetailIds = $this->db->useDbIdOnce('ac')->query('select move_collect_task_detail_id from move_product_log where product_id in %li', $productIds); + } else { + $taskDetailIds = $this->db->query('select move_collect_task_detail_id from move_product_log where product_id in %li', $productIds); + } + $taskDetailIds = array_column($taskDetailIds, 'move_collect_task_detail_id'); + $where[] = $this->db->prepare('and mctd.move_collect_task_detail_id in %li', $taskDetailIds); + } + + if (!empty($filter['sourceItemId'])) { + $sourceItemIds = CommonTool::analyzeProductId($filter['sourceItemId']); + $where[] = $this->db->prepare("and mctd.source_item_id in %ls", $sourceItemIds); + } + + if (!empty($filter['sourceTitle'])) { + $where[] = $this->db->prepare("and mctd.`source_title` like %ss", $filter['sourceTitle']); + } + + if (!empty($filter['sourceShopName'])) { + $where[] = $this->db->prepare("and mctd.`source_shop_name` like %ss", $filter['sourceShopName']); + } + + if($filter['taskDetailIds']){ + $taskDetailIds = is_array($filter['taskDetailIds']) ? $filter['taskDetailIds'] : array($filter['taskDetailIds']); + $where[] = $this->db->prepare("and mctd.`move_collect_task_detail_id` in %li", $taskDetailIds); + } + + $where = $this->buildGetTaskDetailListKeywordWhere($where, $filter['keyword']); + + if ($filter['startTime']) { + $where[] = $this->db->prepare("and mctd.`gmt_create` >= %s", $filter['startTime']); + } + + if ($filter['endTime']) { + $where[] = $this->db->prepare("and mctd.`gmt_create` <= %s", $filter['endTime']); + } + + if ($filter['isSearchDsHistory']) { + $where[] = $this->db->prepare("and exists (select 1 from move_collect_task_detail_ds_log as mctddl where mctddl.move_collect_task_detail_id = mctd.move_collect_task_detail_id)", $filter['endTime']); + } + + if($filter['cateIds']) { + $where[] = $this->db->prepare("and mctd.`cid` in %li", $filter['cateIds']); + } + + if ($filter['isSearchLtaoHistory']) { + $where[] = $this->db->prepare("and exists (select 1 from move_collect_task_detail_ltao_log as mctddl where mctddl.move_collect_task_detail_id = mctd.move_collect_task_detail_id)", $filter['endTime']); + } + + $whereString = !empty($where) ? implode(' ', $where) : ''; + $index = 'idx_shop_id_source_item_id_source'; + if (count($where) == 1 && $filter['status'] && ($filter['moveHistorySource'] != MoveConst::moveHistorySourceAc)) { + $index = 'idx_shopid_status'; + } + $sql = $this->db->prepare("select mctd.* from `move_collect_task_detail` mctd USE INDEX(%l) where mctd.`shop_id` = %i %l order by mctd.`move_collect_task_detail_id` desc", $index, $shopId, $whereString); + + if ($filter['moveHistorySource'] == MoveConst::moveHistorySourceAc) { + $sql = $sql . ' LIMIT ' . ($pageNo - 1) * $pageSize . ', ' . $pageSize; + $taskDetailList = $this->db->useDbIdOnce('ac')->query($sql); + $taskDetailList = is_array($taskDetailList) ? $taskDetailList : []; + $total = count($taskDetailList); + } else { + list($taskDetailList, $total) = $this->db->queryPage($sql, $pageNo, $pageSize); + } + + return [array_column($taskDetailList, null, 'move_collect_task_detail_id'), $total]; + } + + private function buildGetTaskDetailListKeywordWhere($where, $keyword) { + $keyword = trim($keyword); + if($keyword){ + if (preg_match('/^[a-zA-Z0-9]+$/i', $keyword)) { + if(preg_match('/^[0-9]+$/i', $keyword)) { + $taskDetailId = $this->db->queryFirstField('select move_collect_task_detail_id from move_product_log where product_id = %i', $keyword); + $where[] = $this->db->prepare('and (mctd.move_collect_task_detail_id = %i or mctd.`source_item_id` = %s)', $taskDetailId, $keyword); + } else { + $where[] = $this->db->prepare("and (mctd.`source_item_id` = %s)", $keyword); + } + } else { + $where[] = $this->db->prepare("and mctd.`source_title` like %ss", $keyword); + } + } + + return $where; + } + + private function appendMoveTaskInfoToTaskDetailList($taskDetailList, $filter) { + if (empty($taskDetailList)) { + return $taskDetailList; + } + $taskDetailIds = array_column($taskDetailList, 'move_collect_task_id'); + + $sql = $this->db->prepare('select move_collect_task_id, `condition`, copy_type from move_collect_task where move_collect_task_id in %li', $taskDetailIds); + $rows = $this->db->query($sql); + $rows = array_column($rows, null, 'move_collect_task_id'); + foreach ($taskDetailList as &$taskDetail) { + $taskDetail['condition'] = $rows[$taskDetail['move_collect_task_id']]['condition']; + $taskDetail['copy_type'] = $rows[$taskDetail['move_collect_task_id']]['copy_type']; + } + return $taskDetailList; + } + + public function appendMoveProductIdToTaskDetailList($taskDetailList, $filter) { + if (empty($taskDetailList)) { + return $taskDetailList; + } + $taskDetailIds = array_column($taskDetailList, 'move_collect_task_detail_id'); + + $sql = $this->db->prepare('select move_collect_task_detail_id, product_id from move_product_log where move_collect_task_detail_id in %li', $taskDetailIds); + if ($filter['moveHistorySource'] == MoveConst::moveHistorySourceAc) { + $rows = $this->db->useDbIdOnce('ac')->query($sql); + } else { + $rows = $this->db->query($sql); + } + foreach ($rows as $row) { + $taskDetailList[$row['move_collect_task_detail_id']]['product_id'] = $row['product_id']; + } + return $taskDetailList; + } + + private function appendVideoMoveInfoToTaskDetailList($taskDetailList, $shopId) { + if (empty($taskDetailList)) { + return $taskDetailList; + } + $taskDetailIds = array_column($taskDetailList, 'move_collect_task_detail_id'); + $sql = $this->db->prepare('select move_collect_task_detail_id, source_video_url, source_cover_url, video_move.status, video_move.reason, video.audit_status, video.audit_reject_desc, video_move.video_move_id, video.video_id from video_move left join video on video_move.video_id = video.video_id where video_move.shop_id = %i and video_move.move_collect_task_detail_id in %li', $shopId, $taskDetailIds); + + $rows = $this->db->query($sql); + + $videoIdList = array_column($rows, 'video_id'); + if (empty($videoIdList)) { + $checkingStatusVideoIdList = $this->db->queryFirstColumn('select video_id from video_check_status_queue where video_id in %li', $videoIdList); + } + + foreach ($rows as $row) { + $taskDetailList[$row['move_collect_task_detail_id']]['source_video_url'] = $row['source_video_url']; + $taskDetailList[$row['move_collect_task_detail_id']]['source_cover_url'] = $row['source_cover_url']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_move_status'] = $row['status']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_move_reason'] = $row['reason']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_audit_status'] = $row['audit_status']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_audit_reject_desc'] = $row['audit_reject_desc']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_move_id'] = $row['video_move_id']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_id'] = $row['video_id']; + $taskDetailList[$row['move_collect_task_detail_id']]['video_is_checking_status'] = in_array($row['video_id'], $checkingStatusVideoIdList); + } + + return $taskDetailList; + } + + public function retryMoveTask($detailId, $shopId, $reason, ZcLog $log) { + $taskDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $detailId); + $needAddCnt = 1; + if (!empty($taskDetailExt['cnali_ds_detail_id'])) { + $needAddCnt = 0; + } + + $checkAndGetConfigIdRet = $this->checkAvailableCopyAndGetMoveConfigId($shopId, $needAddCnt); + if (CommonTool::isFailRet($checkAndGetConfigIdRet)) { + return $checkAndGetConfigIdRet; + } + $moveShopConfigId = $checkAndGetConfigIdRet['moveShopConfigId']; + $moveDetail = $this->getMoveCollectTaskDetail($shopId, $detailId); + if (empty($moveDetail)) { + return CommonTool::failResult('任务不存在'); + } + + if ($moveDetail['gmt_create'] < '2022-07-01') { + return CommonTool::failResult('商品上货历史太久远重试失败,请重新复制链接再次搬家'); + } + + $moveCollectTask = $this->getMoveCollectTask($moveDetail['move_collect_task_id'], $shopId); + $condition = $moveCollectTask['condition']; + if(empty($condition)) { + return CommonTool::failResult('未找到配置信息!无法重试,请使用链接重新搬家!'); + } + + $condition['filterSkipReason'][$detailId] = []; + if($reason) { + $condition['filterSkipReason'][$detailId][] = $reason; + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + + try { + if ($needAddCnt > 0) { + $deductRet = $this->deductMoveCopyCount($shopId, $needAddCnt, $moveShopConfigId); + if (CommonTool::isFailRet($deductRet)) { + throw new Exception('扣除额度失败'); + } + } + + $this->db->delete('move_collect_task_detail_notice', 'move_collect_task_detail_id = %i', $detailId); + $this->db->update('move_collect_task_detail', array( + 'status' => StatusConst::processing, + 'move_shop_config_id' => $moveShopConfigId, + 'gmt_modified' => ZcDbEval::now() + ), 'shop_id = %i AND move_collect_task_detail_id = %i and status in %ls', $shopId, $detailId, array(StatusConst::fail, StatusConst::cancel, StatusConst::delete, StatusConst::skip)); + + $this->db->update('move_collect_task', array( + 'condition' => serialize($condition), + 'gmt_modified' => ZcDbEval::now(), + ), 'move_collect_task_id = %i', $moveDetail['move_collect_task_id']); + + $priority = $this->getTaskPriority($shopId); + $insertPublishBuffer = [ + 'shop_id' => $shopId, + 'move_collect_task_id' => $moveDetail['move_collect_task_id'], + 'move_collect_task_detail_id' => $detailId, + 'try_times' => 0, + 'priority' => $priority, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ]; + $this->db->insert('move_product_publish_buffer', $insertPublishBuffer); + + $log->info("failRetryMoveTask shopId[$shopId] detailId[$detailId] success"); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::successResult(); + } catch (Exception $ex) { + $log->info("failRetryMoveTask shopId[$shopId] detailId[$detailId] err: " . $ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::failResult($ex->getMessage()); + } + + $retrySuccessDetailMap[$cnaliDetailId] = $currTaskDetailId; + } + + private function checkAvailableCopyAndGetMoveConfigId($shopId, $needAddCnt) { + $shopIsExpire = $this->checkShopIsExpire($shopId); + if ($shopIsExpire) { + return CommonTool::failResult("shopId $shopId 店铺已过期,请先续费"); + } + $moveConfig = $this->getAvailableCopyCount($shopId); + $moveShopConfigId = $moveConfig['move_shop_config_id']; + $availableCopy = $moveConfig['available_total']; + if ($needAddCnt > 0 && $needAddCnt > $availableCopy) { + return CommonTool::failResult("搬家额度不足,请先充值"); + } + + return CommonTool::successResult('moveShopConfigId', $moveShopConfigId); + } + + public function retrySuccessTaskDetail($shopId, $taskDetailList, ZcLog $log) { + $retrySuccessDetailMap = array(); + foreach ($taskDetailList as $taskDetail) { + $taskDetailId = $taskDetail['move_collect_task_detail_id']; + $cnaliDetailId = $taskDetail['cnali_ds_detail_id']; + $newDetailId = $this->moveAgainDetailsByDetailId($shopId, $taskDetailId, $cnaliDetailId, $log); + + if ($newDetailId) { + $retrySuccessDetailMap[$cnaliDetailId] = $newDetailId; + } + } + + return $retrySuccessDetailMap; + } + + public function moveAgainDetailsByDetailIds($detailIds, $shopId, ZcLog $log) { + $processCount = 0; + foreach ($detailIds as $detailId) { + $newDetailId = $this->moveAgainDetailsByDetailId($shopId, $detailId, false, $log); + if ($newDetailId) { + $processCount++; + } + } + + return $processCount; + } + + private function checkIsNeedMoveAgainForDsApi($detailId, $cnaliDetailId) { + $detailIdAncCnaliDetailIdMap = $this->getAlibabaProductToDsTaskDetailIdMap([$detailId]); + if ($detailIdAncCnaliDetailIdMap && $detailIdAncCnaliDetailIdMap[$detailId] && empty($cnaliDetailId)) { + return $detailIdAncCnaliDetailIdMap[$detailId]; + } + + return false; + } + + private function moveAgainDetailsForDs($shopId, $memberId, $cnaliDetailId) { + $repeatCopyRet = $this->dsClient->repeatCopy($shopId, $memberId, $cnaliDetailId); + if (CommonTool::isFailRet($repeatCopyRet)) { + return ''; + } + + return $repeatCopyRet['successNum']; + } + + public function moveAgainDetailsByDetailId($shopId, $detailId, $cnaliDetailId, $log) { + $moveDetail = $this->getMoveCollectTaskDetail($shopId, $detailId); + $moveDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $detailId); + if (empty($moveDetail) || empty($moveDetailExt)) { + return false; + } + if ($moveDetail['gmt_create'] < '2022-07-01') { + return false; + } + + $needAddCnt = 1; + if (!empty($cnaliDetailId)) { + $needAddCnt = 0; + } + + $checkAndGetConfigIdRet = $this->checkAvailableCopyAndGetMoveConfigId($shopId, $needAddCnt); + if (CommonTool::isFailRet($checkAndGetConfigIdRet)) { + return false; + } + $moveShopConfigId = $checkAndGetConfigIdRet['moveShopConfigId']; + + if ($platformShopDetailId = $this->checkIsNeedMoveAgainForDsApi($detailId, $cnaliDetailId)) { + $memberId = $this->getAlibabaMemberId($shopId); + if ($memberId) { + return $this->moveAgainDetailsForDs($shopId, $memberId, $platformShopDetailId); + } + } + + $taskDetailData = array( + 'shop_id' => $shopId, + 'auth_shop_id' => $moveDetail['auth_shop_id'], + 'operator_shop_id' => $shopId, + 'move_collect_task_id' => $moveDetail['move_collect_task_id'], + 'is_fast_mode' => $moveDetail['is_fast_mode'] ? 1 : 0, + 'move_shop_config_id' => $moveShopConfigId, + 'source' => $moveDetail['source'], + 'site' => $moveDetail['site'], + 'source_item_id' => $moveDetail['source_item_id'], + 'source_title' => $moveDetail['source_title'], + 'source_img_url' => $moveDetail['source_img_url'], + 'source_shop_name' => $moveDetail['source_shop_name'], + 'cid' => $moveDetail['cid'], + 'status' => StatusConst::processing, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + + if ($cnaliDetailId) { + $moveDetailExt['cnali_ds_detail_id'] = $cnaliDetailId; + } + $taskDetailDataExt = $this->buildInsertTaskDetailExt($shopId, $moveDetailExt); + + $priority = $this->getTaskPriority($shopId); + $insertPublishBuffer = [ + 'shop_id' => $shopId, + 'move_collect_task_id' => $moveDetail['move_collect_task_id'], + 'try_times' => 0, + 'priority' => $priority, + 'limit_source' => $moveDetail['limit_source'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ]; + + $addRet = $this->addMoveTaskDetail($shopId, $taskDetailData, $taskDetailDataExt, $insertPublishBuffer, $moveShopConfigId, $detailId, $cnaliDetailId, $log); + if (CommonTool::isFailRet($addRet)) { + return false; + } + if ($cnaliDetailId) { + $this->insertMoveCollectDetailDsLog($shopId, $addRet['detailId'], $cnaliDetailId); + } + + $copyType = $this->getCopyTypeByMoveCollectTaskId($moveDetail['move_collect_task_id']); + if(($copyType == MoveConst::collectMobileCopy)) { + $this->insertMoveCollectDetailMobileLog($shopId, $addRet['detailId']); + } + + $isLtaoItem = $this->db->queryFirstField('select * from move_collect_task_detail_ltao_log where move_collect_task_detail_id = %i', $detailId); + if (!empty($isLtaoItem)) { + $this->insertMoveCollectDetailLtaoLog($shopId, $addRet['detailId'], $isLtaoItem['ltao_category_id'], $isLtaoItem['is_from_rank']); + } + + return $addRet['detailId']; + } + + public function addMoveTaskDetail($shopId, $taskDetailData, $taskDetailDataExt, $insertPublishBuffer, $moveShopConfigId, $detailId, $cnaliDetailId, ZcLog $log) { + if (CommonTool::anyEmpty($shopId, $taskDetailData, $taskDetailDataExt, $insertPublishBuffer, $moveShopConfigId)) { + return CommonTool::failResult("添加商品时,参数有误"); + } + $taskDetail = $this->getCollectTaskDetail($detailId); + if (in_array($taskDetail['status'], array(StatusConst::wait, StatusConst::process)) || $taskDetail['shop_id'] != $shopId) { + return CommonTool::failResult("重试失败,任务状态错误"); + } + + $needAddCnt = 1; + if (!empty($cnaliDetailId)) { + $needAddCnt = 0; + } + $checkAndGetConfigIdRet = $this->checkAvailableCopyAndGetMoveConfigId($shopId, $needAddCnt); + if (CommonTool::isFailRet($checkAndGetConfigIdRet)) { + return $checkAndGetConfigIdRet; + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + if ($needAddCnt > 0) { + $deductRet = $this->deductMoveCopyCount($shopId, $needAddCnt, $moveShopConfigId); + if (CommonTool::isFailRet($deductRet)) { + throw new Exception('扣除额度失败'); + } + } + + $taskDetailData['move_shop_config_id'] = $moveShopConfigId; + + $this->db->insert('move_collect_task_detail', $taskDetailData); + $detailId = $this->db->lastInsertId(); + $taskDetailDataExt['move_collect_task_detail_id'] = $detailId; + $insertPublishBuffer['move_collect_task_detail_id'] = $detailId; + $this->db->insert('move_collect_task_detail_ext', $taskDetailDataExt); + $this->db->insert('move_product_publish_buffer', $insertPublishBuffer); + + $log->info("addMoveTaskDetail shopId[$shopId] detailId[$detailId}] success"); + if ($taskDetail['condition']['skipCopied']){ + $newCondition = $this->getMoveCollectTaskCondition($taskDetail['move_collect_task_id']); + unset($newCondition['skipCopied']); + + $this->db->update('move_collect_task', array( + 'condition' => serialize($newCondition), + 'gmt_modified' => ZcDbEval::now() + ), 'move_collect_task_id = %i', $taskDetail['move_collect_task_id']); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $log->info("addMoveTaskDetail shopId[$shopId] detailId[$detailId}] error " . $ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("插入数据库失败"); + } + + return CommonTool::successResult('detailId', $detailId); + } + + public function getAllDeleteMoveCollectTaskDetailIds($shopId) { + return $this->db->queryFirstColumn("select move_collect_task_detail_id from move_collect_task_detail WHERE shop_id = %i and `status` = %s", $shopId, StatusConst::cancel); + } + + public function delMoveTaskDetailHistory($shopId, $detailId) { + $taskDetailInfoData = $this->getMoveCollectTaskDetail($shopId, $detailId); + $moveProductLogData = $this->getMoveProductLogByDetailId($shopId, $detailId); + $taskDetailExtData = $this->db->queryFirstRow('SELECT * FROM move_collect_task_detail_ext WHERE move_collect_task_detail_id = %i AND shop_id = %i', $detailId, $shopId); + $taskId = $this->db->queryFirstField('SELECT move_collect_task_id FROM move_collect_task_detail WHERE move_collect_task_detail_id = %i AND shop_id = %i', $detailId, $shopId); + $taskDetailCnt = $this->db->queryFirstField('SELECT count(*) FROM move_collect_task_detail WHERE move_collect_task_id = %i ', $taskId); + + $ret = $this->db->useDbIdOnce('ac')->insert('move_collect_task_detail', $taskDetailInfoData); + $this->db->useDbIdOnce('ac')->insert('move_collect_task_detail_ext', $taskDetailExtData); + $this->db->useDbIdOnce('ac')->insert('move_product_log', $moveProductLogData); + if ($ret === false) { + return false; + } + + $this->db->delete('move_product_log', 'move_collect_task_detail_id = %i', $detailId); + $ret = $this->db->delete('move_collect_task_detail', 'move_collect_task_detail_id = %i', $detailId); + $this->db->delete('move_collect_task_detail_ext', 'move_collect_task_detail_id = %i', $detailId); + $this->db->delete('move_collect_task_detail_notice', 'move_collect_task_detail_id = %i', $detailId); + if ($ret === false) { + return false; + } + + if ($taskDetailCnt == 1) { + $this->delMoveOssData($shopId, $taskId); + } + + if (empty($taskDetailExtData)) { + $taskDetailExtData = $this->getMoveProductAndSkusFromOss($shopId, $detailId); + } + if ($taskDetailExtData['cnali_ds_detail_id'] > 0) { + $ret = $this->dsClient->updateDsMoveCollectTaskDetail($shopId, DsConst::platformDd, $taskDetailExtData['cnali_ds_detail_id'], $detailId, array( + 'status' => StatusConst::delete, + 'type' => DsConst::updateDsDetailTypeStatus, + )); + + if (empty($ret) || CommonTool::isFailRet($ret)) { + $params = array( + 'shopId' => $shopId, + 'cnaliDsDetailId' => $taskDetailExtData['cnali_ds_detail_id'], + 'detailId' => $detailId, + 'status' => StatusConst::delete, + 'type' => DsConst::updateDsDetailTypeStatus, + ); + $this->insertDsAsyncNoticeTask($shopId, MoveConst::syncUpdateMoveDetailToDs, $params); + } + } + + return true; + } + + public function delMoveOssData($shopId, $moveCollectTaskId) { + static $hasClearTaskMap; + if (!$hasClearTaskMap[$moveCollectTaskId]) { + $ossPath = "mct/{$shopId}/{$moveCollectTaskId}_previewCateAttr.txt"; + $exportDataListStrRet = OssTool::getImmutableObjectByContent($ossPath); + OssTool::deleteImmutableObject($exportDataListStrRet); + $hasClearTaskMap[$moveCollectTaskId] = true; + } + } + + public function getMoveProductLogByDetailId($shopId, $detailId) { + return $this->db->queryFirstRow('SELECT * FROM move_product_log WHERE move_collect_task_detail_id = %i and shop_id = %i', $detailId, $shopId); + } + + public function cancelCollectTask($shopId, $taskDetailIds, $status = StatusConst::delete, $reason = '手动取消复制'){ + $status = $status ? $status : StatusConst::delete; + $reason = $reason ? $reason : '手动取消复制任务'; + + $successCancelDetailIds = []; + $skipCancelDetailIds = []; + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + foreach ($taskDetailIds as $detailId){ + $moveDetail = $this->getMoveCollectTaskDetail($shopId, $detailId); + if (!in_array($moveDetail['status'], array(StatusConst::wait, StatusConst::processing))) { + continue; + } + $moveDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $detailId); + if ($this->checkMoveQueueIsProcessing($shopId, $detailId)) { + $skipCancelDetailIds[] = $detailId; + continue; + } + $transStatus = $this->db->startTransaction(); + try { + $delRow = $this->delQueueByDetailId($shopId, $detailId); + $delPicRow = $this->delToPicQueueByDetailId($shopId, $detailId); + $delBufferRow = $this->delBufferByDetailId($shopId, $detailId); + if ($delRow != 1 && $delPicRow != 1 && $delBufferRow != 1) { + continue; + } + + $this->db->update('move_collect_task_detail', array( + 'status' => $status, + 'reason' => $reason, + ), 'shop_id = %i and move_collect_task_detail_id = %i', $shopId, $detailId); + + $detail = $this->getCollectTaskDetail($detailId); + $taskDetailExt = $this->getMoveCollectTaskDetailExt($shopId, $detailId); + if (empty($taskDetailExt['cnali_ds_detail_id'])) { + $this->revertMoveCopyCount($shopId, $detailId, 'cancelCollectTask'); + } + + if ($detail['move_group_task_detail_id'] > 0) { + $this->db->update('move_group_task_detail', array('status' => $status, 'reason' => $reason, 'gmt_modified' => ZcDbEval::now()), 'move_group_task_detail_id = %i', $detail['move_group_task_detail_id'] ); + } + + $this->db->commit($transStatus); + $successCancelDetailIds[] = $detailId; + if ($moveDetailExt['cnali_ds_detail_id'] > 0) { + $ret = $this->dsClient->updateDsMoveCollectTaskDetail($shopId, AppConst::getDsPlatform(), $moveDetailExt['cnali_ds_detail_id'], $detailId, array( + 'status' => StatusConst::cancel, + 'type' => DsConst::updateDsDetailTypeStatus, + 'reason' => $reason, + )); + + if (empty($ret) || CommonTool::isFailRet($ret)) { + $params = array( + 'shopId' => $shopId, + 'cnaliDsDetailId' => $moveDetailExt['cnali_ds_detail_id'], + 'detailId' => $detailId, + 'status' => StatusConst::cancel, + 'type' => DsConst::updateDsDetailTypeStatus, + 'reason' => $reason, + ); + $this->insertDsAsyncNoticeTask($shopId, MoveConst::syncUpdateMoveDetailToDs, $params); + } + } + } catch (Exception $e) { + $this->db->rollback($transStatus); + } + } + $this->db->setErrorMode($oldErrorMode); + + return [$successCancelDetailIds, $skipCancelDetailIds]; + } + + public function checkMoveQueueIsProcessing($shopId, $detailId) { + $processPicQueue = $this->db->queryFirstRow('SELECT move_product_publish_to_pic_queue_id FROM move_product_publish_to_pic_queue WHERE shop_id = %i AND move_collect_task_detail_id = %i AND locked <> 0', $shopId, $detailId); + $processQueue = $this->db->queryFirstRow('SELECT move_product_publish_queue_id FROM move_product_publish_queue WHERE shop_id = %i AND move_collect_task_detail_id = %i AND locked <> 0', $shopId, $detailId); + + return ($processPicQueue || $processQueue); + } + + public function getCollectTaskDetail($collectTaskDetailId) { + $ret = $this->db->queryFirstRow("SELECT ct.move_collect_task_id, ct.name, ct.condition, ct.copy_type, ctd.* + FROM move_collect_task_detail ctd LEFT JOIN move_collect_task ct ON ct.move_collect_task_id = ctd.move_collect_task_id + WHERE ctd.move_collect_task_detail_id = %i %l", $collectTaskDetailId); + if(empty($ret)){ + return array(); + } + $ret['condition'] = unserialize($ret['condition']); + $ret['condition'] = $this->restoreConditionsBigField($ret['condition'], $ret['shop_id']); + + $taskDetailExtInfo = $this->getMoveCollectTaskDetailExt($ret['shop_id'], $collectTaskDetailId); + $ret = $this->rebuildTaskDetailByDetailExtInfo($ret, $taskDetailExtInfo); + return $ret; + } + + private function rebuildTaskDetailByDetailExtInfo($taskDetailInfo, $taskDetailExtInfo) { + foreach ($taskDetailExtInfo as $key => $taskDetailExtValue) { + $taskDetailValue = $taskDetailInfo[$key]; + if (!empty($taskDetailValue)) { + continue; + } + + $taskDetailInfo[$key] = $taskDetailExtValue; + } + + return $taskDetailInfo; + } + + private function delQueueByDetailId($shopId, $detailId) { + $delPicRow = $this->db->delete('move_product_publish_to_pic_queue', 'shop_id = %i AND move_collect_task_detail_id = %i and locked = 0', $shopId, $detailId); + $delRow = $this->db->delete('move_product_publish_queue', 'shop_id = %i AND move_collect_task_detail_id = %i and locked = 0', $shopId, $detailId); + return ($delPicRow == 1 || $delRow == 1) ? 1 : 0; + } + + private function delToPicQueueByDetailId($shopId, $detailId) { + return $this->db->delete('move_product_publish_to_pic_queue', 'shop_id = %i AND move_collect_task_detail_id = %i and locked = 0', $shopId, $detailId); + } + + private function delBufferByDetailId($shopId, $detailId) { + return $this->db->delete('move_product_publish_buffer', 'shop_id = %i AND move_collect_task_detail_id = %i', $shopId, $detailId); + } + + public function delMoveHistoryByStatus($shopId, $status) { + if (CommonTool::anyEmpty($shopId, $status)) { + return 0; + } + $delCount = 0; + $detailIds = $this->getMoveDetailIdsByStatus($shopId, $status); + + foreach ($detailIds as $detailId) { + $isSuccess = $this->delMoveTaskDetailHistory($shopId, $detailId); + if ($isSuccess) { + $delCount++; + } + } + return $delCount; + } + + public function getMoveDetailIdsByStatus($shopId, $status) { + return $this->db->queryFirstColumn("SELECT move_collect_task_detail_id FROM move_collect_task_detail WHERE shop_id = %i AND `status` = %s", $shopId, $status); + } + + public function searchTaskDetailList($filter, $pageNo, $pageSize, $countTotal = true){ + $wheres = []; + if(!empty($filter['source'])){ + $wheres[] = $this->db->prepare("and mctd.source = %s", $filter['source']); + } + if(!empty($filter['status'])){ + $wheres[] = $this->db->prepare("and mctd.status = %s", $filter['status']); + } + if(!empty($filter['startDt'])){ + $wheres[] = $this->db->prepare("and mctd.gmt_create >= %s", $filter['startDt']); + } + if(!empty($filter['endDt'])){ + $wheres[] = $this->db->prepare("and mctd.gmt_create <= %s", $filter['endDt']); + } + if($filter['shopId'] > 0){ + $wheres[] = $this->db->prepare("and mctd.shop_id = %i", $filter['shopId']); + } + if($filter['taskId'] > 0){ + $wheres[] = $this->db->prepare("and mctd.move_collect_task_id = %i", $filter['taskId']); + } + if($filter['sourceItemId'] > 0){ + $wheres[] = $this->db->prepare("and mctd.source_item_id = %s", $filter['sourceItemId']); + } + if($filter['cid'] > 0){ + $wheres[] = $this->db->prepare("and mctd.cid = %i", $filter['cid']); + } + if($filter['productId']) { + $taskDetailId = $this->db->queryFirstField("SELECT move_collect_task_detail_id FROM move_product_log WHERE product_id = %i LIMIT 1", $filter['productId']); + if (!$taskDetailId) { + return $countTotal ? array() : array(array(), 0); + } + + $wheres[] = $this->db->prepare("and mctd.move_collect_task_detail_id = %i", $taskDetailId); + } + + if($filter['shopName']) { + $shopIds = $this->shopDao->getShopIdsByShopName($filter['shopName'], 10); + if (empty($shopIds) || count($shopIds) > 5) { + return $countTotal ? array() : array(array(), 0); + } + $wheres[] = $this->db->prepare("and mctd.shop_id in %li", $shopIds); + } + + if($filter['terminal'] == 'pc') { + $wheres[] = $this->db->prepare("and mct.copy_type not in %ls", [MoveConst::collectDsCopy, MoveConst::collectMobileCopy]); + } elseif($filter['terminal'] == 'mobile') { + $wheres[] = $this->db->prepare("and mct.copy_type = %s", MoveConst::collectMobileCopy); + } elseif($filter['terminal'] == 'ds') { + $wheres[] = $this->db->prepare("and mct.copy_type = %s and mctd.is_fast_mode = 0", MoveConst::collectDsCopy); + } elseif($filter['terminal'] == 'dsMobile') { + $wheres[] = $this->db->prepare("and mct.copy_type = %s and mctd.is_fast_mode = 1", MoveConst::collectDsCopy); + } + + if (is_numeric($filter['checkStatus'])) { + if ($filter['checkStatus'] == ProductStatusConst::checkSuccess) { + $wheres[] = $this->db->prepare('and product.check_status in %li', [$filter['checkStatus'], ProductStatusConst::checkForSale]); + } else { + $wheres[] = $this->db->prepare('and product.check_status = %i', $filter['checkStatus']); + } + } + + if ($filter['dsSearchType']) { + $dsSearchTypeWhere = $this->buildDsSearchTypeWhere($filter['dsSearchType']); + if ($dsSearchTypeWhere) { + $wheres = CommonTool::safeArrayMerge($wheres, $dsSearchTypeWhere); + } + } + + if ($filter['productId']) { + $useIndex = $this->db->prepare("USE INDEX(`%l`)", 'PRIMARY'); + } else if ($filter['shopName'] || $filter['shopId']) { + $useIndex = $this->db->prepare("USE INDEX(`%l`)", 'idx_shop_id_source_item_id_source'); + } else if($filter['startDt']) { + $useIndex = $this->db->prepare("USE INDEX(`%l`)", 'idx_gmt_create'); + } else { + return $countTotal ? array() : array(array(), 0); + } + + if ($filter['fromMobileLink'] != -1) { + if ($filter['fromMobileLink'] == 0) { + $wheres[] = $this->db->prepare('and mctdfml.move_collect_task_detail_id is null'); + } else { + $wheres[] = $this->db->prepare('and mctdfml.move_collect_task_detail_id is not null'); + } + } + + if (isset($filter['useRecommendCid']) && $filter['useRecommendCid'] != -1) { + if ($filter['useRecommendCid'] == 0) { + $wheres[] = $this->db->prepare('and (mctdcl.use_recommend_cid is null or mctdcl.use_recommend_cid <> mctd.cid)'); + } else { + $wheres[] = $this->db->prepare('and mctdcl.use_recommend_cid = mctd.cid'); + } + } + + $sql = "select `mctd`.*, `mil`.`product_id`, `mct`.`copy_type`, `mct`.`condition`, mipq.move_product_publish_queue_id, product.check_status, mctdfml.move_collect_task_detail_id as is_from_mobile_link, mctd.cid = mctdcl.use_recommend_cid as is_use_recommend_cid + from `move_collect_task_detail` as `mctd` %l "; + if ($filter['editRetry']) { + $sql .= " join `move_collect_task_detail_retry` as `mctdr` on (`mctd`.`move_collect_task_detail_id` = `mctdr`.`move_collect_task_detail_id`)"; + } + + if(isset($filter['isFromLtaoRank']) && $filter['isFromLtaoRank'] != -1) { + $sql .= "join `move_collect_task_detail_ltao_log` as ltlog on `mctd`.`move_collect_task_detail_id` = ltlog .`move_collect_task_detail_id`"; + $wheres[] = $this->db->prepare('and ltlog.is_from_rank = %i', $filter['isFromLtaoRank']); + } + + $where = empty($wheres) ? '' : implode(' ', $wheres); + $sql .= " left join `move_collect_task` as `mct` on (`mctd`.`move_collect_task_id` = `mct`.`move_collect_task_id`) + left join `move_product_log` as `mil` on ( `mctd`.`move_collect_task_detail_id` = `mil`.`move_collect_task_detail_id`) + left join `move_product_publish_queue` as `mipq` on (`mctd`.`move_collect_task_detail_id` = `mipq`.`move_collect_task_detail_id`) + left join `move_collect_task_detail_from_mobile_log` as `mctdfml` on (`mctd`.`move_collect_task_detail_id` = `mctdfml`.`move_collect_task_detail_id`) + left join `move_collect_task_detail_category_log` as `mctdcl` on (`mctd`.`move_collect_task_detail_id` = `mctdcl`.`move_collect_task_detail_id`) + left join `product` on (`mil`.`product_id` = `product`.`product_id`) + where 1 %l order by `mctd`.`move_collect_task_detail_id` desc"; + + if ($countTotal) { + list($taskDetailList, $total) = $this->db->queryPage($sql, $useIndex, $where, $pageNo, $pageSize); + } else { + $start = ($pageNo - 1) * $pageSize; + $sql = $sql . ' ' . $this->db->prepare('limit %i, %i', $start, $pageSize); + $taskDetailList = $this->db->query($sql, $useIndex, $where); + $total = count($taskDetailList); + } + if (empty($taskDetailList)) { + return []; + } + + $taskDetailList = $this->shopDao->appendShopShopName($taskDetailList); + + return [$taskDetailList, $total]; + } + + private function buildDsSearchTypeWhere($dsSearchType) { + $dsSearchTypeWhere = []; + switch ($dsSearchType) { + case MoveConst::dsSearchTypeNotDs : + $dsSearchTypeWhere[] = $this->db->prepare(' AND mct.copy_type != %s', MoveConst::collectDsCopy); + break; + case MoveConst::dsSearchTypeDs : + $dsSearchTypeWhere[] = $this->db->prepare(' AND mct.copy_type = %s and mctd.site != "pft"', MoveConst::collectDsCopy); + break; + case MoveConst::dsSearchTypeChosen : + $dsSearchTypeWhere[] = $this->db->prepare(' AND mct.copy_type = %s and mctd.site = "pft"', MoveConst::collectDsCopy); + break; + case MoveConst::dsSearchTypeLTao : + $dsSearchTypeWhere[] = $this->db->prepare(' AND mct.copy_type = %s', MoveConst::collectLtaoCopy); + break; + } + + return $dsSearchTypeWhere; + } + + public function getProductLogByDetailId($detailId){ + $res = $this->db->queryFirstRow("select mil.product_id, mctd.shop_id, mct.condition from move_collect_task_detail mctd + LEFT JOIN move_product_log mil ON mctd.move_collect_task_detail_id = mil.move_collect_task_detail_id + LEFT JOIN move_collect_task mct ON mct.move_collect_task_id = mctd.move_collect_task_id + where mctd.move_collect_task_detail_id = %i ", $detailId); + $res['condition'] = unserialize($res['condition']); + return $res; + } + + public function getMovePublishHourStatistics($filter) { + $whereString = $this->getPublishQueueCountFilter($filter); + $publishList = $this->db->query("SELECT the_day, the_hour, priority, source, sum(total_num) total_num, SUM(success_num) success_num, SUM(error_num) error_num, SUM(skip_num) skip_num, SUM(publish_cost_seconds) as total_publish_cost_seconds FROM move_shop_publish_count WHERE TRUE %l GROUP BY the_day desc, the_hour asc, priority asc, source asc", $whereString); + return $publishList; + } + + private function getPublishQueueCountFilter($filter) { + $where = array(); + if ($filter['shopId'] > 0) { + $where[] = $this->db->prepare('AND shop_id = %i', $filter['shopId']); + } + if(!empty($filter['startDt'])){ + $where[] = $this->db->prepare("AND the_day >= %s", $filter['startDt']); + } + if(!empty($filter['endDt'])){ + $where[] = $this->db->prepare("AND the_day <= %s", $filter['endDt']); + } + if(!empty($filter['startHour'])){ + $where[] = $this->db->prepare("AND the_hour >= %s", $filter['startHour']); + } + if(!empty($filter['endHour'])){ + $where[] = $this->db->prepare("AND the_hour <= %s", $filter['endHour']); + } + if(!empty($filter['startPriority'])){ + $where[] = $this->db->prepare("AND priority >= %s", (int)$filter['startPriority']); + } + if(!empty($filter['endPriority'])){ + $where[] = $this->db->prepare("AND priority <= %s", (int)$filter['endPriority']); + } + $whereString = implode(' ', $where); + return $whereString; + } + + public function getMovePublishQueueStatistics($filter) { + $where = array(); + if ($filter['shopId'] > 0) { + $where[] = $this->db->prepare('AND shop_id = %i', $filter['shopId']); + } + if(!empty($filter['startPriority'])){ + $where[] = $this->db->prepare("AND priority >= %s", (int)$filter['startPriority']); + } + if(!empty($filter['endPriority'])){ + $where[] = $this->db->prepare("AND priority <= %s", (int)$filter['endPriority']); + } + $whereString = implode(' ', $where); + + $queueStatisticList = $this->db->query("SELECT shop_id, priority, count(*) queue_total, max(gmt_create) max_gmt_create, min(gmt_create) min_gmt_create FROM move_product_publish_queue WHERE TRUE %l GROUP BY shop_id, priority", $whereString); + $bufferStatisticList = $this->db->query("SELECT shop_id, priority, count(*) buffer_total FROM move_product_publish_buffer WHERE TRUE %l GROUP BY priority, shop_id", $whereString); + + $queueHasLockStatistic = $this->db->query("SELECT priority, count(*) total, min(gmt_locked) gmt_locked_min, max(gmt_locked) gmt_locked_max FROM move_product_publish_queue WHERE TRUE AND locked > 0 %l GROUP BY priority", $whereString); + $queueNotLockStatistic = $this->db->query("SELECT priority, count(*) total FROM move_product_publish_queue WHERE TRUE AND locked = 0 %l GROUP BY priority", $whereString); + + return array ($queueStatisticList, $bufferStatisticList, $queueHasLockStatistic, $queueNotLockStatistic); + } + + public function getListKeyLenMap($listKeyNameArray) { + $listKeyLenMap = array(); + foreach ($listKeyNameArray as $listKeyName) { + $listKeyLenMap[$listKeyName] = $this->solidRedis->lLen($listKeyName); + } + return $listKeyLenMap; + } + + public function updateMovePublishQueuePriority($shopId, $oriPriority, $priority, $updateNum) { + $ret = $this->db->update('move_product_publish_buffer', array( + 'priority' => $priority + ), 'shop_id = %i AND priority = %i ORDER BY move_product_publish_buffer_id ASC LIMIT %i', $shopId, $oriPriority, $updateNum); + return $ret; + } + + public function getMoveShopConfigListByShopId($shopId) { + return $this->db->query("select * from `move_shop_config` where `shop_id` = %i order by `gmt_expire` asc", $shopId); + } + + public function addAttachTotalToMoveShopConfig($shopId, $moveShopConfigId, $addNum) { + if (CommonTool::anyEmpty($shopId, $moveShopConfigId, $addNum)) { + return CommonTool::failResult("传入参数有误"); + } + + $addNum = (int)$addNum; + if ($addNum > 0) { + $updateData = array( + 'attach_total' => new ZcDbEval('attach_total + ' . $addNum), + ); + } else { + $addNum = abs($addNum); + $updateData = array( + 'attach_total' => new ZcDbEval('attach_total - ' . $addNum), + ); + } + $updateRet = $this->updateMoveShopConfig($shopId, $moveShopConfigId, $updateData); + + if ($updateRet !== false) { + return CommonTool::successResult(); + } + + return CommonTool::failResult("添加数据库失败"); + } + + private function updateMoveShopConfig($shopId, $moveShopConfigId, $updateData) { + $updateData = ZcArrayHelper::filterColumns($updateData, $this->getMoveShopConfigFields()); + if (empty($updateData)) { + return false; + } + + $updateData['gmt_modified'] = ZcDbEval::now(); + return $this->db->update('move_shop_config', $updateData, 'shop_id = %i and move_shop_config_id = %i', $shopId, $moveShopConfigId); + } + + private function getMoveShopConfigFields() { + return array('shop_id', 'total', 'used_total', 'fail_total', 'pre_paid_fail_total', 'attach_total', 'is_balanced', 'gmt_expire', 'fb_total', 'import_total', 'batch_task_product_total', 'export_product_total', 'detect_task_product_use_total', 'detect_task_product_total', 'ykt_video_create_total', 'ykt_video_create_use_total', 'node_video_create_total', 'node_video_create_use_total'); + } + + public function getMoveRewriteCidRules($filter, $pageNo, $pageSize) { + $whereArr[] = '1'; + if (!empty($filter['cid'])) { + $whereArr[] = $this->db->prepare('cat.category_id = %i', $filter['cid']); + } + if (!empty($filter['path'])) { + $whereArr[] = $this->db->prepare('cat.path like %ss', $filter['path']); + } + if (!empty($filter['leftCatName'])) { + $whereArr[] = $this->db->prepare('cat.category_name like %ss', $filter['leftCatName']); + } + if (!empty($filter['leftCatNameLength'])) { + $whereArr[] = $this->db->prepare('char_length(cat.category_name) < %i', $filter['leftCatNameLength']); + } + if ($filter['isRewrite'] == 'rewrite') { + $whereArr[] = $this->db->prepare(' EXISTS (select 1 from move_rewrite_cid_rule where cat.category_id = move_rewrite_cid_rule.cid and move_rewrite_cid_rule.equal_name != "")'); + } + if ($filter['isRewrite'] == 'unRewrite') { + $whereArr[] = $this->db->prepare(' not EXISTS (select 1 from move_rewrite_cid_rule where cat.category_id = move_rewrite_cid_rule.cid and move_rewrite_cid_rule.equal_name != "")'); + } + $whereStr = implode(' AND ', $whereArr); + $sql = $this->db->prepare('SELECT mrcr.equal_name, mrcr.exclude_keywords, cat.* FROM category_v2 as cat left join move_rewrite_cid_rule as mrcr on mrcr.cid = cat.category_id WHERE %l and cat.has_children = 0', $whereStr, $pageNo, $pageSize); + $sql .= ' LIMIT ' . ($pageNo - 1) * $pageSize . ', ' . $pageSize; + $rows = $this->db->query($sql); + return $rows; + } + + public function getGatherMatchCidList($pageNo, $pageSize, $shopIds) { + $where = '1'; + if (!empty($shopIds)) { + $where = $this->db->prepare('shop_id IN %li', $shopIds); + } + $sql = $this->db->prepare('SELECT * FROM gather_match_cid_data WHERE %l order by gather_match_cid_data_id desc', $where, $pageNo, $pageSize); + $sql .= ' LIMIT ' . ($pageNo - 1) * $pageSize . ', ' . $pageSize; + $rows = $this->db->query($sql); + + if (empty($rows)) { + return []; + } + return $rows; + } + + public function saveRewriteCidRule($data) { + $ruleDate = [ + 'cid' => $data['cid'], + 'path' => $data['path'], + 'equal_name' => $data['equal_name'], + 'exclude_keywords' => $data['exclude_keywords'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ]; + + $affRow = $this->db->insert('move_rewrite_cid_rule', $ruleDate); + if ($affRow === 0) { + return CommonTool::failResult("添加到数据库失败"); + } + + $ossPath = OssConst::moveRewriteCidRules; + OssTool::deleteImmutableObject($ossPath); + return CommonTool::successResult('添加成功'); + } + + public function editRewriteCidRule($data) { + $cid = intval($data['cid']); + if (empty($cid)) { + return CommonTool::failResult('规则不存在'); + } + $update = [ + 'cid' => $data['cid'], + 'path' => $data['path'], + 'gmt_modified' => ZcDbEval::now(), + ]; + if ($data['type'] == 'equalName') { + $update['equal_name'] = $data['changeVal']; + } else { + $update['exclude_keywords'] = $data['changeVal']; + } + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + $ret = $this->db->insertUpdate('move_rewrite_cid_rule', $insert, $update); + if ($ret === false) { + return CommonTool::failResult('更新失败'); + } + $ossPath = OssConst::moveRewriteCidRules; + OssTool::deleteImmutableObject($ossPath); + return CommonTool::successResult('更新成功'); + } + + + public function getRewriteCidsByRule($title) { + $matchRewriteCids = array(); + $title = strtolower($title); + $rules = $this->getAllRewriteCidRules(); + foreach ($rules as $cid => $keywordsArr) { + $isSkip = false; + $excludeKeywords = $keywordsArr['exclude_keywords'] ? $keywordsArr['exclude_keywords'] : array(); + $equalNameRule = $keywordsArr['equal_name_rule'] ? $keywordsArr['equal_name_rule'] : array(); + foreach ($excludeKeywords as $excludeKeyword) { + if (strpos($title, $excludeKeyword) !== false) { + $isSkip = true; + break; + } + } + + if ($isSkip) { + continue; + } + + if ($this->compareRewriteCidRules($equalNameRule, $title)) { + $matchRewriteCids[] = $cid; + } + } + + return $matchRewriteCids; + } + + public function getAllRewriteCidRules($flush = false) { + $ossPath = OssConst::moveRewriteCidRules; + $ret = OssTool::getImmutableObjectByContent($ossPath); + $rules = unserialize($ret['body']); + if (!empty($rules) && !$flush) { + return $rules; + } + + $lastRid = 0; + $limitSize = 200; + $rules = []; + while(true) { + $ruleList = $this->db->query('select * from move_rewrite_cid_rule where cid > %i order by cid asc limit %i', $lastRid, $limitSize); + foreach ($ruleList as $rule) { + if (empty($rule['equal_name']) && empty($rule['exclude_keywords'])) { + continue; + } + $cid = $rule['cid']; + $equalName = $rule['equal_name']; + $excludeKeywords = $rule['exclude_keywords']; + $rules[$cid]['exclude_keywords'] = $excludeKeywords ? array_map('strtolower', array_filter(explode(' ', $excludeKeywords))) : array(); + $rules[$cid]['equal_name_rule'] = $this->parseRewriteCidRule($equalName); + } + $lastRid = end($ruleList)['cid']; + if (count($ruleList) < $limitSize) { + break; + } + } + + OssTool::uploadImmutableObjectByContent($ossPath, serialize($rules)); + return $rules; + } + + private function parseRewriteCidRule($rule) { + $rule = trim($rule); + $rule = str_replace(['(', ')'], ['(', ')'], $rule); + if (!preg_match_all('/\|\||&&|[\(\)]|[^\|&\(\)]*/is', $rule, $ruleItemsMatch)) { + return [ + false, + ]; + } + + $ruleItemsMatch[0] = array_filter($ruleItemsMatch[0]); + $ruleItemsMatch[0] = array_map('strtolower', $ruleItemsMatch[0]); + + $hasNext = true; + $andGroup = false; + $andGroupParent = []; + $currentAndGroup = &$andGroup; + + $result = []; + $parent = []; + $current = &$result; + + while ($hasNext) { + $item = current($ruleItemsMatch[0]); + + switch ($item) { + case '(': + $current[] = []; + end($current); + $key = key($current); + $parent[] = &$current; + $current = &$current[$key]; + + $andGroupParent[] = $currentAndGroup; + $currentAndGroup = false; + break; + case ')': + end($parent); + $key = key($parent); + $current = &$parent[$key]; + array_pop($parent); + + if ($currentAndGroup) { + end($parent); + $key = key($parent); + $current = &$parent[$key]; + array_pop($parent); + } + + $currentAndGroup = array_pop($andGroupParent); + break; + case '||': + if ($currentAndGroup) { + end($parent); + $key = key($parent); + $current = &$parent[$key]; + array_pop($parent); + $currentAndGroup = array_pop($andGroupParent); + } + break; + case '&&': + if (!$currentAndGroup && prev($ruleItemsMatch[0])) { + $prevItem = array_pop($current); + + $current[] = []; + end($current); + $key = key($current); + $parent[] = &$current; + $current = &$current[$key]; + $current['relation'] = 'and'; + $current[] = $prevItem; + + $currentAndGroup = true; + + next($ruleItemsMatch[0]); + } + + break; + default: + $current[] = $item; + } + + if (!next($ruleItemsMatch[0])) { + $hasNext = false; + } + } + + return $result; + } + + private function compareRewriteCidRules($rule, $value) { + $relation = 'or'; + if (isset($rule['relation']) && $rule['relation'] === 'and') { + $relation = 'and'; + } + unset($rule['relation']); + + if (empty($rule)) { + return false; + } + + foreach ($rule as $item) { + if (is_array($item)) { + $match = $this->compareRewriteCidRules($item, $value); + } else { + $match = strpos($value, $item); + } + + if ($match === false && $relation === 'and') { + return false; + } + + if ($match !== false && $relation === 'or') { + return true; + } + } + + if ($relation === 'and') { + return true; + } else { + return false; + } + } + + public function searchMoveProductErrorCode($filter) { + $wheres = []; + if (!empty($filter['shopId'])) { + $wheres[] = $this->db->prepare('AND shop_id = %i', $filter['shopId']); + } + $gmtStart = date('Y-m-d 00:00:00'); + $gmtEnd = date('Y-m-d 23:59:59'); + if (!empty($filter['startTime'])) { + $gmtStart = $filter['startTime']; + } + if (!empty($filter['endTime'])) { + $gmtEnd = $filter['endTime']; + } + $where = implode(' ', $wheres); + return $this->db->query('SELECT reason, count(*) AS cnt FROM move_collect_task_detail WHERE status = %s AND gmt_create > %s AND gmt_create < %s %l GROUP BY reason ORDER BY cnt DESC', StatusConst::fail, $gmtStart, $gmtEnd, $where); + } + + public function logMoveError($reason, $shopId, $taskDetailId, $cnaliDsDetailId = 0) { + $errorCode = $reason; + $dt = date('Ymd'); + $update = [ + 'shop_id' => $shopId, + 'error_code' => $errorCode, + 'dt' => $dt, + 'is_ds' => $cnaliDsDetailId ? 1 : 0, + 'gmt_modified' => ZcDbEval::now(), + ]; + + $insert = $update; + $update['count'] = new ZcDbEval('count + 1'); + $insert['count'] = 1; + $insert['gmt_create'] = ZcDbEval::now(); + + $res = $this->db->insertUpdate('move_error_code', $insert, $update); + if ($res == 2) { + $row = $this->db->queryFirstRow('select move_error_code_id from move_error_code where shop_id = %i and error_code = %s and dt = %i ', $shopId, $errorCode, $dt); + $errorCodeId = $row['move_error_code_id']; + } else { + $errorCodeId = $this->db->lastInsertId(); + } + + if (!empty($errorCodeId)) { + $errorDetailInsert = [ + 'move_error_code_id' => $errorCodeId, + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $taskDetailId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->insert('move_error_code_detail', $errorDetailInsert); + } + } + + public function logLastMoveError($reason, $shopId, $taskDetailId, $cnaliDsDetailId) { + $errorCode = $reason; + $dt = date('Ymd'); + $update = [ + 'shop_id' => $shopId, + 'error_code' => $errorCode, + 'dt' => $dt, + 'is_ds' => $cnaliDsDetailId ? 1 : 0, + 'gmt_modified' => ZcDbEval::now(), + ]; + + $insert = $update; + $update['count'] = new ZcDbEval('count + 1'); + $insert['count'] = 1; + $insert['gmt_create'] = ZcDbEval::now(); + + $res = $this->db->insertUpdate('move_last_error_code', $insert, $update); + if ($res == 2) { + $row = $this->db->queryFirstRow('select move_last_error_code_id from move_last_error_code where shop_id = %i and error_code = %s and dt = %i ', $shopId, $errorCode, $dt); + $errorCodeId = $row['move_last_error_code_id']; + } else { + $errorCodeId = $this->db->lastInsertId(); + } + + if (!empty($errorCodeId)) { + $errorDetailInsert = [ + 'move_last_error_code_id' => $errorCodeId, + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $taskDetailId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->insert('move_last_error_code_detail', $errorDetailInsert); + } + } + + public function searchDsMoveErrorList($filter) { + $filter['startTime'] = $filter['startTime'] ? $filter['startTime'] : date('Y-m-d 00:00:00'); + $filter['endTime'] = $filter['endTime'] ? $filter['endTime'] : date('Y-m-d 23:59:59'); + $wheres = []; + $wheres[] = $this->db->prepare('AND s.status = %s', StatusConst::fail); + if (!empty($filter['shopId'])) { + $wheres[] = $this->db->prepare('AND m.shop_id = %i', $filter['shopId']); + } + if (!empty($filter['startTime'])) { + $wheres[] = $this->db->prepare('AND m.gmt_create >= %s', $filter['startTime']); + } + if (!empty($filter['endTime'])) { + $wheres[] = $this->db->prepare('AND m.gmt_create <= %s', $filter['endTime']); + } + + return $this->db->query('select reason, count(*) as cnt from move_collect_task_detail_ds_log as m left join move_collect_task_detail as s on m.move_collect_task_detail_id = s.move_collect_task_detail_id where 1 %l group by reason', implode(' ', $wheres)); + } + + public function searchMoveItemErrorCode($filter) { + $wheres = []; + if (!empty($filter['shopId'])) { + $wheres[] = $this->db->prepare('AND shop_id = %i', $filter['shopId']); + } + if (!empty($filter['isDs'])) { + $wheres[] = $this->db->prepare('AND is_ds = 1'); + } + $dtStart = date('Ymd'); + $dtEnd = date('Ymd'); + if (!empty($filter['startTime'])) { + $dtStart = date('Ymd', strtotime($filter['startTime'])); + } + if (!empty($filter['endTime'])) { + $dtEnd = date('Ymd', strtotime($filter['endTime'])); + } + $where = implode(' ', $wheres); + if ($filter['errorType'] == 'last') { + $tableName = 'move_last_error_code'; + } else if ($filter['errorType'] == 'skip') { + $tableName = 'move_skip_error_code'; + } else { + $tableName = 'move_error_code'; + } + return $this->db->query('SELECT error_code reason, sum(`count`) AS cnt FROM %l WHERE dt >= %s AND dt <= %s %l GROUP BY reason ORDER BY cnt DESC', $tableName, $dtStart, $dtEnd, $where); + } + + public function getMoveErrorCodeDetailList($errorType, $reason, $startDt, $endDt, $pageNo, $pageSize) { + if (empty($reason) || empty($startDt)) { + return []; + } + //后台搜索 + if ($errorType == 'last') { + return $this->db->queryPage('SELECT mctd.move_collect_task_detail_id, mctd.shop_id, mctd.source, mctd.source_item_id, mctd.publish_hostname, mctd.gmt_create FROM move_collect_task_detail mctd JOIN move_last_error_code_detail mecd ON mctd.move_collect_task_detail_id = mecd.move_collect_task_detail_id JOIN move_last_error_code mec ON mec.move_last_error_code_id = mecd.move_last_error_code_id WHERE mec.error_code = %s AND mec.dt >= %s AND mec.dt <= %s', $reason, $startDt, $endDt, $pageNo, $pageSize); + } + if ($errorType == 'skip') { + return $this->db->queryPage('SELECT mctd.move_collect_task_detail_id, mctd.shop_id, mctd.source, mctd.source_item_id, mctd.publish_hostname, mctd.gmt_create FROM move_collect_task_detail mctd JOIN move_skip_error_code_detail mecd ON mctd.move_collect_task_detail_id = mecd.move_collect_task_detail_id JOIN move_skip_error_code mec ON mec.move_skip_error_code_id = mecd.move_skip_error_code_id WHERE mec.error_code = %s AND mec.dt >= %s AND mec.dt <= %s', $reason, $startDt, $endDt, $pageNo, $pageSize); + } + return $this->db->queryPage('SELECT mctd.move_collect_task_detail_id, mctd.shop_id, mctd.source, mctd.source_item_id, mctd.publish_hostname, mctd.gmt_create FROM move_collect_task_detail mctd JOIN move_error_code_detail mecd ON mctd.move_collect_task_detail_id = mecd.move_collect_task_detail_id JOIN move_error_code mec ON mec.move_error_code_id = mecd.move_error_code_id WHERE mec.error_code = %s AND mec.dt >= %s AND mec.dt <= %s', $reason, $startDt, $endDt, $pageNo, $pageSize); + } + + public function getDsMoveErrorCodeDetailList($reason, $startDt, $endDt, $pageNo, $pageSize) { + if (empty($reason) || empty($startDt)) { + return []; + } + + return $this->db->queryPage('SELECT mctd.move_collect_task_detail_id, mctd.shop_id, mctd.source, mctd.source_item_id, mctd.publish_hostname, mctd.gmt_create FROM move_collect_task_detail_ds_log m JOIN move_collect_task_detail mctd ON mctd.move_collect_task_detail_id = m.move_collect_task_detail_id WHERE mctd.reason = %s AND m.gmt_create >= %s AND m.gmt_create <= %s', $reason, $startDt, $endDt, $pageNo, $pageSize); + } + + public function processShopUrlHistory($shopId, $shopUrl, $source, $seller) { + $row = $this->db->queryFirstRow('SELECT * FROM move_shop_url_history WHERE shop_id = %i AND source_shop_url = %s', $shopId, $shopUrl); + if (!empty($row)) { + $ret =$this->db->update('move_shop_url_history', array( + 'gmt_modified' => ZcDbEval::now() + ), 'move_shop_url_history_id = %i', $row['move_shop_url_history_id']); + } else { + $ret = $this->db->insert('move_shop_url_history', array( + 'shop_id' => $shopId, + 'source_shop_url' => $shopUrl, + 'source' => $source, + 'shop_name' => $seller, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + return $ret; + } + + public function processDsShopUrlHistory($shopId, $shopUrl, $source, $seller) { + $row = $this->db->queryFirstRow('SELECT * FROM ds_move_shop_url_history WHERE shop_id = %i AND source_shop_url = %s', $shopId, $shopUrl); + if (!empty($row)) { + $ret =$this->db->update('ds_move_shop_url_history', array( + 'gmt_modified' => ZcDbEval::now() + ), 'ds_move_shop_url_history_id = %i', $row['ds_move_shop_url_history_id']); + } else { + $ret = $this->db->insert('ds_move_shop_url_history', array( + 'shop_id' => $shopId, + 'source_shop_url' => $shopUrl, + 'source' => $source, + 'shop_name' => $seller, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + return $ret; + } + + public function getShopUuidCode($shopId) { + return $this->shopDao->getShopUuidCode($shopId); + } + + public function getAuthShopList($shopId, $skipExpire = false){ + $ddAuthShopList = $this->getDdAuthShopList($shopId, $skipExpire); + $platformAuthShopList = $this->getPlatformAuthShopList($shopId, $skipExpire); + return CommonTool::safeArrayMerge($ddAuthShopList, $platformAuthShopList); + } + + private function getPlatformAuthShopList($shopId, $skipExpire) { + $moveAuthShopList = $this->db->query("select * from `move_auth_shop` where `shop_id` = %i and platform != %s", $shopId, FetchClientConst::collectTaskSourceAuthDd); + if (empty($moveAuthShopList)) { + return []; + } + + $platformAuthShopList = []; + foreach ($moveAuthShopList as $authInfo) { + $isExpire = $authInfo['gmt_expire'] < date('Y-m-d H:i:s') ? 1 : 0; + if ($skipExpire && $isExpire) { + continue; + } + + $shopInfo = array( + 'platformName' => PlatformAuthConst::getPlatformAuthName($authInfo['platform']), + 'shop_id' => $authInfo['auth_shop_id'], + 'nick_name' => $authInfo['auth_shop_name'], + 'is_expire' => $isExpire, + 'expire_date' => $authInfo['gmt_expire'], + 'platform' => $authInfo['platform'], + 'isDelete' => $authInfo['is_delete'] + ); + $platformAuthShopList[] = $shopInfo; + } + + return $platformAuthShopList; + } + + public function getDdAuthShopList($shopId, $skipExpire = false) { + $moveAuthShopList = $this->db->query("select * from `move_auth_shop` where `shop_id` = %i and platform = %s", $shopId, FetchClientConst::collectTaskSourceAuthDd); + $moveAuthShopList = ZcArrayHelper::changeKeyRow($moveAuthShopList, 'auth_shop_id'); + $authShopIds = array_keys($moveAuthShopList); + array_unshift($authShopIds, $shopId); + + $authShopApps = $this->shopDao->getShopsApp($authShopIds); + $authShopApps = $this->shopDao->rebuildShopServiceExpireDate($authShopApps); + $authShopApps = ZcArrayHelper::changeKeyRow($authShopApps, 'shop_id'); + $ddAuthShopList = array(); + $shopApp = $authShopApps[$shopId]; + $ddAuthShopList[] = array( + 'platformName' => PlatformAuthConst::getPlatformAuthName(FetchClientConst::collectTaskSourceAuthDd), + 'shop_id' => $shopId, + 'nick_name' => $shopApp['shop_name'], + 'is_expire' => $shopApp['is_expire'], + 'expire_date' => $shopApp['service_end_date'] ? : $shopApp['expire_date'], + 'platform' => FetchClientConst::collectTaskSourceAuthDd + ); + + foreach ($moveAuthShopList as $authShopId => $authShopInfo) { + $shopApp = $authShopApps[$authShopId]; + + if ($skipExpire && $shopApp['is_expire']) { + continue; + } + + $shopInfo = array( + 'platformName' => PlatformAuthConst::getPlatformAuthName($authShopInfo['platform']), + 'shop_id' => $authShopId, + 'nick_name' => $shopApp['shop_name'], + 'is_expire' => $shopApp['is_expire'], + 'expire_date' => $shopApp['service_end_date'] ? : $shopApp['expire_date'], + 'platform' => $authShopInfo['platform'] + ); + $ddAuthShopList[] = $shopInfo; + } + + return $ddAuthShopList; + } + + public function addAuthShop($shopId, $uuidCode) { + $uuidRow = $this->db->queryFirstRow("select * from `shop_app_uuid` where `uuid_code` = %s", $uuidCode); + if(empty($uuidRow)){ + return false; + } + + $authShopId = $uuidRow['shop_id']; + $authShop = $this->shopDao->getShop($authShopId); + + if($authShop['gmt_expire'] < ZcDateHelper::now()){ + return false; + } + + if($authShopId == $shopId){ + return false; + } + + $authShopIds = $this->db->queryFirstColumn("select auth_shop_id from `move_auth_shop` where `shop_id` = %i", $shopId); + $authShopIds[] = $shopId; + if(!empty($authShopIds) && in_array($authShopId, $authShopIds)){ + return true; + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->db->insert('move_auth_shop', array ( + 'shop_id' => $shopId, + 'auth_shop_id' => $authShopId, + 'initiator' => 1, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + )); + $this->db->insert('move_auth_shop', array ( + 'shop_id' => $authShopId, + 'auth_shop_id' => $shopId, + 'initiator' => 0, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + )); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return true; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function deleteAuthShop($shopId, $authShopId, $platform) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->db->delete('move_auth_shop', 'shop_id = %i AND auth_shop_id = %i', $shopId, $authShopId); + $this->db->delete('move_auth_shop', 'shop_id = %i AND auth_shop_id = %i', $authShopId, $shopId); + if ($platform != FetchClientConst::collectTaskSourceAuthDd) { + $this->db->delete('platform_shop', 'platform = %s AND platform_user_id = %s', $platform, $authShopId); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return true; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function searchShopUrlHistory($shopId, $pageNo, $pageSize) { + $rows = $this->db->queryPage("select * FROM move_shop_url_history WHERE shop_id = %i ORDER BY gmt_modified DESC", $shopId, $pageNo, $pageSize); + return $rows; + } + + public function searchDsShopUrlHistory($shopId, $pageNo, $pageSize) { + return $this->db->queryPage("select * FROM ds_move_shop_url_history WHERE shop_id = %i ORDER BY gmt_modified DESC", $shopId, $pageNo, $pageSize); + } + + public function deleteShopUrlHistory($shopId, $moveShopUrlHistoryId) { + $ret = $this->db->delete('move_shop_url_history', 'move_shop_url_history_id = %i AND shop_id = %i', $moveShopUrlHistoryId, $shopId); + return $ret ? true : false; + } + + public function deleteDsShopUrlHistory($shopId, $moveShopUrlHistoryId) { + $ret = $this->db->delete('ds_move_shop_url_history', 'ds_move_shop_url_history_id = %i AND shop_id = %i', $moveShopUrlHistoryId, $shopId); + return $ret ? true : false; + } + + public function addSpecToDd($spec, $specName, $accessToken) { + return $this->moveDao->addSpecToDd($spec, $specName, $accessToken); + } + + public function getCategoryAttrFromDd($cid, $accessToken) { + return $this->productDao->getCategoryAttrFromDd($cid, $accessToken); + } + + public function getCategoryAttrV2FromDd($cid, $accessToken, $useCache = true) { + return $this->productDao->getCategoryAttrV2FromDd($cid, $accessToken, $useCache); + } + + public function postSkuDataToDd($addSkuData, $accessToken) { + return $this->moveDao->postSkuDataToDd($addSkuData, $accessToken); + } + + public function getBrandListV2FromDd($filter, $accessToken) { + return $this->productDao->getBrandListV2FromDd($filter, $accessToken); + } + + public function getSugBrandFromDd($filter, $accessToken) { + return $this->productDao->getSugBrandFromDd($filter, $accessToken); + } + + public function getBrandSearchOptionArr($shopId) { + $shopBrandList = $this->getBrandListByShopId($shopId); + $brandOptionArray = []; + $brandOptionArray[] = [ + 'brand_id' => '', + 'brand_name' => '请选择', + ]; + foreach ($shopBrandList as $shopBrand) { + $brandOptionArray[] = [ + 'brand_id' => $shopBrand['brand_id'], + 'brand_name' => $shopBrand['brand_name'], + ]; + } + + return $brandOptionArray; + } + + public function processTimeoutMovePublishQueueUnlock() { + $timeoutMinute = 30; + $lockTimeout = date("Y-m-d H:i:s", time() - ($timeoutMinute * 60)); + $this->unlockLog->info("start processTimeoutQueueUnlock, lockTimeout: " . $lockTimeout); + + $queueList = $this->db->query("SELECT q.priority, q.try_times, q.move_product_publish_queue_id, q.shop_id, q.move_collect_task_detail_id,q.gmt_locked,q.gmt_create,mctd.parse_hostname,mctd.publish_hostname,mctd.source,mctd.source_item_id FROM move_product_publish_queue q left join move_collect_task_detail mctd on q.move_collect_task_detail_id = mctd.move_collect_task_detail_id WHERE locked > 0 AND gmt_locked < %s", $lockTimeout); + $this->unlockLog->info("processTimeoutQueueUnlock find timeout queue count: " . count($queueList)); + foreach ($queueList as $queue) { + $this->unlockLog->info(ZcArrayHelper::sp($queue)); + + if ($queue['try_times'] > 3) { + $publishCostSeconds = '180'; + $this->db->delete('move_product_publish_queue', 'move_product_publish_queue_id = %i', $queue['move_product_publish_queue_id']); + $ret = $this->updateMoveCollectTaskDetail(array( + 'status' => StatusConst::fail, + 'reason' => '重试3次依旧失败,自动关闭此任务', + 'publish_cost_seconds' => $publishCostSeconds + ), $queue['shop_id'], $queue['move_collect_task_detail_id']); + + $this->updateMoveShopPublishCount($queue['shop_id'], 'error', $queue['priority'], $publishCostSeconds); + continue; + } + + $shopId = trim($queue['shop_id']); + $queueId = $queue['move_product_publish_queue_id']; + $moveCollectTaskDetailId = $queue['move_collect_task_detail_id']; + + $this->unlockPublicQueue($queueId, $shopId); + $this->addPublishQueueToRedis($shopId, $queue['priority'], $moveCollectTaskDetailId); + $this->unlockLog->info("moveCollectTaskDetailId $moveCollectTaskDetailId addPublishQueueToRedis"); + } + $this->unlockLog->info("end processTimeoutQueueUnlock"); + } + + public function processTimeoutMovePublishToPicQueueUnlock() { + $timeoutMinute = 30; + $lockTimeout = date("Y-m-d H:i:s", time() - ($timeoutMinute * 60)); + $this->unlockLog->info("start processTimeoutQueueUnlock, lockTimeout: " . $lockTimeout); + + $queueList = $this->db->query("SELECT q.try_times, q.move_product_publish_to_pic_queue_id, q.shop_id, q.move_collect_task_detail_id,q.gmt_locked,q.gmt_create,mctd.parse_hostname,mctd.publish_hostname,mctd.source,mctd.source_item_id FROM move_product_publish_to_pic_queue q left join move_collect_task_detail mctd on q.move_collect_task_detail_id = mctd.move_collect_task_detail_id WHERE locked > 0 AND gmt_locked < %s", $lockTimeout); + $this->unlockLog->info("processTimeoutQueueUnlock find timeout queue count: " . count($queueList)); + foreach ($queueList as $queue) { + $this->unlockLog->info(ZcArrayHelper::sp($queue)); + + if ($queue['try_times'] > 3) { + $publishCostSeconds = '180'; + $this->db->delete('move_product_publish_to_pic_queue', 'move_product_publish_to_pic_queue_id = %i', $queue['move_product_publish_to_pic_queue_id']); + $ret = $this->updateMoveCollectTaskDetail(array( + 'status' => StatusConst::fail, + 'reason' => '重试3次依旧失败,自动关闭此任务', + 'publish_cost_seconds' => $publishCostSeconds + ), $queue['shop_id'], $queue['move_collect_task_detail_id']); + + $this->updateMoveShopPublishCount($queue['shop_id'], 'error', $queue['priority'], $publishCostSeconds); + continue; + } + + $shopId = trim($queue['shop_id']); + $queueId = $queue['move_product_publish_to_pic_queue_id']; + $moveCollectTaskDetailId = $queue['move_collect_task_detail_id']; + + $this->db->exec("UPDATE move_product_publish_to_pic_queue SET locked = 0, try_times = try_times + 1, gmt_modified = NOW() + WHERE move_product_publish_to_pic_queue_id = %i AND shop_id = %i", $queueId, $shopId); + + $this->addPublishToPicQueueToRedis($shopId, $queueId); + + $this->unlockLog->info("moveCollectTaskDetailId $moveCollectTaskDetailId addPublishQueueToRedis"); + } + $this->unlockLog->info("end processTimeoutQueueUnlock"); + } + + public function addPublishToPicQueueToRedis($shopId, $queueId) { + if (in_array($shopId, CommonTool::adminSelfShopIds())) { + $moveProductPublishToPicQueueName = RedisKeyConst::moveProductPublishToPicQueueSelf; + } else { + $moveProductPublishToPicQueueName = RedisKeyConst::moveProductPublishToPicQueue; + } + + return $this->solidRedis->lPush($moveProductPublishToPicQueueName, $queueId); + } + + private function unlockPublicQueue($queueId, $shopId) { + if (empty($queueId) || empty($shopId)) { + return ; + } + + $ret = $this->db->exec("UPDATE move_product_publish_queue SET locked = 0, try_times = try_times + 1, gmt_modified = NOW() + WHERE move_product_publish_queue_id = %i AND shop_id = %i", $queueId, $shopId); + + $this->unlockLog->info("unlockPublicQueue queueId[{$queueId}] shopId[{$shopId}] ret[$ret]"); + if ($ret === false) { + $ex = $this->db->lastException(); + if ($ex instanceof Exception) { + $this->unlockLog->info("unlockPublicQueue queueId[{$queueId}] shopId[{$shopId}] " . $ex->getMessage()); + } + } + return $ret; + } + + public function getMoveCollectTaskDetailByProductIds($productIds) { + if (empty($productIds)) { + return array(); + } + return $this->db->query("select mctd.*, mpl.product_id from move_collect_task_detail mctd inner join move_product_log mpl on mctd.move_collect_task_detail_id = mpl.move_collect_task_detail_id where mpl.product_id in %li", $productIds); + } + + public function getMoveShopStopInfo($shopId) { + return $this->db->queryFirstRow('select * from move_shop_stop where shop_id = %i', $shopId); + } + + public function checkShopIsMoveStopLimit($shopId) { + return !empty($this->db->queryFirstRow('select shop_id from move_shop_stop where shop_id = %i and is_limit_publish = 1', $shopId)); + } + + public function changeContinueMoveStatus($shopId, $isContinueMove) { + return $this->db->update('move_shop_stop', [ + 'gmt_modified' => date('Y-m-d H:i:s'), + 'is_continue_move' => $isContinueMove + ], 'shop_id = %i', $shopId); + } + + public function resetMoveShopStop() { + $this->db->update('move_shop_stop', [ + 'is_over_daily_total' => 0, + 'is_limit_publish' => 0, + 'gmt_modified' => date('Y-m-d H:i:s'), + ], 'gmt_over_daily_total_start < %s', date('Y-m-d 23:59:59', strtotime("-1 day"))); + } + + public function resetMoveShopStopLimit($shopId) { + $this->db->update('move_shop_stop', [ + 'is_limit_publish' => 0, + 'gmt_modified' => date('Y-m-d H:i:s'), + ], 'shop_id = %i', $shopId); + } + + public function getCanRetryStopMoveShopIds() { + return $this->db->queryFirstColumn('select shop_id from move_shop_stop where is_limit_publish = 1 and (gmt_retry_limit_publish < %s or gmt_retry_limit_publish is null)', date('Y-m-d H:i:s', strtotime('-1 hour'))); + } + + public function batchUpdateRetryLimitPublish($shopIds) { + if (!empty($shopIds)) { + $this->db->update('move_shop_stop', [ + 'gmt_retry_limit_publish' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ], 'shop_id in %li', $shopIds); + } + } + + public function replaceShopConditionsBigFieldByShopCondition($shopConditions, $shopMoveConditionMap) { + + foreach ($shopConditions as $shopId => &$condition) { + if (!empty($condition['desc']['descPrefix'])) { + $condition['desc']['descPrefixId'] = $shopMoveConditionMap[$shopId]['desc_prefix_id']; + unset($condition['desc']['descPrefix']); + } + if (!empty($condition['desc']['descSuffix'])) { + $condition['desc']['descSuffixId'] = $shopMoveConditionMap[$shopId]['desc_suffix_id']; + unset($condition['desc']['descSuffix']); + } + if (!empty($condition['desc']['descPrefixImg'])) { + $condition['desc']['descPrefixImgId'] = $shopMoveConditionMap[$shopId]['desc_prefix_img_id']; + unset($condition['desc']['descPrefixImg']); + } + if (!empty($condition['desc']['descSuffixImg'])) { + $condition['desc']['descSuffixImgId'] = $shopMoveConditionMap[$shopId]['desc_suffix_img_id']; + unset($condition['desc']['descSuffixImg']); + } + if (!empty($condition['desc']['descSearch'])) { + $condition['desc']['descSearchId'] = $shopMoveConditionMap[$shopId]['desc_search_id']; + unset($condition['desc']['descSearch']); + } + if (!empty($condition['desc']['descReplace'])) { + $condition['desc']['descReplaceId'] = $shopMoveConditionMap[$shopId]['desc_replace_id']; + unset($condition['desc']['descReplace']); + } + if (!empty($condition['title']['titleDelete'])) { + $condition['title']['titleDeleteId'] = $shopMoveConditionMap[$shopId]['title_delete_id']; + unset($condition['title']['titleDelete']); + } + if (!empty($condition['skipTitleKeyword'])) { + $condition['skipTitleKeywordId'] = $shopMoveConditionMap[$shopId]['skip_title_keyword_id']; + unset($condition['skipTitleKeyword']); + } + if (!empty($condition['skipBrandKeyword'])) { + $condition['skipBrandKeywordId'] = $shopMoveConditionMap[$shopId]['skip_brand_keyword_id']; + unset($condition['skipBrandKeyword']); + } + + if (!empty($condition['skipSkuAliasKeyword'])) { + $condition['skipSkuAliasKeywordId'] = $shopMoveConditionMap[$shopId]['skip_sku_alias_keyword_id']; + unset($condition['skipSkuAliasKeyword']); + } + if (!empty($condition['skipShopName'])) { + $condition['skipShopNameId'] = $shopMoveConditionMap[$shopId]['skip_shop_name_id']; + unset($condition['skipShopName']); + } + } + + return $shopConditions; + } + + public function appendMoveInfoToProductList($productList) { + if (empty($productList)) { + return $productList; + } + $productList = array_column($productList, null, 'product_id'); + + $productIds = array_column($productList, 'product_id'); + $productManualSourceInfos = $this->db->query('SELECT `product_id`, `site`, `source`, `source_item_id`, `move_collect_task_detail_id` FROM `move_product_manual_source` WHERE `product_id` IN %li AND `is_major` = 1', $productIds); + $findManualSourceProductIds = array(); + foreach ($productManualSourceInfos as $productManualSourceInfo) { + $productId = $productManualSourceInfo['product_id']; + $productList[$productId]['site'] = $productManualSourceInfo['site']; + $productList[$productId]['source'] = $productManualSourceInfo['source']; + $productList[$productId]['source_item_id'] = $productManualSourceInfo['source_item_id']; + $productList[$productId]['move_collect_task_detail_id'] = $productManualSourceInfo['move_collect_task_detail_id']; + + $findManualSourceProductIds[] = $productId; + } + $notFindManualSourceProductIds = array_diff($productIds, $findManualSourceProductIds); + if (empty($notFindManualSourceProductIds)) { + return $productList; + } + + $moveDetailList = $this->db->query('SELECT mil.product_id, mctd.site, mctd.source, mctd.source_item_id, mctd.move_collect_task_detail_id, mctd.source_shop_name FROM move_product_log AS mil + LEFT JOIN move_collect_task_detail AS mctd USING(move_collect_task_detail_id) + WHERE product_id IN %li', $notFindManualSourceProductIds); + + foreach ($moveDetailList as $moveDetail) { + $productId = $moveDetail['product_id']; + $productList[$productId]['site'] = $moveDetail['site']; + $productList[$productId]['source'] = $moveDetail['source']; + $productList[$productId]['source_item_id'] = $moveDetail['source_item_id']; + $productList[$productId]['move_collect_task_detail_id'] = $moveDetail['move_collect_task_detail_id']; + $productList[$productId]['source_shop_name'] = $moveDetail['source_shop_name']; + } + return $productList; + } + + public function getMoveHistory($productId, $shopId) { + return $this->db->queryFirstRow('SELECT mctd.cid, mctd.source, mctd.source_item_id, mctd.source_shop_name, mctd.gmt_create, mctd.site FROM move_product_log AS mil LEFT JOIN move_collect_task_detail AS mctd ON mil.move_collect_task_detail_id = mctd.move_collect_task_detail_id WHERE mil.product_id = %i AND mil.shop_id = %i', $productId, $shopId); + } + + public function getProductManualSourceListByProductId($productId, $shopId) { + return $this->db->query('SELECT * FROM `move_product_manual_source` WHERE `product_id` = %i AND `shop_id` = %i ORDER BY `move_product_manual_source_id` DESC', $productId, $shopId); + } + + public function getProductManualSourceList($productIds) { + return $this->db->query('SELECT * FROM `move_product_manual_source` WHERE `product_id` in %li and is_major = 1 ', $productIds); + } + + public function getProductMoveCollectTaskDetailId($productId, $shopId) { + return $this->db->queryFirstField('SELECT `move_collect_task_detail_id` FROM `move_product_log` WHERE `product_id` = %i AND `shop_id` = %i', $productId, $shopId); + } + + public function addMoveProductManualSource($shopId, $productId, $moveCollectTaskDetailId, $source, $sourceItemId, $site = '', $isMajor = true) { + if (CommonTool::anyEmpty($shopId, $productId, $source, $sourceItemId)) { + return CommonTool::failResult('参数错误'); + } + $isMajor = $isMajor ? 1 : 0; + + $manualSourceInfo = [ + 'shop_id' => $shopId, + 'product_id' => $productId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'source' => $source, + 'source_item_id' => $sourceItemId, + 'site' => $site, + 'is_major' => $isMajor, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + if ($isMajor) { + $this->moveProductManualSourceDao->cancelProductManualSourceMajorByProductIds($productId, $shopId); + } + $this->insertUpdateMoveProductManualSource($manualSourceInfo); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + + } catch (Exception $ex) { + + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult('数据库写入失败'); + } + } + + public function insertUpdateMoveProductManualSource($insertManualSourceInfo) { + $insertManualSourceInfo['site'] = !empty($insertManualSourceInfo['site']) ? $insertManualSourceInfo['site'] : ''; // null 值无法建立索引 + $update = $insertManualSourceInfo; + unset($update['gmt_create']); + return $this->db->insertUpdate('move_product_manual_source', $insertManualSourceInfo, $update); + } + + public function deleteMoveProductManualSourceById($shopId, $moveProductManualSourceId) { + return $this->moveProductManualSourceDao->deleteMoveProductManualSourceById($shopId, $moveProductManualSourceId); + } + + public function buildProductAvailableManualSourceInfo($taskDetailList, $shopId) { + $productIds = array_column($taskDetailList, 'product_id'); + if (empty($productIds)) { + return $taskDetailList; + } + + $productManualSourceInfos = $this->db->query('SELECT * FROM `move_product_manual_source` WHERE `shop_id` = %i AND `product_id` IN %li AND `is_major` = 1', $shopId, $productIds); + $productManualSourceInfos = ZcArrayHelper::changeKeyRow($productManualSourceInfos, 'product_id'); + if (!empty($productManualSourceInfos)) { + foreach ($taskDetailList as &$taskDetail) { + $productId = $taskDetail['product_id']; + if (empty($productId) || empty($productManualSourceInfos[$productId])) { + continue; + } + $taskDetail['manual_source_info'] = $productManualSourceInfos[$productId]; + } + } + return $taskDetailList; + } + + public function setMoveProductManualSourceAsMajor($moveProductManualSourceId, $productId, $shopId) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + + try { + $this->moveProductManualSourceDao->cancelProductManualSourceMajorByProductIds($productId, $shopId); + $affRows = $this->moveProductManualSourceDao->updateProductManualSourceById([ + 'is_major' => 1, + ], $moveProductManualSourceId, $productId, $shopId); + if (!$affRows) { + throw new Exception('修改失败'); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + $dbErrorLog = Zc::getLog('db_error'); + $dbErrorLog->info($ex->getMessage()); + return CommonTool::failResult("处理异常"); + } + } + + public function cancelProductManualSourceMajorByProductIds($productIds, $shopId) { + return $this->moveProductManualSourceDao->cancelProductManualSourceMajorByProductIds($productIds, $shopId); + } + + public function getMajorMoveProductManualSourceInfoByProductId($productId, $shopId) { + return $this->db->queryFirstRow('SELECT * FROM `move_product_manual_source` WHERE `product_id` = %i AND `shop_id` = %i AND `is_major` = 1', $productId, $shopId); + } + + public function batchAddMoveProductManualSource($shopId, $productArr, $isMajor = true) { + if (CommonTool::anyEmpty($shopId, $productArr)) { + return CommonTool::failResult('参数错误'); + } + $isMajor = $isMajor ? 1 : 0; + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + foreach ($productArr as $productId => $info) { + $manualSourceInfo = [ + 'shop_id' => $shopId, + 'product_id' => $productId, + 'move_collect_task_detail_id' => $info['taskDetailId'], + 'source' => $info['source'], + 'source_item_id' => $info['sourceItemId'], + 'site' => $info['site'], + 'is_major' => $isMajor, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + + if ($isMajor) { + $this->moveProductManualSourceDao->cancelProductManualSourceMajorByProductIds($productId, $shopId); + } + $this->insertUpdateMoveProductManualSource($manualSourceInfo); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult('数据库写入失败'); + } + } + + public function getMajorMoveProductManualSourceInfoByMoveTaskDetailId($moveTaskDetailId, $shopId) { + return $this->db->queryFirstRow('SELECT * FROM `move_product_manual_source` WHERE `move_collect_task_detail_id` = %i AND `shop_id` = %i AND `is_major` = 1', $moveTaskDetailId, $shopId); + } + + public function getProcessingTaskCount($shopId) { + $countBuffer = $this->db->queryFirstField("SELECT COUNT(*) FROM move_product_publish_buffer WHERE shop_id = %i", $shopId); + $countQueue = $this->db->queryFirstField("SELECT COUNT(*) FROM move_product_publish_queue WHERE shop_id = %i", $shopId); + return $countBuffer + $countQueue; + } + + public function getFreightTemplateOption($accessToken) { + $freightRet = $this->getFreightTemplateListFromDd($accessToken); + if (CommonTool::isFailRet($freightRet)) { + return []; + } + + $freightArr = []; + foreach ($freightRet['freightTemplateList'] as $value) { + $templateId = $value['template']['id']; + $templateName = empty($value['template']['template_name']) ? '默认模板' : $value['template']['template_name']; + $freightArr[$templateId] = $templateName; + } + + return $freightArr; + } + + public function getFreightTemplateListFromDd($accessToken) { + $req = new FreightTemplateListRequest(); + $req->setSize('1000'); + $ret = $this->dd->execute($req, $accessToken); + + $checkRet = CommonTool::checkDdApiRetStatus($ret); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + return CommonTool::successResult('freightTemplateList', $ret['data']['List']); + } + + public function addMoveAfterProductAddQueue($productId, $shopId, $action, $params, $gmtExec = null) { + // 处理move_after_product_add_queue的时候需要判断下搬家配置的商品状态是否为草稿箱 + $insertData = [ + 'shop_id' => $shopId, + 'product_id' => $productId, + 'action' => $action, + 'params' => $params, + 'gmt_exec' => $gmtExec ?: date('Y-m-d H:i:s'), + 'gmt_create' => date('Y-m-d H:i:s'), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]; + + $this->db->insert('move_after_product_add_queue', $insertData); + } + + public function isNeedUpdateSkuCodeUseProductId($condition) { + $productIdRequiredRuleList = [ + BatchConst::selectRuleProductIdAndSpec1AndSpec2, + BatchConst::selectRuleProductIdAndSpec1AndSpec2Num, + ]; + $itemNumRequiredRuleList = [ + BatchConst::selectRuleItemNum, + BatchConst::selectRuleItemNumAndSpec1AndSpec2Num, + BatchConst::selectRuleItemNumAndSpec1AndSpec2, + BatchConst::selectRuleItemNumAndNum, + BatchConst::selectRuleItemNumAndSpec1, + BatchConst::selectRuleItemNumAndSpec2, + ]; + if (!empty($condition['isBuildSkuCode'])) { + if (in_array($condition['skuCodeRule'], $productIdRequiredRuleList)) { + return true; + } + if (in_array($condition['skuCodeRule'], $itemNumRequiredRuleList) + && empty($condition['itemNum']) + && ($condition['skuCodeItemNumEmptyOperate'] == BatchConst::itemNumIsEmptyOperateUseProductId)) { + return true; + } + } + return false; + } + + public function lockMoveAfterProductQueue($timerLockId, $filter) { + $whereArr = []; + if (!empty($filter['includeShopIds'])) { + $whereArr[] = $this->db->prepare('AND shop_id in %li', $filter['includeShopIds']); + } + if (!empty($filter['excludeShopIds'])) { + $whereArr[] = $this->db->prepare('AND shop_id NOT IN %li', $filter['excludeShopIds']); + } + + $whereStr = implode(' ', $whereArr); + $excludeQueueIds = []; + + for ($tryTimes = 1; $tryTimes <= 3; $tryTimes++) { + if ($excludeQueueIds) { + $excludeQueueIds = array_unique($excludeQueueIds); + $whereStr .= $this->db->prepare(' AND move_after_product_add_queue_id NOT IN %li', $excludeQueueIds); + } + + $queueList = $this->db->query("SELECT move_after_product_add_queue_id,product_id,`action`,shop_id FROM move_after_product_add_queue WHERE locked = 0 and gmt_exec < now() %l LIMIT 100", $whereStr); + if (empty($queueList)) { + break; + } + + $queueId = 0; + + foreach ($queueList as $queue) { + if ($queue['action'] == MoveConst::moveAfterProductProcessTypeUpdateStatus) { + // 如果是下线操作,确保最后执行 + $queueListByProduct = $this->db->query("SELECT move_after_product_add_queue_id FROM move_after_product_add_queue WHERE product_id = %i and `action` != %s", $queue['product_id'], MoveConst::moveAfterProductProcessTypeUpdateStatus); + if (empty($queueListByProduct)) { + $queueId = $queue['move_after_product_add_queue_id']; + break; + } else { + $excludeQueueIds[] = $queue['move_after_product_add_queue_id']; + } + } else { + $queueId = $queue['move_after_product_add_queue_id']; + break; + } + } + + if (!$queueId) { + continue; + } + + $affRows = $this->db->update('move_after_product_add_queue', [ + 'locked' => $timerLockId, + 'hostname' => gethostname(), + 'gmt_locked' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ], 'move_after_product_add_queue_id = %i AND locked = 0', $queueId); + if ($affRows) { + $queueMsg = $this->db->queryFirstRow('SELECT * FROM move_after_product_add_queue WHERE move_after_product_add_queue_id = %i', $queueId); + return $this->fixMoveAfterProductQueue($queueMsg); + } + } + return []; + } + + private function fixMoveAfterProductQueue($queueMsg) { + // 暂时在这处理 shop_id==product_id 的脏数据 + if ($queueMsg && ($queueMsg['shop_id'] == $queueMsg['product_id'])) { + $shopId = $this->db->queryFirstField('select shop_id from product where product_id = %i', $queueMsg['product_id']); + if ($shopId) { + $queueMsg['shop_id'] = $shopId; + $this->db->update('move_after_product_add_queue', [ + 'shop_id' => $shopId + ], 'move_after_product_add_queue_id = %i', $queueMsg['move_after_product_add_queue_id']); + } + } + return $queueMsg; + } + + public function delayExecMoveAfterQueue($queueMsg, $reason) { + $tryTime = $queueMsg['try_times']; + if ($tryTime > 10) { + return $this->deleteMoveAfterProductQueue($queueMsg); + } + + $delayTime = $queueMsg['action'] == MoveConst::moveAfterProductProcessUpdateSkuCodeUseProductId ? 60 : 10; + $updateData = array( + 'try_times' => $tryTime + 1, + 'locked' => 0, + 'reason' => $reason, + 'gmt_exec' => date('Y-m-d H:i:s', time() + $delayTime * $tryTime), + 'gmt_modified' => ZcDbEval::now(), + ); + return $this->db->update('move_after_product_add_queue', $updateData, 'move_after_product_add_queue_id = %i', $queueMsg['move_after_product_add_queue_id']); + } + + public function deleteMoveAfterProductQueue($queueMsg) { + return $this->db->delete('move_after_product_add_queue', 'move_after_product_add_queue_id = %i and locked > 0', $queueMsg['move_after_product_add_queue_id']); + } + + public function getChinaProvinceList($flush = false) { + return $this->areaDao->getChinaProvinceList($flush); + } + + public function getParentIdAndCityIdMapAndParentIdAndCityInfoMapByParentIds($parentIds) { + return $this->areaDao->getParentIdAndCityIdMapAndParentIdAndCityInfoMapByParentIds($parentIds); + } + + public function getCityIdAndCityNameMap($flush = false) { + return $this->areaDao->getCityIdAndCityNameMap($flush); + } + + public function getShopDefaultMobile($shopId) { + $shopInfo = $this->shopDao->getShop($shopId); + $accessToken = $shopInfo['access_token']; + + $productRet = $this->productDao->getProductListFromDdV2([ + 'pageNo' => 1, + 'pageSize' => 1 + ], $accessToken); + if (CommonTool::isFailRet($productRet)) { + return ''; + } + + $productId = $productRet['data'][0]['product_id']; + $productInfoRet = $this->productDao->getProductFromDd($productId, $accessToken); + $productInfo = $productInfoRet['product']; + return $productInfo['mobile']; + } + + public function setProductLimitBuyToDd($shopId, $productId, $limitPerBuyer, $maximumPerOrder, $minimumPerOrder, $accessToken) { + return $this->productDao->setProductLimitBuyToDd($shopId, $productId, $limitPerBuyer, $maximumPerOrder, $minimumPerOrder, $accessToken); + } + + public function getMoveTaskConditionByProductId($productId) { + $condition = $this->db->queryFirstField('select mct.`condition` from move_product_log as mpl INNER JOIN move_collect_task_detail as mctd on mctd.move_collect_task_detail_id = mpl.move_collect_task_detail_id left join move_collect_task as mct on mct.move_collect_task_id = mctd.move_collect_task_id +where mpl.product_id = %i', $productId); + + return unserialize($condition); + } + + public function stringDeleteKeys($title, $needDeleteStrs) { + $needDeleteKeys = array(); + $needDeleteStrList = preg_split('/,|,|、/isU', $needDeleteStrs); + foreach ($needDeleteStrList as $needDeleteStr) { + if (empty(trim($needDeleteStr)) && (strlen($needDeleteStr) > 0) && $needDeleteStr !== '0') { + $needDeleteStr = ' '; + } else { + $needDeleteStr = trim($needDeleteStr); + } + + $needDeleteKeys[] = $needDeleteStr; + + } + + if (empty($needDeleteKeys)) { + return trim($title); + } + + $title = str_ireplace($needDeleteKeys, '', $title); + $title = trim($title); + return $title; + } + + public function getMoveTaskConditionByDetailId($moveTaskDetailId) { + $condition = $this->db->queryFirstField('select mct.`condition` from move_collect_task_detail as mctd join move_collect_task as mct on mct.move_collect_task_id = mctd.move_collect_task_id where mctd.move_collect_task_detail_id = %i', $moveTaskDetailId); + + return unserialize($condition); + } + + public function addAttachFbTotalToMoveShopConfig($shopId, $moveConfigId, $addNum) { + if (CommonTool::anyEmpty($shopId, $moveConfigId, $addNum)) { + return CommonTool::failResult("传入参数有误"); + } + + $ret = $this->db->exec("update `move_shop_config` set attach_fb_total = attach_fb_total + %i where `shop_id` = %i and `move_shop_config_id` = %i", $addNum, $shopId, $moveConfigId); + if ($ret === false) { + return CommonTool::failResult("添加数据库失败"); + } + + return CommonTool::successResult(); + } + + public function addAttachImportTotalToMoveShopConfig($shopId, $moveConfigId, $addNum) { + if (CommonTool::anyEmpty($shopId, $moveConfigId, $addNum)) { + return CommonTool::failResult("传入参数有误"); + } + + $ret = $this->db->exec("update `move_shop_config` set attach_import_total = attach_import_total + %i where `shop_id` = %i and `move_shop_config_id` = %i", $addNum, $shopId, $moveConfigId); + if ($ret === false) { + return CommonTool::failResult("添加数据库失败"); + } + + return CommonTool::successResult(); + } + + public function deductAddFetchBankCount($shopId, $successNum) { + $moveConfig = $this->getAvailableCopyCount($shopId); + $moveConfigId = $moveConfig['move_shop_config_id']; + return $this->db->update('move_shop_config', [ + 'used_fb_total' => $moveConfig['used_fb_total'] + $successNum, + ], 'shop_id = %i and `move_shop_config_id` = %i', $shopId, $moveConfigId); + } + + public function moveOvertimeQueueToBuffer() { + $queues = $this->db->query('select * from move_product_publish_queue where gmt_create < %s', date('Y-m-d H:i:s', time() - 3600)); + $newData = []; + $queueIds = []; + foreach ($queues as $queue) { + $queueIds[] = $queue['move_product_publish_queue_id']; + $newData[] = [ + 'shop_id' => $queue['shop_id'], + 'move_collect_task_id' => $queue['move_collect_task_id'], + 'move_collect_task_detail_id' => $queue['move_collect_task_detail_id'], + 'try_times' => $queue['try_times'], + 'priority' => $queue['priority'], + 'limit_source' => $queue['limit_source'], + 'gmt_create' => date('Y-m-d H:i:s'), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]; + } + + $this->db->insert('move_product_publish_buffer', $newData); + $this->db->delete('move_product_publish_queue', ' move_product_publish_queue_id in %li', $queueIds); + } + + public function saveEditMoveSetting($shopId, $defaultMoveShopSettingId, $needDelMoveShopSettingIds, $newConfigNameList) { + if (Commontool::allEmpty($defaultMoveShopSettingId, $needDelMoveShopSettingIds, $newConfigNameList)) { + return true; + } + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + + try { + if ($defaultMoveShopSettingId) { + $this->setDefaultSetting($shopId, $defaultMoveShopSettingId); + } + if ($needDelMoveShopSettingIds) { + $this->deleteMoveSetting($shopId, $needDelMoveShopSettingIds); + } + foreach ($newConfigNameList as $currConfigId => $configName) { + $this->db->update('move_shop_setting', array( + 'config_name' => $configName, + 'gmt_modified' => ZcDbEval::now() + ), ' shop_id = %i AND move_shop_setting_id = %i', $shopId, $currConfigId); + } + + $cnt = $this->db->queryFirstField('select count(*) from move_shop_setting where shop_id = %i and is_config_default = 1', $shopId); + if ($cnt != 1) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return true; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function deleteMoveSetting($shopId, $moveShopSettingId) { + $this->db->delete('move_shop_setting_quality', ' shop_id = %i AND move_shop_setting_id in %li', $shopId, $moveShopSettingId); + $this->db->delete('move_shop_setting_size_template', ' shop_id = %i AND move_shop_setting_id in %li', $shopId, $moveShopSettingId); + return $this->db->delete('move_shop_setting', ' shop_id = %i AND move_shop_setting_id in %li', $shopId, $moveShopSettingId); + } + + public function setDefaultSetting($shopId, $moveShopSettingId) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + + try { + $data['gmt_modified'] = ZcDbEval::now(); + $data['is_config_default'] = 0; + $this->db->update('move_shop_setting', $data, 'shop_id = %i', $shopId); + $data['is_config_default'] = 1; + $affRow = $this->db->update('move_shop_setting', $data, ' shop_id = %i AND move_shop_setting_id = %i', $shopId, $moveShopSettingId); + if (empty($affRow)) { + throw new \Exception('修改失败'); + } + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return true; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function addMoveGroupTask($taskInfo, $shopId) { + $insert['shop_auth_group_id'] = $taskInfo['groupId']; + $insert['move_group_task_name'] = $taskInfo['moveGroupTaskName']; + $insert['operator_shop_id'] = $shopId; + $insert['status'] = StatusConst::wait; + $insert['submit_type'] = $taskInfo['submitType']; + $insert['input_oss_url'] = empty($taskInfo['inputOssUrl']) ? null : $taskInfo['inputOssUrl']; + $insert['fetch_bank_code'] = empty($taskInfo['fetchBankCode']) ? null : $taskInfo['fetchBankCode']; + $insert['import_oss_url'] = empty($taskInfo['importOssUrl']) ? null : $taskInfo['importOssUrl']; + $insert['alloc_type'] = $taskInfo['allocType']; + $insert['gmt_create'] = ZcDbEval::now(); + $insert['gmt_modified'] = ZcDbEval::now(); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + if ($taskInfo['submitType'] == MoveConst::moveGroupSubmitTypeFb) { + foreach ($taskInfo['fetchBankMap'] as $fetchBankCode => $fetchBankName) { + $insert['fetch_bank_code'] = $fetchBankCode; + $insert['move_group_task_name'] = $fetchBankName; + $this->db->insert('move_group_task', $insert); + $taskId = $this->db->lastInsertId(); + $this->createMoveGroupTaskShop($taskInfo, $taskId); + } + } else { + $this->db->insert('move_group_task', $insert); + $taskId = $this->db->lastInsertId(); + $this->createMoveGroupTaskShop($taskInfo, $taskId); + } + + foreach ($taskInfo['shopIds'] as $selectShopId) { + $moveGroupToShopId = $this->db->queryFirstField('select move_group_to_shop_id from move_group_to_shop where shop_auth_group_id = %i and shop_id = %i', $taskInfo['groupId'], $selectShopId); + + $updateMoveToGroup['shop_auth_group_id'] = $taskInfo['groupId']; + $updateMoveToGroup['shop_id'] = $selectShopId; + $updateMoveToGroup['tips'] = '已添加商品包'; + $updateMoveToGroup['gmt_modified'] = ZcDbEval::now(); + if($moveGroupToShopId) { + $this->db->update('move_group_to_shop', $updateMoveToGroup, 'move_group_to_shop_id = %i', $moveGroupToShopId); + } else { + $insertMoveToGroup = $updateMoveToGroup; + $insertMoveToGroup['is_open'] = 1; + $insertMoveToGroup['gmt_create'] = ZcDbEval::now(); + $this->db->insert('move_group_to_shop', $insertMoveToGroup); + } + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("添加任务数据失败"); + } + } + + private function createMoveGroupTaskShop($taskInfo, $taskId) { + $taskShopInsert = []; + foreach ($taskInfo['shopIds'] as $shopId) { + $taskShopInsert[] = array( + 'shop_id' => $shopId, + 'move_group_task_id' =>$taskId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + } + + $this->db->insert('move_group_task_shop', $taskShopInsert); + } + + public function attachMoveGroupProcessInfo($shopList, $groupId, $shopIds) { + $gmtCount = date('Y-m-d'); + $countList = $this->db->query('SELECT shop_id, SUM(success_total) AS success_count, SUM(skip_total) AS skip_count, SUM(fail_total) AS fail_count FROM move_group_daily_count WHERE shop_auth_group_id = %i AND shop_id IN %ls AND gmt_count = %s GROUP BY shop_id', $groupId, $shopIds, $gmtCount); + $countList = ZcArrayHelper::changeKeyRow($countList, 'shop_id'); + + $shopIdArrs = array_chunk($shopIds, 5); + $waitCountList = []; + foreach ($shopIdArrs as $tempShopIds) { + $tempList = $this->db->query('SELECT shop_id, count(*) AS cnt FROM move_group_task_detail mgtd + LEFT JOIN move_group_task mgt ON mgtd.move_group_task_id = mgt.move_group_task_id WHERE mgt.shop_auth_group_id = %i + AND mgtd.shop_id IN %ls AND mgtd.`status` IN %ls GROUP BY shop_id', $groupId, $tempShopIds, [StatusConst::wait, StatusConst::processing]); + $waitCountList = array_merge($waitCountList, (array)$tempList); + } + $waitCountList = ZcArrayHelper::changeKeyRow($waitCountList, 'shop_id'); + + foreach ($shopList as &$shop) { + $shop['successCount'] = $countList[$shop['shop_id']]['success_count'] ?: 0; + $shop['failCount'] = $countList[$shop['shop_id']]['fail_count'] ?: 0; + $shop['skipCount'] = $countList[$shop['shop_id']]['skip_count'] ?: 0; + $shop['waitCount'] = $waitCountList[$shop['shop_id']]['cnt'] ?: 0; + } + + return $shopList; + } + + public function getMoveItemHistoryList($shopId, $groupId, $pageNo, $pageSize) { + list($moveItemHistoryList, $total) = $this->db->queryPage('SELECT sum(success_total) success_count, sum(fail_total) fail_count, sum(skip_total) skip_count, move_group_task_id, gmt_count, count(move_group_task_id) group_task_name_count FROM move_group_daily_count WHERE shop_id = %i AND shop_auth_group_id = %i GROUP BY gmt_count ORDER BY gmt_count DESC', $shopId, $groupId, $pageNo, $pageSize); + foreach ($moveItemHistoryList as &$moveItemHistory) { + $moveItemHistory['move_group_task_name'] = $this->db->queryFirstField('SELECT move_group_task_name FROM move_group_task WHERE move_group_task_id = %i', $moveItemHistory['move_group_task_id']); + $moveItemHistory['gmt_count'] = date('Y-m-d', strtotime($moveItemHistory['gmt_count'])); + } + + return array($moveItemHistoryList, $total); + } + + public function openOrCloseMoveGroupToShopByShopIds($isOpen, $groupId, $shopIds) { + $update = [ + 'gmt_modified' => ZcDbEval::now(), + ]; + if ($isOpen) { + $update['is_open'] = MoveConst::moveGroupOpen; + } else { + $update['is_open'] = MoveConst::moveGroupClose; + } + + $findShopIds = $this->db->queryFirstColumn('SELECT shop_id FROM move_group_to_shop WHERE shop_auth_group_id = %i AND shop_id in %ls', $groupId, $shopIds); + $updateShopIds = []; + $insertData = []; + foreach ($shopIds as $shopId) { + if (!$isOpen) { + $this->moveGroupTaskQueueToBuffer($shopId); + } + if (in_array($shopId, $findShopIds)) { + $updateShopIds[] = $shopId; + continue; + } + $insertData[] = [ + 'shop_auth_group_id' => $groupId, + 'shop_id' => $shopId, + 'is_open' => $update['is_open'] ? $update['is_open'] : MoveConst::moveGroupOpen, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + } + if (!empty($insertData)) { + $this->db->insert('move_group_to_shop', $insertData); + } + + if (!empty($updateShopIds)) { + $this->db->update('move_group_to_shop', $update, 'shop_auth_group_id = %i AND shop_id in %ls', $groupId, $updateShopIds); + } + } + + private function moveGroupTaskQueueToBuffer($shopId) { + $queues = $this->db->query('select move_group_task_queue_id, move_group_task_id, move_group_task_detail_id, move_collect_task_id, shop_auth_group_id, shop_id from move_group_task_queue where shop_id = %i', $shopId); + $queueIds = array_column($queues, 'move_group_task_queue_id'); + if (empty($queueIds)) { + return CommonTool::successResult(); + } + + foreach ($queues as &$queue) { + unset($queue['move_group_task_queue_id']); + $queue['gmt_create'] = date('Y-m-d H:i:s'); + $queue['gmt_modified'] = date('Y-m-d H:i:s'); + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->db->insert('move_group_task_queue_buffer', $queues); + $this->db->delete('move_group_task_queue', 'move_group_task_queue_id in %li', $queueIds); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("移buffer失败"); + } + + } + + public function lockMoveGroupTask($timerLockId, $filter) { + $where = ''; + if ($filter['includeShopIds']) { + $where = $this->db->prepare('and operator_shop_id in %ls', $filter['includeShopIds']); + } + if ($filter['excludeShopIds']) { + $where = $this->db->prepare('and operator_shop_id not in %ls', $filter['excludeShopIds']); + } + + $shopIds = $this->db->queryFirstColumn("select distinct `operator_shop_id` from `move_group_task` where `locked` = 0 AND `status` = %s %l", StatusConst::wait, $where); + if (empty($shopIds)) { + return array(); + } + $shopId = $shopIds[array_rand($shopIds, 1)]; + + $taskMsg = $this->db->queryFirstRow('SELECT * FROM move_group_task WHERE `operator_shop_id` = %i and `locked` = 0 AND `status` = %s order by `move_group_task_id` asc', $shopId, StatusConst::wait); + if (empty($taskMsg)) { + return array(); + } + $taskMsg['locked'] = $timerLockId; + + $affectRows = $this->db->update('move_group_task', array ( + 'locked' => $timerLockId, + 'status' => StatusConst::processing, + 'gmt_locked' => ZcDbEval::now(), + 'hostname' => gethostname(), + 'gmt_modified' => ZcDbEval::now() + ), "move_group_task_id = %i AND locked = 0", $taskMsg['move_group_task_id']); + + if ($affectRows == 1) { + $taskMsg['locked'] = $timerLockId; + return $taskMsg; + } + return array (); + } + + public function getMoveGroupTaskShops($taskId) { + return $this->db->queryFirstColumn('SELECT shop_id FROM move_group_task_shop WHERE move_group_task_id = %i', $taskId); + } + + public function insertMoveCollectTask($shopId, $copyType, $name, $condition, $loger) { + $condition['clientIp'] = CommonTool::clientIp(); + $insert = array( + 'shop_id' => $shopId, + 'copy_type' => $copyType, + 'name' => $name, + 'status' => StatusConst::wait, + 'success_count' => 0, + 'fail_count' => 0, + 'condition' => serialize($condition), + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + $ret = $this->db->insert('move_collect_task', $insert); + $moveCollectTaskId = $this->db->lastInsertId(); + $loger->info("INSERT move_collect_task SQL:" . $this->db->lastSql()); + if ($ret === false) { + return $ret; + } + + return $moveCollectTaskId; + } + + public function updateMoveGroupToShopTipsByShopIds($tips, $groupId, $shopIds) { + $update = [ + 'tips' => $tips, + 'gmt_modified' => ZcDbEval::now() + ]; + $this->db->update('move_group_to_shop', $update, 'shop_auth_group_id = %i AND shop_id in %li', $groupId, $shopIds); + } + + public function checkTaskProductHasExists($itemId, $source, $site, $moveGroupTaskId, $shopId){ + $where = ''; + if (!empty($site)) { + $where = $this->db->prepare(' AND site = %s', $site); + } + $detailId = $this->db->queryFirstColumn('SELECT move_group_task_detail_id FROM move_group_task_detail WHERE shop_id = %i AND move_group_task_id = %i AND source = %s AND source_item_id = %s %l', $shopId, $moveGroupTaskId, $source, $itemId, $where); + if (!empty($detailId)) { + return true; + } + return false; + } + + public function addMoveGroupTaskDetail($sourceItem, $moveGroupTaskId, $groupId, $moveTaskId, $shopId) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $insertMoveGroupDetailData = [ + 'move_group_task_id' => $moveGroupTaskId, + 'shop_id' => $shopId, + 'move_collect_task_id' => $moveTaskId, + 'source' => $sourceItem['source'], + 'site' => $sourceItem['site'], + 'source_item_id' => $sourceItem['itemId'], + 'replace_item_title' => $sourceItem['replaceItemTitle'], + 'fetch_bank_detail_id' => $sourceItem['fetchBankDetailId'], + 'status' => StatusConst::wait, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->insert('move_group_task_detail', $insertMoveGroupDetailData); + $moveGroupDetailId = $this->db->lastInsertId(); + + $insertMoveGroupQueueData = [ + 'move_group_task_id' => $moveGroupTaskId, + 'move_group_task_detail_id' => $moveGroupDetailId, + 'move_collect_task_id' => $moveTaskId, + 'shop_auth_group_id' => $groupId, + 'shop_id' => $shopId, + 'locked' => 0, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->insert('move_group_task_queue_buffer', $insertMoveGroupQueueData); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("添加任务数据失败"); + } + } + + public function deleteMoveCollectTask($taskId, $shopId) { + return $this->db->delete('move_collect_task', 'move_collect_task_id = %i AND shop_id = %i', $taskId, $shopId); + } + + public function updateMoveGroupTaskStatus($taskId, $processRet) { + $update = [ + 'status' => $processRet['result'], + 'reason' => $processRet['reason'], + 'gmt_modified' => ZcDbEval::now() + ]; + return $this->db->update('move_group_task', $update, 'move_group_task_id = %i', $taskId); + } + + public function getMoveGroupToShopByShopIds($shopIds, $groupId) { + return $this->db->query('SELECT * FROM move_group_to_shop WHERE shop_id in %ls AND shop_auth_group_id = %i', $shopIds, $groupId); + } + + public function selectMoveGroupTaskQueueBufferGroup(){ + $queueCount = $this->db->queryFirstField('SELECT COUNT(*) FROM move_group_task_queue '); + $maxQueueCount = 1000; + $leftCount = $maxQueueCount - $queueCount; + if ($leftCount <= 0) { + $this->moveGroupQueueBufferLog->info("selectMoveGroupTaskQueueBufferGroup queue leftCount[{$leftCount}] not enough, maxQueueCount[{$maxQueueCount}], curQueueCount[{$queueCount}]"); + return false; + } + + $groupIdShopIdCountList = $this->getGroupIdShopIdCountMap(); + if (empty($groupIdShopIdCountList)) { + $this->moveGroupQueueBufferLog->info("selectMoveGroupTaskQueueBufferShop shopCountMap is empty"); + return false; + } + + return $this->buildSelectedShopMap($groupIdShopIdCountList, $leftCount); + } + + private function getGroupIdShopIdCountMap() { + $groupIdShopIdList = $this->db->query('SELECT mgtu.shop_id, mgtu.shop_auth_group_id FROM move_group_to_shop mgtu WHERE mgtu.is_open = 1 AND EXISTS (SELECT 1 FROM move_group_task_queue_buffer mgtqb WHERE mgtqb.shop_id = mgtu.shop_id) '); + $groupIdShopIdCountMap = []; + + foreach ($groupIdShopIdList as $groupIdShopId) { + if (empty($groupIdShopId['shop_id']) || empty($groupIdShopId['shop_auth_group_id'])) { + continue; + } + + $cnt = $this->db->queryFirstField('SELECT count(*) cnt FROM move_group_task_queue_buffer WHERE shop_id = %i AND shop_auth_group_id = %i', $groupIdShopId['shop_id'], $groupIdShopId['shop_auth_group_id']); + if ($cnt <= 0) { + continue; + } + + $groupIdShopIdCountMap[] = [ + 'shop_id' => $groupIdShopId['shop_id'], + 'group_id' => $groupIdShopId['shop_auth_group_id'], + 'cnt' => $cnt ? : 0 + ]; + } + return $groupIdShopIdCountMap; + } + + private function buildSelectedShopMap($groupIdShopIdCountList, $leftCount) { + shuffle($groupIdShopIdCountList); + if (empty($groupIdShopIdCountList)) { + return array (); + } + $selectedShopGroupMap = array (); + $allocCount = 0; + $markFullIdxList = array (); + $loop = true; + while (true) { + foreach ($groupIdShopIdCountList as $vc) { + $selectShopIdGroupId = $vc['shop_id'] . '_' . $vc['group_id']; + $cnt = $vc['cnt']; + + if ((empty($vc['shop_id']) || empty($vc['group_id'])) || empty($cnt)) { + continue; + } + + if (isset($markFullIdxList[$selectShopIdGroupId])) { + continue; + } + + if (isset($selectedShopGroupMap[$selectShopIdGroupId])) { + $selectedShopGroupMap[$selectShopIdGroupId]++; + } else { + $selectedShopGroupMap[$selectShopIdGroupId] = 1; + } + + $allocCount++; + if ($allocCount == $leftCount) { + $loop = false; + break; + } + + if ($selectedShopGroupMap[$selectShopIdGroupId] == $vc['cnt']) { + $markFullIdxList[$selectShopIdGroupId] = $selectShopIdGroupId; + } + + if (count($markFullIdxList) == count($selectedShopGroupMap)) { + $loop = false; + break; + } + } + + if (!$loop) { + break; + } + } + $selectedShopGroupCntList = []; + foreach ($groupIdShopIdCountList as $groupIdShopIdCount) { + $selectShopIdGroupId = $groupIdShopIdCount['shop_id'] . '_' . $groupIdShopIdCount['group_id']; + $selectedShopGroupCntList[] = [ + 'shop_id' => $groupIdShopIdCount['shop_id'], + 'group_id' => $groupIdShopIdCount['group_id'], + 'cnt' => $selectedShopGroupMap[$selectShopIdGroupId] + ]; + } + + return $selectedShopGroupCntList; + } + + public function moveGroupQueueBufferShopToQueue($groupShopCount) { + $groupId = $groupShopCount['group_id']; + $shopId = $groupShopCount['shop_id']; + $count = $groupShopCount['cnt']; + $this->moveGroupQueueBufferLog->info("start move shopId $shopId grouId $groupId count $count to queue"); + + if (empty($groupId) || empty($shopId) || empty($count)) { + return ; + } + $moveCount = 0; + do { + $needMove = $count - $moveCount; + if ($needMove <= 0) { + break; + } + $limit = $needMove > 50 ? 50 : $needMove; + $bufferList = $this->db->query("SELECT * FROM move_group_task_queue_buffer WHERE shop_id = %i AND shop_auth_group_id = %i LIMIT %i", $shopId, $groupId, $limit); + $moveCount = $moveCount + count($bufferList); + if (empty($bufferList)) { + break; + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $insertQueueList = array(); + foreach ($bufferList as $buffer) { + $insertQueueList[] = array( + 'move_group_task_id' => $buffer['move_group_task_id'], + 'move_group_task_detail_id' => $buffer['move_group_task_detail_id'], + 'move_collect_task_id' => $buffer['move_collect_task_id'], + 'shop_auth_group_id' => $buffer['shop_auth_group_id'], + 'shop_id' => $buffer['shop_id'], + 'locked' => 0, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + } + + if ($insertQueueList) { + $this->db->insert('move_group_task_queue', $insertQueueList); + $bufferIds = ZcArrayHelper::getSub($bufferList, 'move_group_task_queue_buffer_id'); + $this->db->delete('move_group_task_queue_buffer', 'move_group_task_queue_buffer_id IN %li', $bufferIds); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->moveGroupQueueBufferLog->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("移动失败"); + } + + } while(true); + + return CommonTool::successResult(); + } + + public function lockMoveGroupTaskQueue($timerLockId, $filter) { + $where = ''; + if ($filter['includeShopIds']) { + $where = $this->db->prepare('and mgtq.shop_id in %ls', $filter['includeShopIds']); + } + if ($filter['excludeShopIds']) { + $where = $this->db->prepare('and mgtq.shop_id not in %ls', $filter['excludeShopIds']); + } + + $shopIds = $this->db->queryFirstColumn("select distinct mgtq.`shop_id` from `move_group_task_queue` mgtq LEFT JOIN move_group_to_shop mgtu ON mgtu.shop_id = mgtq.shop_id AND mgtu.shop_auth_group_id = mgtu.shop_auth_group_id where mgtq.`locked` = 0 AND mgtu.is_open = 1 %l", $where); + if (empty($shopIds)) { + return array(); + } + $shopId = $shopIds[array_rand($shopIds, 1)]; + + $queueMsg = $this->db->queryFirstRow('SELECT * FROM move_group_task_queue WHERE `shop_id` = %s and `locked` = 0 order by `move_group_task_queue_id` asc', $shopId); + + if (empty($queueMsg)) { + return array(); + } + $affectRows = $this->db->update('move_group_task_queue', array ( + 'locked' => $timerLockId, + 'gmt_locked' => ZcDbEval::now(), + 'gmt_last_heartbeat' => ZcDbEval::now(), + 'hostname' => gethostname(), + 'gmt_modified' => ZcDbEval::now() + ), "move_group_task_queue_id = %i AND locked = 0", $queueMsg['move_group_task_queue_id']); + + if ($affectRows == 1) { + $queueMsg['locked'] = $timerLockId; + return $queueMsg; + } + return array (); + } + + public function updateMoveGroupTaskQueueLastHeartbeat($queueId) { + $this->db->update('move_group_task_queue', array ( + 'gmt_last_heartbeat' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "move_group_task_queue_id = %i", $queueId); + } + + public function getMoveCollectTaskCondition($moveTaskId) { + $condition = $this->db->queryFirstField('SELECT `condition` FROM move_collect_task WHERE move_collect_task_id = %i', $moveTaskId); + return unserialize($condition); + } + + public function getMoveGroupTaskDetail($moveGroupTaskDetailId) { + return $this->db->queryFirstRow('SELECT *, mgt.submit_type, mgt.fetch_bank_code, mgt.operator_shop_id FROM move_group_task_detail mgtd LEFT JOIN move_group_task mgt ON mgtd.move_group_task_id = mgt.move_group_task_id WHERE mgtd.move_group_task_detail_id = %i', $moveGroupTaskDetailId); + } + + public function addItemToMoveTask($item, $moveCollectTaskId, $moveGroupTaskDetailId, $operatorShopId, $shopId, $condition, $loger) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $productTotal = 1; + $checkAndGetConfigIdRet = $this->checkAvailableCopyAndGetMoveConfigId($shopId, $productTotal); + if (CommonTool::isFailRet($checkAndGetConfigIdRet)) { + throw new Exception($checkAndGetConfigIdRet['reason']); + } + + $moveShopConfigId = $checkAndGetConfigIdRet['moveShopConfigId']; + $deductRet = $this->deductMoveCopyCount($shopId, $productTotal, $moveShopConfigId); + if (CommonTool::isFailRet($deductRet)) { + throw new Exception("shopId $shopId " . $deductRet['reason']); + } + + $moveCollectTaskDetailId = $this->insertMoveCollectDetail($shopId, $operatorShopId, $moveCollectTaskId, $item, $moveShopConfigId, $loger); + $this->insertMoveCollectDetailExt($moveCollectTaskDetailId, $shopId, $item); + + $limitSource = 'all'; + if (($item['source'] == FetchClientConst::collectTaskSource1688) && $item['is_fast_mode']) { + $limitSource = FetchClientConst::collectTaskSource1688; + } + $this->addTaskBuffer($shopId, $moveCollectTaskId, $moveCollectTaskDetailId, $productTotal, $limitSource); + + $this->updateMoveGroupTaskDetailStatus($moveCollectTaskDetailId, $moveGroupTaskDetailId); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $loger->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("添加任务数据失败"); + } + } + + private function insertMoveCollectDetailExt($moveCollectTaskDetailId, $authShopId, $item) { + $insertTaskDetailExt = array( + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'shop_id' => $authShopId, + 'price' => $item['price'], + 'has_change_img' => $item['has_change_img'] ? MoveConst::settingBoolTrue : null, + 'has_change_color_map' => $item['has_change_color_map'] ? MoveConst::settingBoolTrue : null, + 'has_change_size_map' => $item['has_change_size_map'] ? MoveConst::settingBoolTrue : null, + 'has_save_notes' => $item['has_save_notes'] ? MoveConst::settingBoolTrue : null, + 'need_shift_img' => $item['need_shift_img'] ? MoveConst::settingBoolTrue : null, + 'fetch_bank_detail_id' => $item['fetch_bank_detail_id'] ? $item['fetch_bank_detail_id'] : null, + 'move_group_task_detail_id' => $item['move_group_task_detail_id'] ? $item['move_group_task_detail_id'] : null, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + $this->db->insert('move_collect_task_detail_ext', $insertTaskDetailExt); + } + + private function insertMoveCollectDetail($authShopId, $operatorShopId, $moveCollectTaskId, $item, $moveShopConfigId, $loger) { + $insertTaskDetail = array( + 'shop_id' => $authShopId, + 'auth_shop_id' => $item['auth_shop_id'] ? $item['auth_shop_id'] : '', + 'operator_shop_id' => $operatorShopId, + 'move_collect_task_id' => $moveCollectTaskId, + 'is_fast_mode' => $item['is_fast_mode'], + 'source' => $item['source'], + 'site' => $item['site'], + 'source_item_id' => $item['source_item_id'], + 'source_title' => $item['source_title'], + 'source_img_url' => $item['source_img_url'], + 'source_shop_name' => $item['source_shop_name'], + 'move_shop_config_id' => $moveShopConfigId, + 'cid' => $item['cid'], + 'status' => StatusConst::processing, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + + $this->db->insert('move_collect_task_detail', $insertTaskDetail); + $loger->info("INSERT move_collect_task_detail SQL:" . $this->db->lastSql()); + return $this->db->lastInsertId(); + } + + private function updateMoveGroupTaskDetailStatus($moveCollectTaskDetailId, $moveGroupTaskDetailId) { + $data = [ + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'status' => StatusConst::processing, + 'gmt_modified' => ZcDbEval::now() + ]; + $status = $this->db->queryFirstField('SELECT `status` FROM move_group_task_detail WHERE move_group_task_detail_id = %i', $moveGroupTaskDetailId); + if ($status === StatusConst::delete) { + unset($data['status']); + } + + $this->db->update('move_group_task_detail', $data, 'move_group_task_detail_id = %i', $moveGroupTaskDetailId); + } + + public function updateMoveGroupTaskDetailResult($processRet, $moveGroupTaskDetailId) { + $update['gmt_modified'] = ZcDbEval::now(); + $update['status'] = $processRet['result']; + if(CommonTool::isFailRet($processRet) && $processRet['code'] == 'skip') { + $update['status'] = $processRet['code']; + } + + if (CommonTool::isFailRet($processRet)) { + $update['reason'] = $processRet['reason']; + } + + return $this->db->update('move_group_task_detail', $update, 'move_group_task_detail_id = %i', $moveGroupTaskDetailId); + } + + public function statisticMoveGroupMoveStatus ($processRet, $moveTaskGroupDetailId, $shopId) { + if (CommonTool::anyEmpty($processRet, $moveTaskGroupDetailId)) { + return false; + } + + if(CommonTool::isFailRet($processRet) && $processRet['code'] == 'skip') { + $processRet['result'] = $processRet['code']; + } + + try { + $ts = date('Y-m-d'); + $value = $shopId . '^' . $moveTaskGroupDetailId . '^' . $ts; + if ($this->redis->sAdd(RedisKeyConst::moveGroupMoveCountMap, $value) !== false) { + $key = RedisKeyConst::moveGroupMoveStatusCount . '_' . $moveTaskGroupDetailId . '_' . $ts . '_' . $processRet['result']; + if ($this->redis->incr($key) !== false) { + $this->redis->expire($key, 36000); + return true; + } + } + + return false; + } catch (Exception $e) { + return false; + } + } + + public function clearMoveGroupTaskQueue($qMsg, $processRet, $logger) { + $ret = $this->db->delete('move_group_task_queue', 'move_group_task_queue_id = %i', $qMsg['move_group_task_queue_id']); + $logger->info('delete queue ret['. $ret .']'); + if (CommonTool::isFailRet($processRet)) { + $data = [ + 'status' => StatusConst::fail, + 'reason' => $processRet['reason'], + 'gmt_modified' => ZcDbEval::now() + ]; + $this->db->update('move_group_task_detail', $data, 'move_group_task_detail_id = %i', $qMsg['move_group_task_detail_id']); + } + } + + public function processMoveGroupCopyStatusCount ($param) { + $moveCountMap = $this->redis->sGetMembers(RedisKeyConst::moveGroupMoveCountMap); + if (empty($moveCountMap)) { + $this->countMoveGroupLog->info('get redis shopConfigMap empty' . print_r($moveCountMap, true)); + return false; + } + $date = date('Y-m-d'); + foreach ($moveCountMap as $moveCountKey) { + list($shopId, $moveTaskGroupDetailId, $ts) = explode('^', $moveCountKey); + $taskInfo = $this->db->queryFirstRow('SELECT mgt.* FROM move_group_task mgt LEFT JOIN move_group_task_detail mgtd ON mgt.move_group_task_id = mgtd.move_group_task_id WHERE mgtd.move_group_task_detail_id = %i', $moveTaskGroupDetailId); + if (empty($taskInfo)) { + $this->countMoveGroupLog->info('empty taskInfo : '. $this->db->lastSql()); + continue; + } + $needProcessStatusList = [StatusConst::success, StatusConst::skip, StatusConst::fail]; + foreach ($needProcessStatusList as $status) { + $key = RedisKeyConst::moveGroupMoveStatusCount . '_' . $moveTaskGroupDetailId . '_' . $ts . '_' . $status; + $statusCount = (int)$this->redis->get($key); + if (empty($statusCount)) { + continue; + } + if ($this->redis->decrBy($key, $statusCount) !== false) { + $statusKey = $status . '_total'; + $update = [ + 'move_group_task_id' => $taskInfo['move_group_task_id'], + 'shop_auth_group_id' => $taskInfo['shop_auth_group_id'], + 'shop_id' => $shopId, + 'gmt_count' => $ts, + $statusKey => new ZcDbEval($statusKey . ' + ' . $statusCount), + 'gmt_modified' => ZcDbEval::now() + ]; + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + $effRow = $this->db->insertUpdate('move_group_daily_count', $insert, $update); + if (!$effRow) { + $row = $this->redis->incrBy($key, $statusCount); + $this->countMoveGroupLog->info("shopId[{$shopId}] update database fail effRow[{$effRow}] incrBy [{$statusCount}] ret[{$row}]"); + } + } + } + if ($date != $ts) { + $this->redis->sRem(RedisKeyConst::moveGroupMoveCountMap, $moveCountKey); + } + } + } + + public function getMoveItemHistoryDetailList($shopId, $groupId, $filter, $pageNo, $pageSize) { + $where = array(); + if ($filter['status']) { + if (is_array($filter['status'])) { + $where[] = $this->db->prepare('AND mctd.status in %ls', $filter['status']); + } else { + $where[] = $this->db->prepare('AND mctd.status = %s', $filter['status']); + } + } + if ($filter['moveDate']) { + $where[] = $this->db->prepare('AND mgtd.gmt_modified >= %s AND mgtd.gmt_modified < %s', date('Y-m-d H:i:s', strtotime($filter['moveDate'])), date('Y-m-d H:i:s', strtotime($filter['moveDate'] . '+1day'))); + } + $whereStr = implode(' ', $where); + + $statusList = array( + StatusConst::success, + StatusConst::fail, + StatusConst::skip + ); + list($moveItemHistoryDetailList, $total) = $this->db->queryPage('SELECT mgtd.move_group_task_detail_id, mctd.*, mgt.move_group_task_name, mil.product_id FROM move_group_task_detail mgtd LEFT JOIN move_group_task mgt ON mgt.move_group_task_id = mgtd.move_group_task_id LEFT JOIN move_collect_task_detail mctd ON mctd.move_collect_task_detail_id = mgtd.move_collect_task_detail_id LEFT JOIN move_product_log mil ON mctd.move_collect_task_detail_id = mil.move_collect_task_detail_id WHERE mgtd.move_collect_task_detail_id IS NOT NULL AND mgtd.shop_id = %i AND mgt.shop_auth_group_id = %i AND mgtd.`status` IN %ls %l ORDER BY mgtd.move_group_task_detail_id DESC', $shopId, $groupId, $statusList, $whereStr, $pageNo, $pageSize); + + $moveItemHistoryDetailList = $this->attachTaskInfoData($moveItemHistoryDetailList); + + return array($moveItemHistoryDetailList, $total); + } + + private function attachTaskInfoData($moveCollectTaskDetailList){ + $taskIds = ZcArrayHelper::getSub($moveCollectTaskDetailList, 'move_collect_task_id'); + $taskIds = array_unique($taskIds); + $taskList = $this->db->query("SELECT move_collect_task_id,copy_type FROM move_collect_task WHERE move_collect_task_id IN %li", $taskIds); + $taskList = ZcArrayHelper::changeKeyRow($taskList, 'move_collect_task_id'); + foreach ($moveCollectTaskDetailList as &$taskDetail) { + $currTaskId = $taskDetail['move_collect_task_id']; + $taskDetail['copy_type'] = $taskList[$currTaskId]['copy_type']; + } + return $moveCollectTaskDetailList; + } + + public function getMoveStopStatusByShopId($shopId) { + return $this->db->queryFirstField('select is_over_daily_total from move_shop_stop where shop_id = %i', $shopId); + } + + public function getMoveShopStopInfoByShopId($shopId) { + return $this->db->queryFirstRow("SELECT * FROM move_shop_stop WHERE shop_id = %i", $shopId); + } + + public function getNoSyncMoveSettingColums(){ + return array( + 'freight_template_id', + 'brand_id', + 'brand_name', + 'skip_match_category_fail', + 'match_fail_use_category_id', + 'quality_report_id', + 'class_quality_id', + 'common_size_template', + 'assoc_ids', + ); + } + + public function checkNeedDefaultSkuAlias($shopId) { + $fieldName = 'sku_alias_delete'; + $check = $this->db->queryFirstField('select 1 from move_shop_setting_big_field where shop_id = %i and field_name = %s', $shopId, $fieldName); + if($check) { + return 0; + } + return 1; + } + + public function addMoveItemSourceInfo($source, $itemId, $title, $shopName, $itemNum, $brandName) { + if (empty($itemNum)) { + return; + } + $insertData = array( + 'source' => $source, + 'item_id' => $itemId, + 'title' => $title, + 'shop_name' => $shopName, + 'brand' => $brandName, + 'item_num' => $itemNum, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + + $updateData = array( + 'same_item_num_count' => new ZcDbEval('same_item_num_count + 1'), + 'gmt_modified' => ZcDbEval::now(), + ); + + return $this->db->insertUpdate('tmp_move_item_source_info', $insertData, $updateData); + } + + public function getMoveImgOssUrlByMd5Value($md5Value) { + return $this->db->queryFirstField('select oss_url from move_collect_img_to_oss where md5_material = %s', $md5Value); + } + + public function insertUpdateMoveImgOssUrlInfo($shopId, $imgUrl, $ossUrl, $md5Value) { + $update = [ + 'shop_id' => $shopId, + 'img_url' => $imgUrl, + 'oss_url' => $ossUrl, + 'md5_material' => $md5Value, + 'gmt_modified' => ZcDbEval::now(), + ]; + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + return $this->db->insertUpdate('move_collect_img_to_oss', $insert, $update); + } + + + public function getCopyTypeByMoveCollectTaskId($taskId) { + return $this->db->queryFirstField('select copy_type from move_collect_task where move_collect_task_id = %i', $taskId); + } + + public function checkExistMoveCollectTaskDetailByItemId($shopId, $source, $sourceItemId, $statuses = array()) { + $whereArr = array(); + if ($statuses) { + $whereArr[] = $this->db->prepare('and status in %ls', $statuses); + } + $whereStr = implode(' ', $whereArr); + return $this->db->queryFirstField('select 1 from move_collect_task_detail where shop_id = %i and source = %s and source_item_id = %s %l LIMIT 1 ', $shopId, $source, $sourceItemId, $whereStr); + } + + public function getShopProductQualitySettingList($shopId, $settingId = 0, $cid = null) { + $where = []; + if ($settingId) { + $where[] = $this->db->prepare("and move_shop_setting_id = %i", $settingId); + } + if (is_array($cid)) { + $where[] = $this->db->prepare("and cid in %li", $cid); + } elseif (is_numeric($cid)) { + $where[] = $this->db->prepare("and cid in %li", [$cid, 0]); + } + return $this->db->query("select * from move_shop_setting_quality where shop_id = %i %l", $shopId, implode(' ', $where)); + } + + public function getShopProductQualitySettingByMoveShopSettingIdAndCidAndQualityKey($moveShopSettingId, $cid, $qualityKey) { + return $this->db->queryFirstRow("select * from move_shop_setting_quality where move_shop_setting_id = %i and cid = %i and quality_key = %s", $moveShopSettingId, $cid, $qualityKey); + } + + public function getSizeTemplateSubTypeByCid($cid) { + return $this->productDao->getSizeTemplateSubTypeByCid($cid); + } + + public function getSizeTemplateSubTypeByCateIds($cateIds) { + return $this->productDao->getSizeTemplateSubTypeByCateIds($cateIds); + } + + public function getCategorySizeTemplateSubTypeList($filter, $pageNo, $pageSize) { + return $this->productDao->getCategorySizeTemplateSubTypeList($filter, $pageNo, $pageSize); + } + + public function getCategorySizeTemplateSubTypeMap($shopCateMap = null) { + return $this->productDao->getCategorySizeTemplateSubTypeMap($shopCateMap); + } + + public function getRequiredSizeTemplateCids($shopId) { + $list = $this->productDao->getShopRequiredSizeTemplateList($shopId); + return array_column($list, 'cid'); + } + + public function getShopSettingSizeTemplateList($shopId, $settingId = 0, $cid = null) { + $where = []; + if ($settingId) { + $where[] = $this->db->prepare("and move_shop_setting_id = %i", $settingId); + } + if (is_array($cid)) { + $where[] = $this->db->prepare("and cid in %li", $cid); + } elseif (is_numeric($cid)) { + $where[] = $this->db->prepare("and cid = %i", $cid); + } + return $this->db->query("select * from move_shop_setting_size_template where shop_id = %i %l", $shopId, implode(' ', $where)); + } + + public function getShopTemplateInfoListByShopSettingSizeTemplateList($shopId, $shopSettingSizeTemplateList) { + $templateIds = array_column($shopSettingSizeTemplateList,'template_id'); + $templateIds = array_unique($templateIds); + $shopTemplateList = $this->getMoveShopSizeTemplateListByTemplateIds($shopId, $templateIds); + $shopTemplateMap = array_column($shopTemplateList, null, 'template_id'); + $cidAndTemplateIdMap = array_column($shopSettingSizeTemplateList,'template_id', 'cid'); + $cidAndTemplateInfoMap = []; + foreach ($cidAndTemplateIdMap as $cid => $templateId) { + $cidAndTemplateInfoMap[$cid] = $shopTemplateMap[$templateId]; + } + + return $cidAndTemplateInfoMap; + } + + public function getMoveShopSizeTemplateListByTemplateIds($shopId, $templateIds) { + return $this->db->query('select * from move_shop_size_template where shop_id = %i and template_id in %li', $shopId, $templateIds); + } + + public function getShopSettingSizeTemplateIdByCid($shopId, $settingId, $cid, $commonTemplateId) { + $sizeTemplateSetting = $this->db->queryFirstRow("select template_id from move_shop_setting_size_template where shop_id = %i and move_shop_setting_id = %i and cid = %i", $shopId, $settingId, $cid); + return $sizeTemplateSetting['template_id'] ?: $commonTemplateId; + } + + public function getShopSettingCidSizeTemplateIdMap($shopId, $settingId, $cids) { + if (empty($cids)) { + return []; + } else { + $sizeTemplateSettings = $this->db->query("select template_id,cid from move_shop_setting_size_template where shop_id = %i and move_shop_setting_id = %i and cid in %li", $shopId, $settingId, $cids); + return array_column($sizeTemplateSettings, 'template_id', 'cid'); + } + } + + public function getShopSettingSizeTemplateByCid($shopId, $settingId, $cid, $commonTemplateId) { + $sizeTemplate = []; + $sizeTemplateId = $this->getShopSettingSizeTemplateIdByCid($shopId, $settingId, $cid, $commonTemplateId); + if ($sizeTemplateId) { + $sizeTemplate = $this->getSizeTemplateInfo($sizeTemplateId); + } + return $sizeTemplate; + } + + public function getShopSettingCidSizeTemplateMap($shopId, $settingId, $cidCommonTemplateIdMap) { + $cidCommonTemplateIdMap = (array)$cidCommonTemplateIdMap; + $cids = array_keys($cidCommonTemplateIdMap); + $cidSizeTemplateMap = []; + $cidSizeTemplateIdMap = $this->getShopSettingCidSizeTemplateIdMap($shopId, $settingId, $cids); + foreach ($cids as $cid) { + if (empty($cidSizeTemplateIdMap[$cid]) && !empty($cidCommonTemplateIdMap[$cid])) { + $cidSizeTemplateIdMap[$cid] = $cidCommonTemplateIdMap[$cid]; + } + } + $sizeTemplateIds = array_unique(array_values($cidSizeTemplateIdMap)); + if (empty($sizeTemplateIds)) { + $sizeTemplateMap = []; + } else { + $sizeTemplates = $this->db->query("select * from move_shop_size_template where template_id in %li", $sizeTemplateIds); + $sizeTemplateMap = ZcArrayHelper::changeKeyRow($sizeTemplates, 'template_id'); + } + foreach ($cidSizeTemplateIdMap as $cid => $sizeTemplateId) { + $cidSizeTemplateMap[$cid] = $sizeTemplateMap[$sizeTemplateId] ?: null; + } + return $cidSizeTemplateMap; + } + + public function getSizeTemplateInfo($sizeTemplateId) { + return $this->db->queryFirstRow("select * from move_shop_size_template where template_id = %i", $sizeTemplateId); + } + + public function getProductQualityMap() { + $qualityList = $this->db->query("select quality_key, quality_name from product_quality where 1"); + return ZcArrayHelper::mapNameValue($qualityList, 'quality_key', 'quality_name'); + } + + private function getProductQualityCacheFile($cid) { + return Zc::C(ZcConfigConst::LogDir) . 'cache/move_service/product_quality_' . $cid . '.json'; + } + + private function getProductQualityFromCache($cid) { + $cacheFile = $this->getProductQualityCacheFile($cid); + if (!file_exists($cacheFile)) { + return null; + } + $cache = json_decode(file_get_contents($cacheFile), true); + if (!$cache || ($cache['create_time'] < time() - 3600)) { + return null; + } + return $cache['data']; + } + + private function setProductQualityCache($cid, $data) { + $cacheFile = $this->getProductQualityCacheFile($cid); + $dir = dirname($cacheFile); + if (!file_exists($dir)) { + mkdir($dir, 0755, true); + } + $cache = [ + 'create_time' => time(), + 'data' => $data, + ]; + file_put_contents($cacheFile, json_encode($cache)); + } + + public function getProductQualityToCidList($cid, $accessToken, $updateDb = false, $useCache = true) { + if ($useCache && ($cache = $this->getProductQualityFromCache($cid))) { + return CommonTool::successResult(['qualityList' => $cache]); + } + + $req = new ProductQualificationConfigRequest(); + $req->setCategoryId($cid); + $ddRet = DdFactory::getDdClient()->execute($req, $accessToken); + $checkRet = CommonTool::checkDdApiRetStatus($ddRet); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + $configList = $ddRet['data']['config_list']; + $qualityList = []; + foreach ($configList as $config) { + $quality = [ + 'is_required' => $config['is_required'], + 'quality_key' => $config['key'], + 'quality_name' => $config['name'], + 'text_list' => $config['text_list'], + ]; + $qualityList[$config['key']] = $quality; + if ($updateDb) { + $this->insertUpdateProductQuality($quality); + } + } + + $this->setProductQualityCache($cid, $qualityList); + + return CommonTool::successResult(['qualityList' => $qualityList]); + } + + private function insertUpdateProductQuality($quality) { + $updateTime = $this->redis->hGet('product_quality_update_time', $quality['quality_key']) ? : 0; + if ($updateTime > (time() - 7200)) { + return; + } + + $insert = $update = [ + 'quality_key' => $quality['quality_key'], + 'quality_name' => $quality['quality_name'], + 'gmt_modified' => ZcDbEval::now(), + ]; + $insert['gmt_create'] = ZcDbEval::now(); + + $this->redis->hSet('product_quality_update_time', $quality['quality_key'], time()); + $this->db->insertUpdate('product_quality', $insert, $update); + } + + public function getProductQualityToCidListByShop() { + $qualityList = $this->db->query("select quality_key, quality_name from product_quality"); + return CommonTool::successResult(['qualityList' => $qualityList]); + } + + public function addProductQualityImgLog($shopId, $imgUrl) { + $update = $insert = [ + 'shop_id' => $shopId, + 'img_url' => $imgUrl, + 'img_url_md5' => md5($imgUrl), + 'status' => StatusConst::normal, + 'gmt_modified' => ZcDbEval::now(), + ]; + $insert['gmt_create'] = ZcDbEval::now(); + return $this->db->insertUpdate('move_shop_setting_quality_image_log', $insert, $update); + } + + public function addProductQualityImgLogByQualityList($shopId, $qualityList) { + if (!$qualityList) { + return; + } + foreach ($qualityList as $quality) { + foreach ($quality['quality_attachments'] as $attachment) { + $this->addProductQualityImgLog($shopId, $attachment['url']); + } + } + } + + public function getProductQualityImgLogList($shopId, $filter, $pageNo, $pageSize) { + $sql = $this->db->prepare("select * from move_shop_setting_quality_image_log where shop_id = %i order by move_shop_setting_quality_image_log_id desc", $shopId); + return $this->db->queryPage($sql, $pageNo, $pageSize); + } + + public function saveSizeTemplateSetting($shopId, $moveShopSettingId, $cateSizeTemplateMap) { + if (empty($cateSizeTemplateMap)) { + return true; + } + $delCids = []; + $editCids = []; + foreach ($cateSizeTemplateMap as $cid => $templateId) { + if (!is_numeric($cid)) { + continue; + } + if (empty($templateId)) { + $delCids[] = $cid; + continue; + } + $editCids[] = $cid; + } + if (!empty($delCids)) { + $this->db->delete('move_shop_setting_size_template', "shop_id = %i and move_shop_setting_id = %i and cid in %li", $shopId, $moveShopSettingId, $delCids); + } + if (empty($editCids)) { + return true; + } + + $settingSizeTemplates = $this->db->query('select move_shop_setting_size_template_id,cid from move_shop_setting_size_template where shop_id = %i and move_shop_setting_id = %i and cid in %li', $shopId, $moveShopSettingId, $editCids); + $updateCids = []; + foreach ($settingSizeTemplates as $item) { + $updateCids[] = $item['cid']; + $update = [ + 'template_id' => $cateSizeTemplateMap[$item['cid']], + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->update('move_shop_setting_size_template', $update, 'move_shop_setting_size_template_id = %i', $item['move_shop_setting_size_template_id']); + } + $insertCids = array_diff($editCids, $updateCids); + if (!empty($insertCids)) { + $inserts = array_map(function ($cid) use ($shopId, $moveShopSettingId, $cateSizeTemplateMap) { + return [ + 'shop_id' => $shopId, + 'move_shop_setting_id' => $moveShopSettingId, + 'cid' => $cid, + 'template_id' => $cateSizeTemplateMap[$cid], + 'gmt_modified' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now(), + ]; + }, $insertCids); + if (count($inserts) > 0) { + $this->db->insert('move_shop_setting_size_template', $inserts); + } + } + return true; + } + + public function checkShopIsSetSizeTemplate($shopId) { + $exist = $this->db->queryFirstField('select 1 from move_shop_setting_size_template where shop_id = %i limit 1', $shopId); + if ($exist) { + return $exist; + } + + $config = $this->db->queryFirstField('select common_size_template from move_shop_setting where shop_id = %i and is_config_default = 1 limit 1', $shopId); + return unserialize($config); + } + + public function batchSaveSizeTemplateSetting($shopId, $settingId, $cids, $subTypeIdMap) { + $settingSizeTemplates = $this->db->query('select move_shop_setting_size_template_id,cid,template_id from move_shop_setting_size_template where shop_id = %i and move_shop_setting_id = %i and cid in %li', $shopId, $settingId, $cids); + $settingSizeTemplateMap = ZcArrayHelper::changeKeyRow($settingSizeTemplates, 'cid'); + unset($settingSizeTemplates); + $categorySizeTemplateSubTypeMap = $this->getCategorySizeTemplateSubTypeMap(); + $inserts = []; + $skipCids = []; + $skipPaths = []; + $transStatus = $this->db->startTransaction(); + $oldErrorMode = $this->db->setErrorMode(ZcDB::ERROR_MODE_EXCEPTION); + $updateCount = 0; + $cidTemplateIdMap = []; + try { + foreach ($cids as $cid) { + $subType = $categorySizeTemplateSubTypeMap[$cid]; + if (!$subType) { + $skipCids[] = $cid; + continue; + } + $templateId = $subTypeIdMap[$subType]; + if (!$templateId) { + $skipCids[] = $cid; + continue; + } + + if ($settingSizeTemplateMap[$cid]) { + //更新 + if ($settingSizeTemplateMap[$cid]['template_id'] != $templateId) { + $update = [ + 'template_id' => $templateId, + 'gmt_modified' => ZcDbEval::now(), + ]; + $this->db->update('move_shop_setting_size_template', $update, 'move_shop_setting_size_template_id = %i', $settingSizeTemplateMap[$cid]['move_shop_setting_size_template_id']); + $updateCount++; + $cidTemplateIdMap[$cid] = $templateId; + } + } else { + //新增 + $inserts[] = [ + 'shop_id' => $shopId, + 'move_shop_setting_id' => $settingId, + 'cid' => $cid, + 'template_id' => $templateId, + 'gmt_modified' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now(), + ]; + $cidTemplateIdMap[$cid] = $templateId; + } + } + $insertCount = count($inserts); + if ($insertCount > 0) { + $inserts = array_chunk($inserts, 100); + foreach ($inserts as $insertChunk) { + $this->db->insert('move_shop_setting_size_template', $insertChunk); + } + } + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult('配置失败'); + } + if (count($skipCids) > 0) { + $skipPaths = $this->db->query('select path from category_v2 where category_id in %li', $skipCids); + } + + return CommonTool::successResult('data', compact('insertCount', 'updateCount', 'skipPaths', 'cidTemplateIdMap')); + } + + private function saveProductQualitySetting($shopId, $moveShopSettingId, $data) { + if (empty($data['product_quality_map'])) { + return true; + } + $imgUrlLogList = []; + foreach ($data['product_quality_map'] as $cid => $qualityKeyImgMap) { + foreach ($qualityKeyImgMap as $qualityKey => $imgList) { + $imgList = array_filter($imgList, function ($url) { + return $url && filter_var($url, FILTER_VALIDATE_URL); + }); + $imgList = array_values(array_unique($imgList)); + if (empty($imgList)) { + $this->db->delete('move_shop_setting_quality', "shop_id = %i and move_shop_setting_id = %i and cid = %i and quality_key = %s", + $shopId, $moveShopSettingId, $cid, $qualityKey + ); + continue; + } + $imgUrlLogList += $imgList; + $update = [ + 'shop_id' => $shopId, + 'move_shop_setting_id' => $moveShopSettingId, + 'cid' => $cid, + 'quality_key' => $qualityKey, + 'contents' => json_encode($imgList), + 'gmt_modified' => ZcDbEval::now(), + ]; + $checkSql = $this->db->prepare("select move_shop_setting_quality_id from move_shop_setting_quality where shop_id = %i and move_shop_setting_id = %i and cid = %i and quality_key = %s", + $shopId, $moveShopSettingId, $cid, $qualityKey + ); + if ($row = $this->db->queryFirstRow($checkSql)) { + $this->db->update('move_shop_setting_quality', $update, 'move_shop_setting_quality_id = %i', $row['move_shop_setting_quality_id']); + } else { + $insert = $update; + $insert['gmt_create'] = $update['gmt_modified']; + $this->db->insert('move_shop_setting_quality', $insert); + } + } + } + foreach ($imgUrlLogList as $imgUrl) { + $this->addProductQualityImgLog($shopId, $imgUrl); + } + } + + public function checkAndMoveConfigImageAuditTask($bigFieldData, $data, $shopId, $moveShopSettingId) { + if (!empty($bigFieldData['desc_prefix_img'])) { + $fieldName = BizConst::bizMoveConfigImageFieldDescPrefixImg; + $extField = serialize(['desc_prefix_img_id' => $bigFieldData['desc_prefix_img_id']]); + $needAuditUrls = CommonTool::getImageUrlArrNotDdUrl([$bigFieldData['desc_prefix_img']]); + if (!empty($needAuditUrls)) { + $this->addMaterialBizMoveConfigImageTask($shopId, $moveShopSettingId, $fieldName, $extField, $needAuditUrls); + } + + } + + if (!empty($bigFieldData['desc_suffix_img'])) { + $fieldName = BizConst::bizMoveConfigImageFieldDescSuffixImg; + $extField = serialize(['desc_suffix_img_id' => $bigFieldData['desc_suffix_img_id']]); + $needAuditUrls = CommonTool::getImageUrlArrNotDdUrl([$bigFieldData['desc_suffix_img']]); + if (!empty($needAuditUrls)) { + $this->addMaterialBizMoveConfigImageTask($shopId, $moveShopSettingId, $fieldName, $extField, $needAuditUrls); + } + } + + if (!empty($data['product_quality_map'])) { + foreach ($data['product_quality_map'] as $cid => $qualityKeyImgMap) { + foreach ($qualityKeyImgMap as $qualityKey => $imgList) { + $imgList = array_filter($imgList, function ($url) { + return $url && filter_var($url, FILTER_VALIDATE_URL); + }); + $imgList = array_values(array_unique($imgList)); + if (!empty($imgList)) { + $fieldName = BizConst::bizMoveConfigImageFieldQuality; + $extField = serialize([ + 'cid' => $cid, + 'quality_key' => $qualityKey + ]); + $needAuditUrls = CommonTool::getImageUrlArrNotDdUrl($imgList); + if (!empty($needAuditUrls)) { + $this->addMaterialBizMoveConfigImageTask($shopId, $moveShopSettingId, $fieldName, $extField, $needAuditUrls); + } + } + } + } + } + } + + public function addMaterialBizMoveConfigImageTask($shopId, $moveShopSettingId, $fieldName, $extField, $needAuditUrls) { + return $this->materialDao->addMaterialBizMoveConfigImageTask($shopId, $moveShopSettingId, $fieldName, $extField, $needAuditUrls); + } + + public function addMoveRestoreHistoryTask($insertData) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->db->insert('move_restore_history_task', $insertData); + $insertData['move_restore_history_task_id'] = $this->db->lastInsertId(); + unset($insertData['condition']); + unset($insertData['status']); + $insertData['locked'] = 0; + + $this->db->insert('move_restore_history_queue', $insertData); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->moveLog->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("添加任务数据失败"); + } + } + + public function getMoveRestoreHistoryTaskList($shopId, $pageNo, $pageSize) { + return $this->db->queryPage("select * from move_restore_history_task where shop_id = %i order by move_restore_history_task_id desc", $shopId, $pageNo, $pageSize); + } + + public function stopRestoreMoveDelHistoryTask($shopId, $taskId) { + $restoreMoveDelHistoryTask = $this->getMoveRestoreHistoryTaskByTaskId($shopId, $taskId); + + if ($restoreMoveDelHistoryTask['status'] == StatusConst::finish) { + return CommonTool::failResult('任务已结束'); + } + + if ($restoreMoveDelHistoryTask['status'] == StatusConst::wait) { + return $this->delMoveRestoreHistoryQueue($taskId, $shopId); + } + + if ($restoreMoveDelHistoryTask['status'] == StatusConst::processing) { + $ret = $this->cancelMoveRestoreHistoryTask($shopId, $taskId); + if ($ret) { + return CommonTool::successResult(); + } else { + return CommonTool::failResult('取消恢复任务失败'); + } + } + + return CommonTool::failResult('任务状态异常,请刷新页面重试或联系客服'); + } + + private function getMoveRestoreHistoryTaskByTaskId($shopId, $taskId) { + return $this->db->queryFirstRow("select * from move_restore_history_task where shop_id = %i and move_restore_history_task_id = %i order by move_restore_history_task_id desc", $shopId, $taskId); + } + + private function delMoveRestoreHistoryQueue($taskId, $shopId) { + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $isSuccess = $this->doLockMoveRestoreHistoryQueue($taskId, $shopId); + if ($isSuccess != 1) { + return CommonTool::failResult('终止失败,请重试'); + } + + $this->db->delete('move_restore_history_queue', 'shop_id = %i and move_restore_history_task_id = %i', $shopId, $taskId); + $this->updateMoveRestoreHistoryTask($shopId, $taskId, ['status' => StatusConst::finish]); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult("终止任务数据失败"); + } + } + + public function doLockMoveRestoreHistoryQueue($taskId, $shopId, $timerLockId = 1) { + $updateData['gmt_locked'] = date('Y-m-d H:i:s'); + $updateData['gmt_modified'] = date('Y-m-d H:i:s'); + $updateData['gmt_last_heartbeat'] = date('Y-m-d H:i:s'); + $updateData['locked'] = $timerLockId; + return $this->db->update('move_restore_history_queue', $updateData, 'shop_id = %i and move_restore_history_task_id = %i and locked = 0', $shopId, $taskId); + } + + public function updateMoveRestoreHistoryTask($shopId, $taskId, $updateData) { + $updateData['gmt_modified'] = date('Y-m-d H:i:s'); + + return $this->db->update('move_restore_history_task', $updateData, 'shop_id = %i and move_restore_history_task_id = %i', $shopId, $taskId); + } + + private function cancelMoveRestoreHistoryTask($shopId, $taskId) { + $updateData['gmt_modified'] = date('Y-m-d H:i:s'); + $updateData['status'] = StatusConst::processingCancel; + return $this->db->update('move_restore_history_task', $updateData, 'shop_id = %i and move_restore_history_task_id = %i and status = "processing" ', $shopId, $taskId); + } + + public function lockMoveRestoreHistoryQueue($timerLockId, $filter) { + $whereArr = array(); + if (!empty($filter['includeShopIds'])) { + $whereArr[] = $this->db->prepare('AND shop_id IN %li', $filter['includeShopIds']); + } + if (!empty($filter['excludeShopIds'])) { + $whereArr[] = $this->db->prepare('AND shop_id NOT IN %li', $filter['excludeShopIds']); + } + $whereStr = implode(' ', $whereArr); + + $shopIds = $this->db->queryFirstColumn("SELECT shop_id FROM `move_restore_history_queue` WHERE locked = 0 %l group by shop_id", $whereStr); + if (empty($shopIds)) { + return []; + } + $shopId = $shopIds[array_rand($shopIds)]; + + $task = $this->db->queryFirstRow("SELECT q.move_restore_history_queue_id, t.* FROM `move_restore_history_queue` as q left join move_restore_history_task as t on t.move_restore_history_task_id = q.move_restore_history_task_id WHERE q.locked = 0 and t.shop_id = %i", $shopId); + + if (!empty($task)) { + $affectRows = $this->doLockMoveRestoreHistoryQueue($task['move_restore_history_task_id'], $shopId, $timerLockId); + if ($affectRows == 1) { + return $task; + } + } + return array (); + } + + public function clearMoveRestoreHistoryTaskAndQueue($shopId, $taskId) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->updateMoveRestoreHistoryTask($shopId, $taskId, ['status' => StatusConst::finish]); + $this->db->delete('move_restore_history_queue', 'move_restore_history_task_id = %i and shop_id = %i', $taskId, $shopId); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->moveLog->error($ex->getMessage()); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + + return CommonTool::failResult("清除队列失败"); + } + } + + public function restoreTaskDetailByShopId($shopId, $taskMsg) { + $restoreSuccessTotal = 0; + $restoreFailTotal = 0; + + if (empty($shopId)) { + $this->moveRestoreLog->info('restore history item,lack shopId'); + return CommonTool::failResult('缺少shopId'); + } + $this->moveRestoreLog = Zc::getLog('timer/move/move_restore_history/' . date('Ymd') . '/move_restore_history' . $shopId, ZcLog::INFO); + $this->moveRestoreLog->info("param is: shopId[$shopId], taskMsg: " . print_r($taskMsg, true)); + + $whereString = $this->buildWhereString($taskMsg['condition']); + + $queueId = $taskMsg['move_restore_history_queue_id']; + list($restoreSuccessTotal, $restoreFailTotal) = $this->restoreAcTaskDetail('ac', $shopId, $whereString, $taskMsg['move_restore_history_task_id'], $restoreSuccessTotal, $restoreFailTotal, $queueId); + + return array( + 'restoreSuccessTotal' => $restoreSuccessTotal, + 'restoreFailTotal' => $restoreFailTotal, + ); + } + + private function restoreAcTaskDetail($dbId, $shopId, $whereString, $restoreTaskId, $restoreSuccessTotal, $restoreFailTotal, $queueId) { + $limit = 100; + + $startDetailId = $this->db->useDbIdOnce($dbId)->queryFirstField("select min(mctd.move_collect_task_detail_id) from move_collect_task_detail mctd USE INDEX(`idx_shop_id_source_item_id_source`) + left join `move_product_log` mwl on mctd.move_collect_task_detail_id = mwl.move_collect_task_detail_id + where mctd.shop_id = %i %l order by mctd.move_collect_task_detail_id asc", $shopId, $whereString); + $this->moveRestoreLog->info('query move_collect_task_detail startDetailId: ' . $startDetailId); + if ($startDetailId === false) { + $this->moveRestoreLog->info('query move_collect_task_detail min move_collect_task_detail_id emtpy, maybe end [' . $this->db->lastSql() . ']'); + return array($restoreSuccessTotal, $restoreFailTotal); + } + $startDetailId--; + + while (true) { + if (file_exists(Zc::C(ZcConfigConst::LogDir) . 'rstd_stop')) { + $this->moveRestoreLog->info("rstd_stop stop file exist, exit"); + break; + } + + $this->updateMoveRestoreHistoryQueueLastHeartbeat($queueId); + + $taskInfo = $this->getMoveRestoreHistoryTaskByTaskId($shopId, $restoreTaskId); + if ($taskInfo['status'] == StatusConst::processingCancel) { + break; + } + + $historyTaskDetailList = $this->db->useDbIdOnce($dbId)->query("select mctd.* from `move_collect_task_detail` mctd USE INDEX(`idx_shop_id`) + left join `move_product_log` mwl on mctd.move_collect_task_detail_id = mwl.move_collect_task_detail_id + where mctd.`shop_id` = %i and mctd.move_collect_task_detail_id > %i %l order by mctd.`move_collect_task_detail_id` asc", $shopId, $startDetailId, $whereString, $limit); + $this->moveRestoreLog->info('query ac move_collect_task_detail historyTaskDetailList count: ' . count($historyTaskDetailList) . ', lastSql: ' . $this->db->lastSql()); + if (empty($historyTaskDetailList)) { + $this->moveRestoreLog->info('query move_collect_task_detail emtpy, maybe end [' . $this->db->lastSql() . ']'); + break; + } + $historyTaskDetailList = ZcArrayHelper::changeKeyRow($historyTaskDetailList, 'move_collect_task_detail_id'); + $this->updateMoveRestoreHistoryQueueLastHeartbeat($queueId); + $taskDetailList = $this->db->query("select * from move_collect_task_detail as mctd where mctd.shop_id = %i and mctd.move_collect_task_detail_id > %i %l order by mctd.move_collect_task_detail_id asc limit %i", $shopId, $startDetailId, $whereString, $limit); + $this->moveRestoreLog->info('query zc move_collect_task_detail taskDetailList count: ' . count($taskDetailList)); + $taskDetailIds = ZcArrayHelper::getSub($taskDetailList, 'move_collect_task_detail_id'); + + $ret = $this->startRestoreTaskDetail($dbId, $historyTaskDetailList, $taskDetailIds, $shopId); + $this->updateMoveRestoreHistoryQueueLastHeartbeat($queueId); + $restoreSuccessTotal += $ret['restoreSuccessTotal']; + $restoreFailTotal += $ret['restoreFailTotal']; + $startDetailId = max($taskDetailIds); + if (count($historyTaskDetailList) < $limit) { + $this->moveRestoreLog->info('query move_collect_task_detail emtpy count historyTaskDetailList lt limit, maybe end [' . $this->db->lastSql() . ']'); + break; + } + } + + return array($restoreSuccessTotal, $restoreFailTotal); + } + + private function updateMoveRestoreHistoryQueueLastHeartbeat($queueId) { + $this->db->update('move_restore_history_queue', array ( + 'gmt_last_heartbeat' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "move_restore_history_queue_id = %i", $queueId); + } + + private function startRestoreTaskDetail($dbId, $historyTaskDetailList, $taskDetailIds, $shopId) { + $restoreSuccessTotal = 0; + $restoreFailTotal = 0; + $needRestoreMoveSkuLog = array( + FetchClientConst::collectTaskSourceAuthJd, + FetchClientConst::collectTaskSourceJd, + FetchClientConst::collectTaskSourceSn, + FetchClientConst::collectTaskSourceYhd, + FetchClientConst::collectTaskSourceZhaojiafang, + FetchClientConst::collectTaskSourceSecoo, + ); + foreach ($historyTaskDetailList as $taskDetailId => $taskDetailInfo) { + $this->moveRestoreLog->info('taskDetailId: ' . $taskDetailId); + if (file_exists(Zc::C(ZcConfigConst::LogDir) . 'rstd_stop')) { + $this->moveRestoreLog->info("rstd_stop stop file exist, exit"); + break; + } + if (in_array($taskDetailId, $taskDetailIds)) { + $this->moveRestoreLog->info('restore history skip, taskDetailId: ' . $taskDetailId); + continue; + } + unset($taskDetailInfo['is_edited']); + unset($taskDetailInfo['item_image_urls']); + unset($taskDetailInfo['source_desc_md5']); + $historyTaskDetailExtInfo = $this->db->useDbIdOnce($dbId)->queryFirstRow("select * from move_collect_task_detail_ext where move_collect_task_detail_id = %i", $taskDetailId); + $historyMoveProductLogInfo = $this->db->useDbIdOnce($dbId)->queryFirstRow("select * from move_product_log where move_collect_task_detail_id = %i and shop_id = %i", $taskDetailId, $shopId); + $this->moveRestoreLog->info('restore history product, query historyTaskDetailExtInfo and historyMoveProductLogInfo taskDetailId: ' . $taskDetailId); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + try { + $this->db->insert('move_collect_task_detail', $taskDetailInfo); + $this->db->useDbIdOnce($dbId)->delete('move_collect_task_detail', 'move_collect_task_detail_id = %i', $taskDetailId); + if ($historyMoveProductLogInfo) { + $this->db->insert('move_product_log', $historyMoveProductLogInfo); + $this->db->useDbIdOnce($dbId)->delete('move_product_log', 'move_collect_task_detail_id = %i and shop_id = %i', $taskDetailId, $shopId); + } + if ($historyTaskDetailExtInfo) { + $this->db->insert('move_collect_task_detail_ext', $historyTaskDetailExtInfo); + $this->db->useDbIdOnce($dbId)->delete('move_collect_task_detail_ext', 'move_collect_task_detail_id = %i', $taskDetailId); + } + +// if (in_array($taskDetailInfo['source'], $needRestoreMoveSkuLog)) { +// $moveSkuLogList = $this->db->useDbIdOnce($dbId)->query("SELECT * FROM move_sku_log WHERE product_id = %i AND shop_id = %i", $historyMoveProductLogInfo['product_id'], $shopId); +// foreach ($moveSkuLogList as $moveSkuLog) { +// $this->db->insert('move_sku_log', $moveSkuLog); +// } +// $this->db->useDbIdOnce($dbId)->delete('move_sku_log', 'product_id = %i AND shop_id = %i', $historyMoveProductLogInfo['product_id'], $shopId); +// } + $this->moveRestoreLog->info('restore history product, task detail id is: ' . $taskDetailId); + + $restoreSuccessTotal++; + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $restoreFailTotal++; + $this->moveRestoreLog->info('restore history product fail, error message: ' . $ex->getMessage()); + $this->db->setErrorMode($oldErrorMode); + } + } + + return array( + 'restoreSuccessTotal' => $restoreSuccessTotal, + 'restoreFailTotal' => $restoreFailTotal, + ); + } + + private function buildWhereString($filter) { + $whereArray = array(); + if (!empty($filter['status'])) { + $whereArray[] = $this->db->prepare('and mctd.status in %li', (array) $filter['status']); + } + if (!empty($filter['moveHistoryEndTime'])) { + $whereArray[] = $this->db->prepare("and mctd.`gmt_create` <= %s", $filter['moveHistoryEndTime']); + } + + if (!empty($filter['moveHistoryStartTime'])) { + $whereArray[] = $this->db->prepare("and mctd.`gmt_create` >= %s", $filter['moveHistoryStartTime']); + } + + if (!empty($filter['moveHistoryProductId'])) { + $whereArray[] = $this->db->prepare("and mwl.product_id = %i", $filter['moveHistoryProductId']); + } + + if(!empty($filter['detailIds'])){ + $whereArray[] = $this->db->prepare("and mctd.`move_collect_task_detail_id` in %li", $filter['detailIds']); + } + $whereString = implode(' ', $whereArray); + + return $whereString; + } + + public function updateMoveDsSetting($setting, $moveShopSettingId, $shopId) { + if (isset($setting['skipCopied'])) { + $update['skip_copied'] = $setting['skipCopied'] ? $setting['skipCopied'] : null; + } + if (isset($setting['useSystemBanWord'])) { + $update['use_system_ban_word'] = $setting['useSystemBanWord'] ? $setting['useSystemBanWord'] : null; + } + if (isset($setting['autoFilterBanWord'])) { + $update['auto_filter_ban_word'] = $setting['autoFilterBanWord'] ? $setting['autoFilterBanWord'] : null; + } + if (isset($setting['delMainImgHeadNum'])) { + $update['del_main_img_head_num'] = $setting['delMainImgHeadNum'] ? $setting['delMainImgHeadNum'] : null; + } + if (isset($setting['delMainImgTailNum'])) { + $update['del_main_img_tail_num'] = $setting['delMainImgTailNum'] ? $setting['delMainImgTailNum'] : null; + } + if (isset($setting['delDescImgHeadNum'])) { + $update['del_desc_img_head_num'] = $setting['delDescImgHeadNum'] ? $setting['delDescImgHeadNum'] : null; + } + if (isset($setting['delDescImgTailNum'])) { + $update['del_desc_img_tail_num'] = $setting['delDescImgTailNum'] ? $setting['delDescImgTailNum'] : null; + } + if (isset($setting['isCopySourceVideo'])) { + $update['is_copy_source_video'] = $setting['isCopySourceVideo'] ? $setting['isCopySourceVideo'] : null; + } + if (isset($setting['aliPriceType'])) { + $update['ali_price_type'] = $setting['aliPriceType'] ? $setting['aliPriceType'] : null; + } + if (isset($setting['pricePercent'])) { + $update['price_percent'] = $setting['pricePercent'] ? $setting['pricePercent'] : null; + } + if (isset($setting['sourcePostFeePriceAddValue'])) { + $update['source_post_fee_price_add_value'] = $setting['sourcePostFeePriceAddValue'] ? $setting['sourcePostFeePriceAddValue'] : null; + } + if (isset($setting['priceAdd'])) { + $update['price_add'] = $setting['priceAdd'] ? $setting['priceAdd'] : null; + } + if (isset($setting['priceSub'])) { + $update['price_sub'] = $setting['priceSub'] ? $setting['priceSub'] : null; + } + if (isset($setting['priceTail'])) { + $update['price_tail'] = $setting['priceTail'] ? $setting['priceTail'] : null; + } + if (isset($setting['priceDecimal'])) { + $update['price_decimal'] = $setting['priceDecimal'] ? $setting['priceDecimal'] : null; + } + if (isset($setting['expressTemplateId'])) { + $update['freight_template_id'] = $setting['expressTemplateId'] ? $setting['expressTemplateId'] : null; + } + if (isset($setting['moveOnsaleType'])) { + $update['move_onsale_type'] = $setting['moveOnsaleType'] ? $setting['moveOnsaleType'] : null; + } + if (isset($setting['reduceType'])) { + $update['reduce_type'] = $setting['reduceType'] ? $setting['reduceType'] : null; + } + if (isset($setting['supply7dayReturn'])) { + $update['supply_7day_return'] = $setting['supply7dayReturn'] ? $setting['supply7dayReturn'] : null; + } + if (isset($setting['mobile'])) { + $update['mobile'] = $setting['mobile'] ? $setting['mobile'] : null; + } + if (isset($setting['titleDelete'])) { + $update['title_delete'] = $setting['titleDelete'] ? $setting['titleDelete'] : null; + } + + $update['shop_id'] = $shopId; + + return $this->updateMoveSetting($shopId, $moveShopSettingId, $update); + } + + public function checkMoveAuthShop($shopId, $authShopId) { + if ($shopId == $authShopId) { + return true; + } + $authShop = $this->db->queryFirstRow("select * from `move_auth_shop` where `shop_id` = %i and `auth_shop_id` = %i", $shopId, $authShopId); + if(empty($authShop)){ + return false; + } + + return true; + } + + public function addItemToBlacklist($shopId, $itemDetailSimple) { + $source = $itemDetailSimple['source']; + $itemId = $itemDetailSimple['itemId']; + $site = $itemDetailSimple['site'] ? : ''; + if (CommonTool::anyEmpty($shopId, $source, $itemId)) { + return CommonTool::failResult("添加到黑名单时参数有误"); + } + + $hasRecord = $this->db->queryFirstRow("SELECT * FROM move_collect_product_blacklist WHERE move_collect_product_blacklist_id IN( + SELECT move_collect_product_blacklist_id FROM move_collect_product_blacklist_product WHERE shop_id = %i AND product_id = %s + ) AND source = %s AND site = %s", $shopId, $itemId, $source, $site); + if ($hasRecord) { + return CommonTool::successResult(); + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + + try { + $this->db->insert('move_collect_product_blacklist', array( + 'shop_id' => $shopId, + 'source' => $source, + 'site' => $site, + 'product_id' => $itemId, + 'title' => $itemDetailSimple['title'], + 'img_url' => $itemDetailSimple['imgUrl'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + $blacklistId = $this->db->lastInsertId(); + if (empty($blacklistId)) { + throw new Exception("获取黑名单ID失败"); + } + + $insertBlacklistItemDataArr = array(); + $itemDetailSimple['sameItemIds'] = $itemDetailSimple['sameItemIds'] ? : [$itemId]; + foreach ($itemDetailSimple['sameItemIds'] as $itemId) { + $insertBlacklistItemDataArr[] = array( + 'shop_id' => $shopId, + 'move_collect_product_blacklist_id' => $blacklistId, + 'product_id' => $itemId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + } + + if ($insertBlacklistItemDataArr) { + $this->db->insert('move_collect_product_blacklist_product', $insertBlacklistItemDataArr); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + + $dbErrorLog = Zc::getLog('db_error'); + $dbErrorLog->info($ex->getMessage()); + return CommonTool::failResult("处理异常"); + } + + return CommonTool::successResult(); + } + + public function checkIsBlackItem($shopId, $itemId, $source) { + $isBlackItem = $this->db->queryFirstRow("SELECT 1 FROM move_collect_product_blacklist WHERE move_collect_product_blacklist_id IN( + SELECT move_collect_product_blacklist_id FROM move_collect_product_blacklist_product WHERE shop_id = %i AND product_id = %s + ) AND source = %s", $shopId, $itemId, $source); + return $isBlackItem ? true : false; + } + + public function buildShopIdAndBlacklistTagMapToItemList($mainShopId, $itemList, $source = '', $site = '') { + $shopIds = $this->getAuthShopIds($mainShopId); + $shopIds[] = $mainShopId; + $shopIds = array_unique($shopIds); + + $itemIdFieldName = $this->getItemIdFieldName(current($itemList)); + $itemIdList = ZcArrayHelper::getSub($itemList, $itemIdFieldName); + + $shopIdSourceSiteItemIdMap = $this->buildShopIdSourceSiteItemIdMapByBlacklist($shopIds, $itemIdList); + + foreach ($itemList as &$item) { + $source = $item['source'] ? : $source; + $site = $item['site'] ? : $site; + $itemId = $item[$itemIdFieldName] ? : ''; + + $shopIdIdAndBlacklistTagMap = array(); + foreach ($shopIds as $shopId) { + foreach ($this->getShareItemIdSourceList($source) as $source) { + if ($shopIdSourceSiteItemIdMap[$shopId][$source][$site][$itemId]) { + $shopIdIdAndBlacklistTagMap[$shopId] = 1; + } + } + } + + $item['shopIdAndBlacklistTagMap'] = $shopIdIdAndBlacklistTagMap; + } + + return $itemList; + } + + private function getShareItemIdSourceList($source) { + $shareItemIdSourceListArr = array( + array( + FetchClientConst::collectTaskWebsiteSourceAlimama, + FetchClientConst::collectTaskWebsiteSourceEtao, + FetchClientConst::collectTaskWebsiteSourceFanli + ), + + array( + FetchClientConst::collectTaskWebsiteSourceUnionJd, + FetchClientConst::collectTaskSourceJd, + ), + ); + + foreach ($shareItemIdSourceListArr as $shareItemIdSourceList) { + if (in_array($source, $shareItemIdSourceList)) { + return $shareItemIdSourceList; + } + } + + return array($source); + } + + private function getItemIdFieldName($item) { + $fieldNameArr = array('itemId', 'item_id', 'productId', 'product_id', 'wareId', 'ware_id', 'sku_id', 'skuId'); + foreach ($fieldNameArr as $fieldName) { + if ($item[$fieldName]) { + return $fieldName; + } + } + + return 'itemId'; + } + + public function getAuthShopIds ($shopId, $skipExpire = true) { + $authShopList = $this->getAuthShopList($shopId, $skipExpire); + return array_column($authShopList, 'shop_id'); + } + + private function buildShopIdSourceSiteItemIdMapByBlacklist($shopIds, $itemIdList) { + if (CommonTool::anyEmpty($shopIds, $itemIdList)) { + return array(); + } + + $itemIdListChunkArr = array_chunk($itemIdList, 200); + $shopIdSourceSiteItemIdMap = array(); + + foreach ($itemIdListChunkArr as $itemIdListChunk) { + $blacklistList = $this->db->query("SELECT mcpb.`shop_id`, mcpb.`source`, mcpb.`site`, mcpbp.`product_id` FROM move_collect_product_blacklist mcpb LEFT JOIN move_collect_product_blacklist_product mcpbp ON mcpbp.move_collect_product_blacklist_id = mcpb.move_collect_product_blacklist_id + WHERE mcpb.move_collect_product_blacklist_id IN ( + SELECT move_collect_product_blacklist_id FROM move_collect_product_blacklist_product WHERE shop_id IN %li + AND product_id IN %ls)", $shopIds, $itemIdListChunk); + + foreach ($blacklistList as $blacklist) { + $shopId = $blacklist['shop_id']; + $source = $blacklist['source'] ? : ''; + $site = $blacklist['site'] ? : ''; + $itemId = $blacklist['product_id'] ? : ''; + $shopIdSourceSiteItemIdMap[$shopId][$source][$site][$itemId] = true; + } + } + + return $shopIdSourceSiteItemIdMap; + } + + public function searchMoveBlacklist($filter, $shopId, $pageNo, $pageSize) { + $whereArr = array(); + $whereArr[] = $this->db->prepare("shop_id = %i", $shopId); + + if ($filter['productId']) { + $whereArr[] = $this->db->prepare("move_collect_product_blacklist_id IN ( + SELECT move_collect_product_blacklist_id FROM move_collect_product_blacklist_product + WHERE shop_id = %i AND product_id = %s)", $shopId, $filter['productId']); + } + + if ($filter['title']) { + $whereArr[] = $this->db->prepare("title LIKE %ss", $filter['title']); + } + + $whereStr = implode(' AND ', $whereArr); + list($itemList, $total) = $this->db->queryPage("SELECT * FROM move_collect_product_blacklist WHERE %l + ORDER BY move_collect_product_blacklist_id DESC", $whereStr, $pageNo, $pageSize); + + return array( + $itemList, $total + ); + } + + public function delItemBlacklistByIds($shopId, $blacklistIds) { + $productIds = $this->db->queryFirstColumn("SELECT product_id FROM move_collect_product_blacklist_product WHERE shop_id = %i AND move_collect_product_blacklist_id IN %li", $shopId, $blacklistIds); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + + try { + $this->db->delete('move_collect_product_blacklist', 'shop_id = %i AND move_collect_product_blacklist_id IN %li', $shopId, $blacklistIds); + $this->db->delete('move_collect_product_blacklist_product', 'shop_id = %i AND move_collect_product_blacklist_id IN %li', $shopId, $blacklistIds); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + + $dbErrorLog = Zc::getLog('db_error'); + $dbErrorLog->info($ex->getMessage()); + return CommonTool::failResult("处理异常"); + } + + return CommonTool::successResult('productIds', $productIds); + } + + public function delAllBlacklistItem($shopId) { + $startBlacklistId = 0; + $stepLen = 100; + + do { + $blacklistIds = $this->db->queryFirstColumn("SELECT move_collect_product_blacklist_id FROM move_collect_product_blacklist WHERE shop_id = %i AND move_collect_product_blacklist_id > %i ORDER BY move_collect_product_blacklist_id ASC LIMIT %i", $shopId, $startBlacklistId, $stepLen); + if (empty($blacklistIds)) { + break; + } + + $delRet = $this->delItemBlacklistByIds($shopId, $blacklistIds); + if (CommonTool::isFailRet($delRet)) { + return $delRet; + } + + $startBlacklistId = max($blacklistIds); + } while(true); + + return CommonTool::successResult(); + } + + public function updateMoveSettingMobile($shopId, $defaultMobile) { + return $this->db->update('move_shop_setting', ['mobile' => $defaultMobile], 'shop_id = %i and is_config_default = 1', $shopId); + } + + public function processClearDataShopInfoList($shopInfoList) { + if (empty($shopInfoList)) { + return true; + } + + foreach ($shopInfoList as $shopInfo) { + $update = array( + 'shop_id' => $shopInfo['shop_id'], + 'is_expire' => $shopInfo['is_expire'], + 'status' => $shopInfo['status'], + 'gmt_modified' => ZcDbEval::now() + ); + $insert = $update; + $insert['locked'] = 0; + $insert['gmt_create'] = ZcDbEval::now(); + + $this->db->insertUpdate('move_clear_data_queue', $insert, $update); + } + return true; + } + + public function lockMoveClearDataQueue($timerLockId, $filter) { + $where = ''; + if ($filter['includeShopIds']) { + $where = $this->db->prepare('AND shop_id IN %li', $filter['includeShopIds']); + } + if ($filter['excludeShopIds']) { + $where = $this->db->prepare('AND shop_id NOT IN %li', $filter['excludeShopIds']); + } + $queueIds = $this->db->queryFirstColumn('SELECT move_clear_data_queue_id FROM move_clear_data_queue WHERE `locked` = 0 and `status` = %s %l order by `move_clear_data_queue_id` asc limit 100 ', StatusConst::processing, $where); + $queueId = $queueIds[array_rand($queueIds, 1)]; + if (empty($queueId)) { + return array(); + } + + $queueMsg = $this->db->queryFirstRow('select * from move_clear_data_queue where move_clear_data_queue_id = %i ', $queueId); + $affectRows = $this->db->update('move_clear_data_queue', array ( + 'locked' => $timerLockId, + 'hostname' => gethostname(), + 'gmt_locked' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "move_clear_data_queue_id = %i AND locked = 0 AND `status` = %s", $queueId, StatusConst::processing); + if ($affectRows == 1) { + return $queueMsg; + } + return array (); + } + + public function doProcessMoveClearDataQueue($shopId, $isExpire, $accessToken) { + $this->moveClearLog = Zc::getLog('timer/move_clear/' . date('Y-m-d') . '/' . $shopId, ZcLog::INFO); + $this->moveClearLog->info("processMoveClearQueue shopId[$shopId] start"); + + $allStat = array(); + $processCount = 0; + $lastProductId = 0; + while (true) { + if (file_exists(Zc::C(ZcConfigConst::LogDir) .'mc_stop')) { + $this->moveClearLog->info("mc_stop file exist, exit"); + break; + } + + $productRows = $this->db->query('SELECT product_id, shop_id, move_collect_task_detail_id, gmt_create FROM move_product_log WHERE shop_id = %i AND product_id > %i order by product_id asc limit 200', $shopId, $lastProductId); + if (empty($productRows)) { + break; + } + $moveProductInfoList = array(); + foreach ($productRows as $product) { + $moveProductInfoList[$product['product_id']] = $product; + $lastProductId = $product['product_id']; + } + + $stat = $this->filterNoExistProductAndBackup($shopId, $isExpire, $accessToken, $moveProductInfoList); + foreach ($stat as $key => $c) { + $allStat[$key] = (int)$allStat[$key] + (int)$c; + } + + $processCount += count($moveProductInfoList); + $this->moveClearLog->info("processCount $processCount, allStat: " . ZcArrayHelper::sp($allStat)); + } + + $this->moveClearLog->info("processMoveClearQueue shopId[$shopId] end"); + return $allStat; + } + + public function filterNoExistProductAndBackup($shopId, $isExpire, $accessToken, $moveProductInfoList) { + if ($isExpire) { + $this->moveClearLog->info("shopId $shopId is expire over 6 months, backup all queue: " . count($moveProductInfoList)); + return $this->backupMoveProductInfo($moveProductInfoList, false, $accessToken); + } + + $moveProductIds = array_keys($moveProductInfoList); + $backupProductIds = $this->getShopNoExistProductIds($shopId, $moveProductIds); + + $this->moveClearLog->info("moveProductIds[" . implode(',', $moveProductIds) . '], backupProductIds[' . implode(',', $backupProductIds) . ']'); + if (empty($backupProductIds)) { + $this->moveClearLog->info("shopId $shopId nothing need backup."); + return array(); + } + + $backupProductInfoList = array(); + foreach ($backupProductIds as $backupProductId) { + $backupProductInfoList[$backupProductId] = $moveProductInfoList[$backupProductId]; + } + + return $this->backupMoveProductInfo($backupProductInfoList, true, $accessToken); + } + + private function getShopNoExistProductIds($shopId, $moveProductIds) { + $localProductIds = $this->db->queryFirstColumn("SELECT product_id FROM product WHERE shop_id = %i AND product_id in %li", $shopId, $moveProductIds); + return array_diff($moveProductIds, $localProductIds); + } + + private function backupMoveProductInfo($moveProductInfoList, $needCheckFromDd, $accessToken) { + $allStat = array(); + + $existProductIds = $this->db->queryFirstColumn('select product_id from product where product_id in %li', array_column($moveProductInfoList, 'product_id')); + foreach ($moveProductInfoList as $moveProductInfo) { + if (strtotime($moveProductInfo['gmt_create']) + 3600 * 24 * 180 < time()) { + $needCheckFromDd = false; + } + + if (in_array($moveProductInfo['product_id'], $existProductIds)) { + $needCheckFromDd = false; + } + if ($needCheckFromDd) { + $productInfosRet = $this->productDao->getProductFromDd($moveProductInfo['product_id'], $accessToken); + if (CommonTool::isSuccessRet($productInfosRet) && !in_array($productInfosRet['product']['status'], [ProductStatusConst::recycleBin, ProductStatusConst::delete, ProductStatusConst::checkBlocked])) { + list($productNew, , , $productExtend, , $productSpecPic) = $this->productDao->getProductByDdProduct($productInfosRet['product'], $moveProductInfo['shop_id'], date('YmdHis')); + $this->productDao->insertUpdate($productNew); + $this->productDao->saveProductExtend($productExtend); + continue; + } + + if (CommonTool::isFailRet($productInfosRet)) { + //授权已被关闭,请重新打开授权开关 + //时间戳和系统时间相差超过10分钟:2023-02-12 17:04:39 + //服务内部访问超时,请重试 + //请求被限流, 请稍后再试 + if (strpos($productInfosRet['reason'], '限流') || strpos($productInfosRet['reason'], '打开授权') || strpos($productInfosRet['reason'], '请重试') || strpos($productInfosRet['reason'], '超过10分钟')) { + continue; + } + } + } + + $stat = $this->doBackupMoveProductInfo($moveProductInfo['shop_id'], $moveProductInfo['product_id'], $moveProductInfo['move_collect_task_detail_id']); + foreach ($stat as $key => $c) { + $allStat[$key] = (int)$allStat[$key] + (int)$c; + } + } + + return $allStat; + } + + private function doBackupMoveProductInfo($shopId, $productId, $mctdId) { + $stat = array(); + + $mwlRow = $this->db->queryFirstRow('SELECT * FROM move_product_log WHERE product_id = %i', $productId); + try { + $stat['ac_mwl_count'] = $this->db->useDbIdOnce('ac')->insert('move_product_log', $mwlRow); + } catch (Exception $ex) { + $affect = $this->db->useDbIdOnce('ac')->delete('move_product_log', 'product_id = %i', $productId); + if ($affect) { + $stat['ac_mwl_count'] = $this->db->useDbIdOnce('ac')->insert('move_product_log', $mwlRow); + } + } + if ($stat['ac_mwl_count']) { + $stat['del_mwl_count'] = $this->db->delete('move_product_log', 'product_id = %i', $productId); + } + + $mctdeRows = $this->db->query('SELECT * FROM move_collect_task_detail_ext WHERE move_collect_task_detail_id = %i', $mctdId); + if ($mctdeRows) { + try { + $stat['ac_mctde_count'] = $this->db->useDbIdOnce('ac')->insert('move_collect_task_detail_ext', $mctdeRows); + } catch (Exception $ex) { + $affect = $this->db->useDbIdOnce('ac')->delete('move_collect_task_detail_ext', 'move_collect_task_detail_id = %i', $mctdId); + if ($affect) { + $stat['ac_mctde_count'] = $this->db->useDbIdOnce('ac')->insert('move_collect_task_detail_ext', $mctdeRows); + } + } + if ($stat['ac_mctde_count']) { + $stat['del_mctde_count'] = $this->db->delete('move_collect_task_detail_ext', 'move_collect_task_detail_id = %i', $mctdId); + } + } + + $mctdRow = $this->db->query('SELECT * FROM move_collect_task_detail WHERE move_collect_task_detail_id = %i', $mctdId); + try { + $stat['ac_mctd_count'] = $this->db->useDbIdOnce('ac')->insert('move_collect_task_detail', $mctdRow); + } catch (Exception $ex) { + $affect = $this->db->useDbIdOnce('ac')->delete('move_collect_task_detail', 'move_collect_task_detail_id = %i', $mctdId); + if ($affect) { + $stat['ac_mctd_count'] = $this->db->useDbIdOnce('ac')->insert('move_collect_task_detail', $mctdRow); + } + } + if ($stat['ac_mctd_count']) { + $stat['del_mctd_count'] = $this->db->delete('move_collect_task_detail', 'move_collect_task_detail_id = %i', $mctdId); + } + + $this->moveClearLog->info("doBackup shopId[$shopId], productId[$productId], mctdId[$mctdId] ret:" . ZcArrayHelper::sp($stat)); + return $stat; + } + + public function clearMoveClearDataQueue($queueMsg, $clearStat) { + $shopId = $queueMsg['shop_id']; + $queueId = $queueMsg['move_clear_data_queue_id']; + $this->db->delete('move_clear_data_queue', 'move_clear_data_queue_id = %i AND locked > 0', $queueId); + + $clearStat['shop_id'] = $shopId; + $clearStat['hostname'] = gethostname(); + $clearStat['gmt_modified'] = ZcDbEval::now(); + $clearStat['gmt_create'] = ZcDbEval::now(); + + $ar = $this->db->insert('move_clear_data_log', $clearStat); + $this->moveClearLog->info('insert move_clear_data_log: ' . $ar); + + $insert = [ + 'shop_id' => $shopId, + 'ac_mwl_count' => (int)$clearStat['ac_mwl_count'], + 'ac_mctd_count' => (int)$clearStat['ac_mctd_count'], + 'ac_mctde_count' => (int)$clearStat['ac_mctde_count'], + 'del_mwl_count' => (int)$clearStat['del_mwl_count'], + 'del_mctd_count' => (int)$clearStat['del_mctd_count'], + 'del_mctde_count' => (int)$clearStat['del_mctde_count'], + 'gmt_last_clear' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now() + ]; + $update = [ + 'shop_id' => $shopId, + 'ac_mwl_count' => new ZcDbEval('ac_mwl_count + %i', (int)$clearStat['ac_mwl_count']), + 'ac_mctd_count' => new ZcDbEval('ac_mctd_count + %i', (int)$clearStat['ac_mctd_count']), + 'ac_mctde_count' => new ZcDbEval('ac_mctde_count + %i', (int)$clearStat['ac_mctde_count']), + 'del_mwl_count' => new ZcDbEval('del_mwl_count + %i', (int)$clearStat['del_mwl_count']), + 'del_mctd_count' => new ZcDbEval('del_mctd_count + %i', (int)$clearStat['del_mctd_count']), + 'del_mctde_count' => new ZcDbEval('del_mctde_count + %i', (int)$clearStat['del_mctde_count']), + 'gmt_last_clear' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $ar = $this->db->insertUpdate('move_clear_data_info', $insert, $update); + $this->moveClearLog->info('insertUpdate move_clear_data_info: ' . $ar); + } + + public function getDsBuyUrl($shopId) { + $isExistDs = $this->isExistDs($shopId); + return DsConst::getDsBuyUrl($isExistDs); + } + + public function isExistDs($shopId) { + return $this->db->queryFirstField('select 1 from shop_to_1688_ds_member where shop_id = %i limit 1', $shopId); + } + + public function getDsMemberInfoFromDs($shopId) { + $isExist = $this->redis->hGet(RedisKeyConst::getDsMemberInfoFromDsKey(), $shopId); + if ($isExist) { + return []; + } + + $ret = $this->dsClient->getAuthShopMemberInfos(DsConst::platformDd, $shopId); + $this->redis->hSet(RedisKeyConst::getDsMemberInfoFromDsKey(), $shopId, 1); + $this->redis->expire(RedisKeyConst::getDsMemberInfoFromDsKey(), 3600 * 24); + if (CommonTool::isFailRet($ret)) { + return []; + } + + foreach ($ret['memberInfos'] as $memberInfo) { + $this->shopDao->insertUpdateUserTo1688DsMember($shopId, $memberInfo['memberId'], $memberInfo['resourceOwner'], strtotime($memberInfo['serviceExpireTime'])); + } + + return $this->getDsMemberInfoFromDb($shopId); + } + + private function getDsMemberInfoFromDb($shopId) { + return $this->moveDao->getDsMemberInfoFromDb($shopId); + } + + public function createMoveProductPublishToPicQueue($queueMsg) { + return $this->moveDao->createMoveProductPublishToPicQueue($queueMsg); + } + + public function getDsMemberInfo($shopId) { + $dsMemberInfo = $this->getDsMemberInfoFromDb($shopId); + $memberId = $dsMemberInfo['cnali_member_id']; + if (empty($memberId)) { + $dsMemberInfo = $this->getDsMemberInfoFromDs($shopId); + if (empty($dsMemberInfo)) { + return []; + } + $memberId = $dsMemberInfo['cnali_member_id']; + } + + if (!empty($dsMemberInfo['cnali_member_name'])) { + return $dsMemberInfo; + } + + $memberInfoRet = $this->dsClient->getDsMemberName($memberId, Zc::C('acn.ds.domain')); + if (CommonTool::isFailRet($memberInfoRet)) { + return ''; + } + $memberName = $memberInfoRet['memberInfo']['resourceOwner']; + + $this->db->update('shop_to_1688_ds_member', array( + 'cnali_member_name' => $memberName, + 'gmt_modified' => ZcDbEval::now(), + ), 'shop_id = %i and cnali_member_id = %s', $shopId, $memberId); + + $dsMemberInfo['cnali_member_name'] = $memberName; + return $dsMemberInfo; + } + + public function getAlibabaMemberId($shopId) { + return $this->db->queryFirstField('select cnali_member_id from shop_to_1688_ds_member where shop_id = %i and gmt_expire > now() order by gmt_modified desc limit 1', $shopId); + } + + public function getAlibabaProductToDsTaskDetailIdMap($moveCollectTaskDetailIds) { + if (empty($moveCollectTaskDetailIds)) { + return []; + } + $productToDsItems = $this->db->query('select cnali_ds_detail_id, move_collect_task_detail_id from move_collect_task_detail_ds_log where move_collect_task_detail_id in %li', $moveCollectTaskDetailIds); + return ZcArrayHelper::mapNameValue($productToDsItems, 'move_collect_task_detail_id', 'cnali_ds_detail_id'); + } + + public function isDsTaskDetail($taskDetailId) { + return !empty($this->db->query('select move_collect_task_detail_id from move_collect_task_detail_ds_log where move_collect_task_detail_id = %i', $taskDetailId)); + } + + public function getLtaoProductTaskDetailIdList($moveCollectTaskDetailIds) { + if (empty($moveCollectTaskDetailIds)) { + return []; + } + return $this->db->queryFirstColumn('select move_collect_task_detail_id from move_collect_task_detail_ltao_log where move_collect_task_detail_id in %li', $moveCollectTaskDetailIds); + } + + public function isLtaoTaskDetail($taskDetailId) { + return !empty($this->db->query('select move_collect_task_detail_id from move_collect_task_detail_ltao_log where move_collect_task_detail_id = %i', $taskDetailId)); + } + + public function getDsSourceItemId($shopId, $productId) { + return $this->db->queryFirstField('select source_item_id from product_to_ds_item where shop_id = %i and product_id = %i limit 1', $shopId, $productId); + } + + public function lockProductDsItemStatusQueue($timerLockId, $filter) { + $where = ''; + if ($filter['includeShopIds']) { + $where = $this->db->prepare('and shop_id in %li', $filter['includeShopIds']); + } + if ($filter['excludeShopIds']) { + $where = $this->db->prepare('and shop_id not in %li', $filter['excludeShopIds']); + } + + $shopIds = $this->db->queryFirstColumn("select distinct `shop_id` from `product_to_ds_item_status_queue` where `locked` = 0 %l", $where); + if (empty($shopIds)) { + return array (); + } + $shopId = $shopIds[array_rand($shopIds, 1)]; + + $queueMsg = $this->db->queryFirstRow('SELECT * FROM product_to_ds_item_status_queue WHERE `shop_id` = %i AND locked = 0', $shopId); + + if (empty($queueMsg)) { + return array (); + } + + $affectRows = $this->db->update('product_to_ds_item_status_queue', array ( + 'hostname' => gethostname(), + 'locked' => $timerLockId, + 'gmt_locked' => ZcDbEval::now(), + 'gmt_last_heartbeat' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "product_to_ds_item_status_queue_id = %i AND locked = 0", $queueMsg['product_to_ds_item_status_queue_id']); + + if ($affectRows == 1) { + return $queueMsg; + } + return array (); + } + + public function doProcessProductToDsItemStatusQueue($queueMsg, ZcLog $loger) { + $shopId = $queueMsg['shop_id']; + $productId = $queueMsg['product_id']; + $sourceItemId = $queueMsg['source_item_id']; + $status = $queueMsg['status']; + $loger->info('-------doProcessProductToDsItemStatusQueue---queueMsg' . print_r($queueMsg, true)); + $productInfo = $this->getDsProductData($sourceItemId, $shopId); + + if ($status == StatusConst::delete) { + $loger->info('-------doProcessProductToDsItemStatusQueue---start delete'); + $delRet = $this->dsClient->delProductDsItem($shopId, $productId, $sourceItemId, DsOrderConst::getOdDomainByApp()); + if (CommonTool::isFailRet($delRet)) { + $delRet['reason'] = '删除订单信息失败---' . $delRet['reason']; + return $delRet; + } + } + + if ($status == StatusConst::normal) { + $loger->info('-------doProcessProductToDsItemStatusQueue---start add'); + $addRet = $this->dsClient->addProductDsItem($shopId, $productId, $sourceItemId, DsOrderConst::getOdDomainByApp(), $productInfo['sellerId']); + if (CommonTool::isFailRet($addRet)) { + $addRet['reason'] = '添加订单信息失败---' . $addRet['reason']; + return $addRet; + } + } + + $loger->info('-------doProcessProductToDsItemStatusQueue---start update'); + $updateRet = $this->dsClient->updatePlatformDsItemStatus($shopId, $status, $productId, $sourceItemId, DsConst::platformDd, Zc::C('acn.ds.domain'), $productInfo['sellerId']); + if (CommonTool::isFailRet($updateRet)) { + $updateRet['reason'] = '更新主客信息失败---' . $updateRet['reason']; + return $updateRet; + } + + return $updateRet; + } + + public function clearProductToDsItemStatusQueue($queueMsg, $processRet) { + $lastHeartBeatTime = date('Y-m-d H:i:s', strtotime('-2 days')); + $this->db->delete('product_to_ds_item_status_queue', 'gmt_last_heartbeat < %s', $lastHeartBeatTime); + + if (CommonTool::isSuccessRet($processRet)) { + return $this->db->delete('product_to_ds_item_status_queue', 'product_to_ds_item_status_queue_id = %i', $queueMsg['product_to_ds_item_status_queue_id']); + } + } + + public function savePcwsConfig($shopId, $clientId, $isUseSelfFetch, $isJoinFetch, $isDisplayFetchButton, $isAutoFetchItem, $userAgreement, $version) { + $insert = $update = [ + 'shop_id' => $shopId, + 'is_use_self_fetch' => $isUseSelfFetch ? 1 : 0, + 'is_join_fetch' => $isJoinFetch ? 1 : 0, + 'is_display_fetch_button' => $isDisplayFetchButton ? 1 : 0, + 'is_auto_fetch_item' => $isAutoFetchItem ? 1 : 0, + 'user_agreement' => $userAgreement ? 1 : 0, + 'version' => $version, + 'ip' => CommonTool::clientIp(), + 'gmt_modified' => ZcDbEval::now(), + ]; + $insert['gmt_create'] = ZcDbEval::now(); + + $this->db->insertUpdate('pcws_config', $insert, $update); + $insert['client_id'] = $update['client_id'] = $clientId; + $this->db->insertUpdate('pcws_client_config', $insert, $update); + } + + + public function getBrandListByShopId($shopId) { + return $this->productDao->getBrandListByShopId($shopId); + } + + public function getBrandName($brandId, $shopId) { + return $this->productDao->getBrandName($brandId, $shopId); + } + + public function processBrandIdError($productDetailBase, $queueMsg, $dataIsChange, $reason, ZcLog $logger) { + return $this->productDao->processBrandIdError($productDetailBase, $queueMsg, $dataIsChange, $reason, $logger); + } + + public function getNewestMoveCommitmentLog($shopId) { + $row = $this->db->queryFirstRow('select * from move_commitment_log where shop_id = %i ', $shopId); + + return $row; + } + + public function saveUserCommitment($shopId, $ip, $ua) { + $insert = [ + 'shop_id' => $shopId, + 'ip' => $ip, + 'ua' => $ua, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + + $res = $this->db->insertUpdate('move_commitment_log', $insert, $insert); + return $res ? CommonTool::successResult() : CommonTool::failResult('保存失败'); + } + + public function checkBrandIsAuth($cid, $brandName, $accessToken) { + $ret = $this->getBrandListV2FromDd([ + 'query' => $brandName, + 'categoryId' => $cid + ], $accessToken); + + foreach ($ret['data']['auth_brand_list'] as $brand) { + if ($brandName == $brand['name_cn'] || $brand == $brand['name_en'] || $brand == $brand['name_en'] . '/' . $brand['name_cn']) { + return true; + } + } + + foreach ($ret['data']['brand_list'] as $brand) { + if ($brandName == $brand['name_cn'] || $brand == $brand['name_en'] || $brand == $brand['name_en'] . '/' . $brand['name_cn']) { + return true; + } + } + + return false; + } + + public function searchBrandIdByBrandName($cid, $brandName, $accessToken, $log = null, $isReturnNoBrand = true) { + return $this->productDao->searchBrandIdByBrandNameFromDd($cid, $brandName, $accessToken, $log, $isReturnNoBrand); + } + + public function getCateBrandMapAndIsBrandReqAndBrandAid($cateAttributes) { + return $this->productDao->getCateBrandMapAndIsBrandReqAndBrandAid($cateAttributes); + } + + public function matchBrandFromCateBrand($brandName, $cateBrandMap) { + return $this->productDao->matchBrandFromCateBrand($brandName, $cateBrandMap); + } + + public function searchBrandInfoByBrandName($brandName) { + return $this->productDao->searchBrandInfoByBrandName($brandName); + } + + public function getCateAttrsAndQualitys($needGetCateAttrCids, $needGetCateQualityCids, $accessToken) { + $cateAttrs = $cateQualitys = $fails = []; + $needGetCateAttrCids = array_unique($needGetCateAttrCids); + $needGetCateQualityCids = array_unique($needGetCateQualityCids); + $getCateAttrUrls = $getCateQualityUrls = []; + $domain = Zc::C('multi.crawler.domain'); + foreach ($needGetCateAttrCids as $cid) { + $getCateAttrUrls[] = Zc::url(RouteConst::TimerMoveTaskGetCateAttr, array('cid' => $cid, 'accessToken' => $accessToken), 'http', $domain); + } + foreach ($needGetCateQualityCids as $cid) { + $getCateQualityUrls[] = Zc::url(RouteConst::TimerMoveTaskGetCateQuality, array('cid' => $cid, 'accessToken' => $accessToken), 'http', $domain); + } + $urls = array_merge($getCateAttrUrls, $getCateQualityUrls); + if (!$urls) { + return [$cateAttrs, $cateQualitys, $fails]; + } + $urlRets = $this->spider->crawl($urls); + + foreach ($urlRets as $url => $urlRet) { + if (CommonTool::isFailRet($urlRet)) { + $fails[$url] = $urlRet; + continue; + } + $ret = json_decode($urlRet['content'], true); + if (CommonTool::isFailRet($ret)) { + $fails[$url] = $urlRet; + continue; + } + parse_str(parse_url($url, PHP_URL_QUERY), $param); + $cid = $param['cid']; + + if (strpos($url, RouteConst::TimerMoveTaskGetCateAttr) != false) { + $cateAttrs[$cid] = $ret['data']; + } elseif (strpos($url, RouteConst::TimerMoveTaskGetCateQuality) != false) { + $cateQualitys[$cid] = $ret['qualityList']; + } + } + + return [$cateAttrs, $cateQualitys, $fails]; + } + + public function getDsSkuList($skuList, $shopId, $productId) { + $productInfo = $this->tryGetDsProductInfo($shopId, $productId); + if (empty($productInfo)) { + return []; + } + + $skuRelationMap = []; + $getSkuRelationRet = $this->tryGetDsSkuRelation($shopId, $productId, $productInfo['productId']); + if (CommonTool::isSuccessRet($getSkuRelationRet) && !empty($getSkuRelationRet['skuRelation'])) { + $skuRelationMap = ZcArrayHelper::mapNameValue($getSkuRelationRet['skuRelation'], 'platformSkuId', 'sourceSkuId'); + } + + $skuList = ZcArrayHelper::changeKeyRow($skuList, 'sku_id'); + $skuMap = ZcArrayHelper::changeKeyRow($productInfo['skuMap'], 'skuId'); + $dsSkuList = []; + foreach ($skuList as $skuId => $skuInfo) { + $newSkuName = $skuInfo['sku_name']; + if (isset($skuRelationMap[$skuId]) && !empty($skuRelationMap[$skuId])) { + $sourceSkuId = $skuRelationMap[$skuId]; + $dsSkuList[$newSkuName] = $skuMap[$sourceSkuId]; + continue; + } + + $skuNameArr = array_filter(explode(' ', $newSkuName)); + $sourceSkuName = ';' . implode(';', $skuNameArr) . ';'; + if(count(explode(' ', $newSkuName)) == 1){ + $sourceSkuName .= ';'; + } + + if (isset($productInfo['skuMap'][$sourceSkuName])) { + $dsSkuList[$newSkuName] = $productInfo['skuMap'][$sourceSkuName]; + } + } + + if (empty($dsSkuList)) { + $dsSkuList['默认'] = array( + 'price' => $productInfo['jd_price'], + 'stock' => $productInfo['stock_num'], + ); + } + + return $dsSkuList; + } + + private function tryGetDsSkuRelation($shopId, $productId, $sourceItemId) { + return $this->dsClient->getMoveProductSkuRelation($shopId, DsConst::platformDd, $productId, $sourceItemId); + } + + public function resetAndCleanShopUuidCode($shopId) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + + $this->deleteShopUuidCode($shopId); + $this->db->delete('move_auth_shop', 'shop_id = %i', $shopId); + $this->db->delete('move_auth_shop', 'auth_shop_id = %i', $shopId); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return true; + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return false; + } + } + + public function deleteShopUuidCode($shopId) { + return $this->db->delete('shop_app_uuid', 'shop_id = %i', $shopId); + } + + public function addMultiShopToAuthShop($shopId, $authShopIds) { + $authShopsApp = $this->shopDao->getShopsApp($authShopIds); + $moveAuthShopIds = $this->db->queryFirstColumn("select auth_shop_id from `move_auth_shop` where `shop_id` = %i", $shopId); + $moveAuthShopIds[] = $shopId; + + $insert = []; + $expireShopCnt = 0; + foreach ($authShopsApp as $authShop) { + if($authShop['is_expire']) { + $expireShopCnt++; + continue; + } + + $authShopId = $authShop['shop_id']; + if(in_array($authShopId, $moveAuthShopIds)) { + continue; + } + + $insert[] = [ + 'shop_id' => $shopId, + 'auth_shop_id' => $authShopId, + 'initiator' => 1, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ]; + + $insert[] = [ + 'shop_id' => $authShopId, + 'auth_shop_id' => $shopId, + 'initiator' => 0, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ]; + } + + if($expireShopCnt == count($authShopsApp)) { + return CommonTool::failResult(' 授权店铺错误,请检查店铺是否过期'); + } + + if(empty($insert)) { + return CommonTool::successResult('添加成功'); + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->db->insert('move_auth_shop', $insert); + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult('添加失败' . $ex->getMessage()); + } + + return CommonTool::successResult('添加成功'); + } + + public function getMoveSetting($shopId, $moveShopSettingId) { + return $this->db->queryFirstRow('SELECT * FROM move_shop_setting WHERE shop_id = %i and move_shop_setting_id = %i', $shopId, $moveShopSettingId); + } + + public function recordDsProductCenterSearchText($shopId, $text, $isSystem, $isSearchProduct) { + $insert['shop_id'] = $shopId; + $insert['keyword'] = $text; + $insert['is_system'] = $isSystem; + $insert['is_search_product'] = $isSearchProduct; + $insert['gmt_create'] = ZcDbEval::now(); + $insert['gmt_modified'] = ZcDbEval::now(); + + $update = $insert; + unset($update['gmt_create']); + $this->db->insertUpdate('ds_product_center_search_log', $insert, $update); + } + + public function getDsProductCenterSearchText($shopId) { + return $this->db->queryFirstColumn('select keyword from ds_product_center_search_log where shop_id = %i limit 100', $shopId); + } + + public function clearDsProductCenterSearchText($shopId) { + $this->db->delete('ds_product_center_search_log', 'shop_id = %i', $shopId); + } + + public function productCenterSearchLog($filter, $pageNo, $pageSize) { + $where[] = '1=1'; + if ($filter['startDt']) { + $where[] = $this->db->prepare(' and gmt_modified > %s', $filter['startDt']); + } + if ($filter['endDt']) { + $where[] = $this->db->prepare(' and gmt_modified < %s', $filter['endDt']); + } + $whereStr = implode(' ', $where); + return $this->db->queryPage("SELECT * FROM ds_product_center_search_log WHERE %l ORDER BY ds_product_center_search_log_id DESC", $whereStr, $pageNo, $pageSize); + } + + public function searchProductCenterExportLog($startDt, $endDt) { + $maxId = 0; + $limit = 100; + $rows = []; + while (true) { + $tempRows = $this->db->query('SELECT * FROM ds_product_center_search_log WHERE ds_product_center_search_log_id > %i and gmt_modified > %s and gmt_modified < %s ORDER BY ds_product_center_search_log_id asc limit %i ', $maxId, $startDt, $endDt, $limit); + + $rows = array_merge($rows, (array)$tempRows); + $maxId = max(array_column($rows, 'dsProductCenterSearchLogId')); + if (count($tempRows) < $limit) { + break; + } + } + + return $rows; + } + + + public function addShopDsSyncConfig($shopId, $syncTitle, $syncPrice, $syncStock, $syncStatus) { + $update = array( + 'shop_id' => $shopId, + 'sync_title' => $syncTitle ? 1 : 0, + 'sync_stock' => $syncStock ? 1 : 0, + 'sync_price' => $syncPrice ? 1 : 0, + 'sync_status' => $syncStatus ? 1 : 0, + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + return $this->db->insertUpdate('shop_ds_sync_plan_config', $insert, $update); + } + + public function getShopDsSyncConfig($shopId) { + $syncConfig = $this->db->queryFirstRow('select sync_title as syncTitle,sync_stock as syncStock,sync_price as syncPrice,sync_status as syncStatus from shop_ds_sync_plan_config where shop_id = %i limit 1', $shopId); + if (empty($syncConfig)) { + $syncConfig = array( + 'syncTitle' => 0, + 'syncStock' => 0, + 'syncPrice' => 0, + 'syncStatus' => 0, + ); + } + + return $syncConfig; + } + + public function getDsProductData($itemId, $shopId, $site = '') { + $memberId = $this->getAlibabaMemberId($shopId); + $sourceProductDataRet = $this->dsClient->getSourceProductData($shopId, AppConst::getDsPlatform(), 0, $memberId, $itemId, $site); + if (CommonTool::isFailRet($sourceProductDataRet)) { + return $sourceProductDataRet; + } + $sourceProductData = $sourceProductDataRet['productInfo']; + $sourceProductData['isFromDs'] = true; + + return CommonTool::successResult($sourceProductData); + } + + public function getBrandNameByProductFormatNew($productFormatNew, $brandId, $shopId) { + $brandName = ''; + foreach ($productFormatNew as $attributes) { + foreach ($attributes as $attribute) { + if($attribute['propertyName'] == '品牌') { + $brandName = $attribute['name']; + break; + } + } + } + + if(empty($brandName)) { + return $this->getBrandName($brandId, $shopId); + } + + return $brandName; + } + + public function addPlatformAuth($shopId, $platformUserId, $authCode, $platform, $authShopName, $gmtExpire) { + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $update = array( + 'platform' => $platform, + 'platform_user_id' => $platformUserId, + 'auth_code_s' => CommonTool::encrypt($authCode, $platformUserId), + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + + $this->db->insertUpdate('platform_shop', $insert, $update); + + $moveAuthShopId = $this->db->queryFirstField('select move_auth_shop_id from move_auth_shop where platform = %s and shop_id = %i and auth_shop_id = %i limit 1', $platform, $shopId, $platformUserId); + + $update = array( + 'platform' => $platform, + 'auth_shop_id' => $platformUserId, + 'shop_id' => $shopId, + 'auth_shop_name' => $authShopName, + 'gmt_expire' => $gmtExpire, + 'initiator' => 0, + 'is_delete' => 0, + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + if ($moveAuthShopId) { + $this->db->update('move_auth_shop', $update, 'move_auth_shop_id = %i', $moveAuthShopId); + } else { + $this->db->insert('move_auth_shop', $insert); + } + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult('添加失败' . $ex->getMessage()); + } + + return CommonTool::successResult(); + } + + public function getAuthPlatformShopInfo($authPlatform, $authShopId) { + $platformShopInfo = $this->db->queryFirstRow('select platform_shop_id, auth_code_s from platform_shop where platform = %s and platform_user_id = %s limit 1', $authPlatform, $authShopId); + $authCodeS = $platformShopInfo['auth_code_s']; + if (empty($authCodeS)) { + return []; + } + + $platformShopInfo['authCode'] = CommonTool::decrypt($authCodeS, $authShopId); + return $platformShopInfo; + } + + public function getPlatformMoveAuthShopInfo($platform, $shopId, $authShopId) { + return $this->db->queryFirstRow('select * from move_auth_shop where platform = %s and shop_id = %i and auth_shop_id = %s', $platform, $shopId, $authShopId); + } + + public function deletePlatformAuth($post, ZcLog $logger) { + if (!$this->verifyToken($post)) { + $logger && $logger->info('---------post data-------' . print_r($post, true)); + return CommonTool::failResult('token 校验失败'); + } + $shopId = $post['shopId']; + $platform = $post['platform']; + + if (CommonTool::anyEmpty($shopId, $platform)) { + return CommonTool::failResult('参数错误'); + } + + $affect = $this->db->update('move_auth_shop', array( + 'gmt_expire' => ZcDbEval::now(), + 'is_delete' => 1, + 'gmt_modified' => ZcDbEval::now(), + ),'platform = %s and auth_shop_id = %s', $platform, $shopId); + return $affect ? CommonTool::successResult() : CommonTool::failResult('删除失败'); + } + + public function processPlatformAuthCallback($post, $logger = null) { + $appName = $post['appName']; + $shopId = $post['shopId']; + $authCode = $post['authCode']; + $platform = $post['platform']; + $authShopName = $post['authShopName']; + $gmtExpire = $post['gmtExpire']; + $platformUserId = $post['platformUserId']; + $logger && $logger->info('------post----' . print_r($post, true)); + if (!$this->verifyToken($post)) { + $logger && $logger->info('---------post data-------' . print_r($post, true)); + return CommonTool::failResult('token 校验失败'); + } + + if ($appName != Zc::C('appName')) { + return CommonTool::failResult('应用错误'); + } + + if (CommonTool::anyEmpty($shopId, $authCode, $platform, $authShopName, $gmtExpire, $platformUserId)) { + return CommonTool::failResult('参数异常'); + } + + $addPlatformAuthRet = $this->addPlatformAuth($shopId, $platformUserId, $authCode, $platform, $authShopName, $gmtExpire); + $logger && $logger->info('------$addPlatformAuthRet----' . print_r($addPlatformAuthRet, true)); + return $addPlatformAuthRet; + } + + private function verifyToken($post) { + $token = $post['token']; + unset($post['token']); + return PlatformAuthTool::getToken($post) == $token; + } + + public function lockDsAsyncNoticeTask($timerLockId, $filter) { + $where = []; + if ($filter['includeShopIds']) { + $where[] = $this->db->prepare(' and shop_id in %li', $filter['includeShopIds']); + } + if ($filter['excludeShopIds']) { + $where[] = $this->db->prepare(' and shop_id not in %li', $filter['excludeShopIds']); + } + if ($filter['type']) { + $where[] = $this->db->prepare(' and `type` = %s', $filter['type']); + } + $whereStr = $where ? implode(' ', $where) : ''; + + $shopIds = $this->db->queryFirstColumn("select `shop_id` from `ds_async_notice_task` where `locked` = 0 and gmt_exec < now() %l limit 100", $whereStr); + if (empty($shopIds)) { + return array (); + } + $shopId = $shopIds[array_rand($shopIds, 1)]; + + $queueMsg = $this->db->queryFirstRow('SELECT * FROM ds_async_notice_task WHERE `shop_id` = %i AND locked = 0', $shopId); + if (empty($queueMsg)) { + return array (); + } + + $affectRows = $this->db->update('ds_async_notice_task', array ( + 'hostname' => gethostname(), + 'locked' => $timerLockId, + 'gmt_locked' => ZcDbEval::now(), + 'gmt_last_heartbeat' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "ds_async_notice_task_id = %i AND locked = 0", $queueMsg['ds_async_notice_task_id']); + + if ($affectRows == 1) { + return $queueMsg; + } + return array (); + } + + public function sendDsSyncFailMsg($shopId, $sourceItemId, $productId, $reason, $action = '') { + if (strpos($reason, '获取token失败') !== false) { + return; + } + + if (strpos($reason, '已下架') !== false) { + return; + } + + if (empty($sourceItemId)) { + return; + } + + $msg = sprintf('同步主客信息失败,平台:抖店%s, 用户id:%d, 来源商品id:%d; 商品id : %d; 失败原因:%s; hostname:%s,预警来源:%s', AppConst::getAppChineseName(Zc::C('appName')), $shopId, $sourceItemId, $productId, $reason, gethostname(), $action); + DingTalkTool::sendMessage(DingTalkTool::dingTaskBizDsNotice, $msg, ['15280166568']); + } + + public function syncShopInfoToDs($shopId) { + $isExistDs = $this->isExistDs($shopId); + if (!$isExistDs) { + return CommonTool::successResult(); + } + + $shopInfo = $this->shopDao->getShop($shopId); + $appVersionCodeToNameMap = AppConst::getAppVersionCodeToNameMap(); + $version = $appVersionCodeToNameMap[$shopInfo['app_version']]; + + $this->dsClient->syncShopInfoToDs([ + 'gmtExpire' => $this->moveDao->getShopExpireTime($shopId), + 'version' => $version ? $version : $appVersionCodeToNameMap[AppConst::appVersionCodePaid], + 'userId' => $shopId, + 'platform' => DsConst::platformDd, + ]); + return CommonTool::successResult(); + } + + public function syncDsSaleType($queueMsg, $params, $loger) { + $loger->info('-------doProcessProductToDsItemStatusQueue---start update'); + $updateRet = $this->dsClient->updatePlatformDsItemStatus($queueMsg['shop_id'], $params['status'], $params['productId'], $params['sourceItemId'], DsConst::platformDd, Zc::C('acn.ds.domain')); + if (CommonTool::isFailRet($updateRet)) { + $updateRet['reason'] = '更新主客信息失败---' . $updateRet['reason']; + return $updateRet; + } + + return CommonTool::successResult(); + } + + public function updateDsSaleType($queueMsg, $params, $productInfo, ZcLog $loger) { + if ($params['status'] == StatusConst::delete) { + $loger->info('-------doProcessProductToDsItemStatusQueue---start delete'); + $delRet = $this->dsClient->delProductDsItem($queueMsg['shop_id'], $params['productId'], $params['sourceItemId'], DsOrderConst::getOdDomainByApp()); + if (CommonTool::isFailRet($delRet)) { + $delRet['reason'] = '删除代销失败---' . $delRet['reason']; + return $delRet; + } + } + + if ($params['status'] == StatusConst::normal) { + $loger->info('-------doProcessProductToDsItemStatusQueue---start add'); + $addRet = $this->dsClient->addProductDsItem($queueMsg['shop_id'], $params['productId'], $params['sourceItemId'], DsOrderConst::getOdDomainByApp(), $productInfo['sellerId']); + if (CommonTool::isFailRet($addRet)) { + $addRet['reason'] = '添加代销失败---' . $addRet['reason']; + return $addRet; + } + } + return CommonTool::successResult(); + } + + public function clearDsAsyncNoticeTask($queueMsg, $processRet) { + if (CommonTool::isSuccessRet($processRet) || $queueMsg['try_times'] >= 3) { + $this->addDsAsyncNoticeTaskFailLog($queueMsg, $processRet); + return $this->db->delete('ds_async_notice_task', 'ds_async_notice_task_id = %i', $queueMsg['ds_async_notice_task_id']); + } + + return $this->db->update('ds_async_notice_task', array( + 'locked' => 0, + 'gmt_exec' => date('Y-m-d H:i:s', time() + $queueMsg['try_times'] * 60), + 'try_times' => new ZcDbEval('try_times + 1'), + 'gmt_modified' => ZcDbEval::now() + ), 'ds_async_notice_task_id = %i', $queueMsg['ds_async_notice_task_id']); + } + + private function addDsAsyncNoticeTaskFailLog($queueMsg, $processRet) { + $updateRet = $this->tryUpdateDsAsyncNoticeTaskFailLogRetryResult($queueMsg['ds_async_notice_task_id'], $processRet['result'], $processRet['reason']); + if (CommonTool::isSuccessRet($processRet)) { + return; + } + + $params = json_decode($queueMsg['params'], true); + $this->sendDsSyncFailMsg($queueMsg['shop_id'], $params['sourceItemId'], $params['productId'], $processRet['reason'], $queueMsg['type']); + if (!$updateRet) { + return $this->db->insert('ds_async_notice_task_fail_log', array( + 'ds_async_notice_task_id' => $queueMsg['ds_async_notice_task_id'], + 'shop_id' => $queueMsg['shop_id'], + 'type' => $queueMsg['type'], + 'params' => $queueMsg['params'], + 'source_item_id' => $params['sourceItemId'], + 'product_id' => $params['productId'], + 'hostname' => gethostname(), + 'reason' => $processRet['reason'], + 'is_retry' => 0, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + } + + private function tryUpdateDsAsyncNoticeTaskFailLogRetryResult($taskId, $status, $reason) { + $taskId = $this->db->queryFirstField('select ds_async_notice_task_id from ds_async_notice_task_fail_log where ds_async_notice_task_id = %i limit 1', $taskId); + if ($taskId) { + return $this->db->update('ds_async_notice_task_fail_log', array( + 'hostname' => gethostname(), + 'retry_status' => $status, + 'reason' => $reason, + 'gmt_modified' => ZcDbEval::now(), + ), 'ds_async_notice_task_id = %i', $taskId); + } + + return false; + } + + public function checkPddShopUrlAuthorize($shopId, $source, $shopUrl, $mallId = '') { + if ($source != FetchClientConst::collectTaskSourcePinduoduo) { + return CommonTool::successResult(); + } + if (AppConst::isddmsV2()) { + return CommonTool::successResult(); + } + + preg_match('#(?:yangkeduo|ishangtong|pinduoduo)\.com.*mall_id=(\d+)#is', $shopUrl, $match); + $platformShopId = $mallId ?: $match[1]; + + $exist = $this->db->queryFirstField('select count(1) from move_auth_shop where platform = "authPdd" and shop_id = %i and auth_shop_id = %i ', $shopId, $platformShopId); + if ($exist) { + return CommonTool::successResult(); + } + return CommonTool::failCodeResult(ErrorCodeConst::forbidCopyPdd, '禁止复制拼多多'); + } + + public function checkPlatformAuthorize($fetchSourceList, $extSourceList = []) { + return $this->moveDao->checkPlatformAuthorize($fetchSourceList, $extSourceList); + } + + public function getAuthPlatformRealSourceUrl($productId) { + $authPlatformSourceItemInfo = $this->db->queryFirstRow('select * from auth_platform_source_item where product_id = %i', $productId); + if (empty($authPlatformSourceItemInfo)) { + return ''; + } + + return FetchClientTool::buildMoveSourceUrl($authPlatformSourceItemInfo['real_source_item_id'], $authPlatformSourceItemInfo['real_source']); + } + + public function checkShowGuide($shopId) { + $hasDsLog = $this->db->queryFirstField('select 1 from move_collect_task_detail_ds_log where shop_id = %i limit 1', $shopId); + if ($hasDsLog) { + return false; + } + + $hasGuide = $this->db->queryFirstField('select 1 from shop_tip_log where shop_id = %i and ds_guide = 1 limit 1', $shopId); + if ($hasGuide) { + return false; + } + + return true; + } + + public function getMoveProductSourceItemInfo($productId, $shopId) { + return $this->db->queryFirstRow('SELECT mctd.`source_item_id`, mctd.`source`, mctd.`site`, mctd.`source_shop_name` FROM `move_collect_task_detail` AS mctd INNER JOIN `move_product_log` AS mwl USING(`move_collect_task_detail_id`) WHERE mwl.product_id = %i AND mwl.shop_id = %i', $productId, $shopId); + } + + public function lockMoveCancelTaskQueue($timerLockId, $filter) { + $whereArr = []; + if (!empty($filter['includeShopIds'])) { + $whereArr[] = $this->db->prepare('AND shop_id in %li', $filter['includeShopIds']); + } + if (!empty($filter['excludeShopIds'])) { + $whereArr[] = $this->db->prepare('AND shop_id NOT IN %li', $filter['excludeShopIds']); + } + + $whereStr = implode(' ', $whereArr); + $queueMsg = $this->db->queryFirstRow('select * from move_cancel_task_queue where locked = 0 %l limit 1', $whereStr); + if (!empty($queueMsg)) { + $affRows = $this->db->update('move_cancel_task_queue', [ + 'locked' => $timerLockId, + 'hostname' => gethostname(), + 'gmt_locked' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ], 'move_cancel_task_queue_id = %i AND locked = 0', $queueMsg['move_cancel_task_queue_id']); + if ($affRows) { + $queueMsg['locked'] = $timerLockId; + return $queueMsg; + } + } + + return []; + } + + public function doProcessMoveCancelTaskQueue($queueMsg) { + $logger = Zc::getLog('timer/move/processCancelTask'); + $shopId = $queueMsg['shop_id']; + $cid = $queueMsg['cid']; + $reason = $queueMsg['reason']; + + $moveTaskDetailIds = $this->getShopTaskProcessingTaskDetailIds($shopId, $cid); + if (!empty($moveTaskDetailIds)) { + // 增加自定义前缀,便于区分 + $failReason = 'client:' . $reason; + list($successCancelDetailIds, $skipCancelDetailIds) = $this->cancelCollectTask($shopId, $moveTaskDetailIds, StatusConst::fail, $failReason); + $processCount = count($successCancelDetailIds); + $logger->info("------processCount-------{$processCount}"); + } + + return CommonTool::successResult(); + } + + private function getShopTaskProcessingTaskDetailIds($shopId, $cid = null) { + $publishBufferDetailIds = $this->db->queryFirstColumn("SELECT move_collect_task_detail_id FROM move_product_publish_buffer WHERE shop_id = %i", $shopId); + $publishQueueDetailIds = $this->db->queryFirstColumn("SELECT move_collect_task_detail_id FROM move_product_publish_queue WHERE shop_id = %i", $shopId); + + $detailIds = array_merge($publishBufferDetailIds, $publishQueueDetailIds); + $detailIds = array_unique($detailIds); + + if ($cid > 0 && !empty($detailIds)) { + $detailIds = $this->db->queryFirstColumn("SELECT move_collect_task_detail_id FROM move_collect_task_detail WHERE move_collect_task_detail_id IN %li AND shop_id = %i AND cid = %i", $detailIds, $shopId, $cid); + } + + return $detailIds; + } + + public function clearMoveCancelTaskQueue($queueMsg) { + return $this->db->delete('move_cancel_task_queue', 'move_cancel_task_queue_id = %i and locked > 0', $queueMsg['move_cancel_task_queue_id']); + } + + public function checkShopHasDefaultSetting($shopId) { + return $this->db->queryFirstField('select 1 from move_shop_setting where shop_id = %i and is_config_default = 1 limit 1', $shopId); + } + + public function logSkipSystemModalInfo($shopId, $post) { + return $this->db->useDbIdOnce('ac')->insert('skip_system_log', array( + 'shop_id' => $shopId, + 'source' => $post['source'], + 'site' => $post['site'], + 'source_item_id' => $post['sourceItemId'], + 'source_title' => $post['sourceTitle'], + 'source_img_url' => $post['sourceImgUrl'], + 'source_shop_name' => $post['sourceShopName'], + 'hit_type' => $post['hitType'], + 'hit_word' => $post['hitWord'], + 'source_brand' => $post['sourceBrand'], + 'field' => $post['field'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + + public function lockPlatformAsyncNoticeTask($timerLockId, $filter) { + $where = ''; + if ($filter['includeShopIds']) { + $where = $this->db->prepare('and shop_id in %li', $filter['includeShopIds']); + } + if ($filter['excludeShopIds']) { + $where = $this->db->prepare('and shop_id not in %li', $filter['excludeShopIds']); + } + + $queueMsg = $this->db->queryFirstRow('SELECT * FROM platform_async_notice_task WHERE locked = 0 and gmt_exec < now() %l', $where); + if (empty($queueMsg)) { + return array (); + } + + $affectRows = $this->db->update('platform_async_notice_task', array ( + 'hostname' => gethostname(), + 'locked' => $timerLockId, + 'gmt_locked' => ZcDbEval::now(), + 'gmt_last_heartbeat' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ), "platform_async_notice_task_id = %i AND locked = 0", $queueMsg['platform_async_notice_task_id']); + + if ($affectRows == 1) { + return $queueMsg; + } + return array (); + } + + public function doProcessPlatformAsyncNoticeTask($queueMsg) { + $params = json_decode($queueMsg['params'], true); + + $ret = ''; + switch ($queueMsg['type']) { + case MoveConst::platformAsyncNoticeTaskTypePlatformAuthMove : + $ret = $this->processPlatformAuthMoveSyncData($params); + break; + } + + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + return $ret; + } + + private function processPlatformAuthMoveSyncData($params) { + $authPlatformShopInfo = $this->getAuthPlatformShopInfo($params['authPlatform'], $params['authPlatformUserId']); + $authCode = $authPlatformShopInfo['authCode']; + $applyPlatform = FetchClientConst::collectTaskSourceAuthDd; + + $retJson = PlatformAuthDataTool::addMoveAuthPlatformProductLog($applyPlatform, $authCode, $params['authPlatform'], $params['authPlatformItemId'], $params['applyPlatformMoveCollectTaskDetailId'], $params['applyPlatformItemId'], $params['applyPlatformUserId'], $params['status']); + return json_decode($retJson, true); + } + + public function clearPlatformAsyncNoticeTask($queueMsg, $processRet) { + if (CommonTool::isSuccessRet($processRet) || $queueMsg['try_times'] > 10) { + return $this->db->delete('platform_async_notice_task', 'platform_async_notice_task_id = %i', $queueMsg['platform_async_notice_task_id']); + } + + return $this->db->update('platform_async_notice_task', array( + 'locked' => 0, + 'gmt_exec' => date('Y-m-d H:i:s', time() + $queueMsg['try_times'] * 60), + 'try_times' => new ZcDbEval('try_times + 1'), + 'gmt_modified' => ZcDbEval::now() + ), 'platform_async_notice_task_id = %i', $queueMsg['platform_async_notice_task_id']); + } + + public function getTaskDetailIndexByMoveTaskId($moveTaskId, $moveTaskDetailId){ + $sql = 'SELECT move_collect_task_detail_id FROM move_collect_task_detail WHERE move_collect_task_id = %i ORDER BY move_collect_task_detail_id ASC'; + $arr = $this->db->query($sql, $moveTaskId); + if(empty($arr)){ + return 0; + } + return array_search($moveTaskDetailId, array_column($arr, 'move_collect_task_detail_id')); + } + + public function getShopBrandIdAndNameByBrandName($cid, $shopId, $brandName) { + return $this->db->queryFirstRow('select * from shop_category_brand where shop_id = %i and category_id = %i and brand_name like %ss', $cid, $shopId, $brandName); + } + + public function getShopPlatformAuthUuidCode($shopId, $platformUserId, $platform, $gmtExpire) { + $authCode = $this->db->queryFirstField('select auth_code from shop_to_auth_platform where platform = %s and shop_id = %i limit 1', $platform, $shopId); + if (empty($authCode)) { + $authCode = md5(Zc::C('platformAuthToken') . $shopId . $platform); + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $update = array( + 'shop_id' => $shopId, + 'platform' => $platform, + 'auth_code' => $authCode, + 'gmt_expire' => $gmtExpire, + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + $this->db->insertUpdate('shop_to_auth_platform', $insert, $update); + + $update = array( + 'shop_id' => $shopId, + 'platform' => $platform, + 'platform_user_id' => $platformUserId, + 'gmt_expire' => $gmtExpire, + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + $this->db->insertUpdate('shop_to_auth_platform_user', $insert, $update); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return ''; + } + + return $authCode; + } + + public function getAuthShopPlatformUserId($shopId, $platform, $applyPlatformUserId) { + return $this->db->queryFirstField('select platform_user_id from shop_to_auth_platform_user where shop_id = %i and platform = %s and platform_user_id = %s limit 1', $shopId, $platform, $applyPlatformUserId); + } + + public function addMoveAuthPlatformProductLog($applyPlatform, $applyPlatformUserId, $applyPlatformProductId, $applyMoveCollectTaskDetailId, $shopId, $productId, $status) { + $insert = array( + 'platform' => $applyPlatform, + 'platform_user_id' => $applyPlatformUserId, + 'platform_product_id' => $applyPlatformProductId, + 'platform_move_collect_task_detail_id' => $applyMoveCollectTaskDetailId, + 'shop_id' => $shopId, + 'product_id' => $productId, + 'status' => $status, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + $update = $insert; + unset($update['gmt_create']); + + $addRet = $this->db->insertUpdate('move_auth_platform_product_log', $insert, $update); + return $addRet ? CommonTool::successResult() : CommonTool::failResult('添加失败'); + } + public function addMoveCollectTaskDetailCategoryLog($shopId, $moveCollectTaskDetailId, $sourceCategoryPath, $finalMoveCid, $systemMatchCid, $useRecommendCid, $productDetailBase, $accessToken) { + $apiMatchCidLog = $this->getApiMatchCidLog($productDetailBase, $accessToken); + $insert = array( + 'shop_id' => $shopId, + 'move_collect_task_detail_id' => $moveCollectTaskDetailId, + 'source_category_path' => $sourceCategoryPath, + 'final_move_cid' => $finalMoveCid, + 'system_match_cid' => $systemMatchCid, + 'use_recommend_cid' => $useRecommendCid, + 'api_match_cid_log' => is_array($apiMatchCidLog) ? json_encode($apiMatchCidLog) : $apiMatchCidLog, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + $update = $insert; + unset($update['gmt_create']); + + return $this->db->insertUpdate('move_collect_task_detail_category_log', $insert, $update); + } + + public function addMoveShopRequiredSizeTemplate($shopId, $finalMoveCid, $addProductRet) { + if (CommonTool::isSuccessRet($addProductRet) || strpos($addProductRet['reason'], '该类目商品需上传完整尺码表信息') === false) { + return true; + } + $update = array( + 'shop_id' => $shopId, + 'cid' => $finalMoveCid, + 'gmt_modified' => ZcDbEval::now(), + ); + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + return $this->db->insertUpdate('move_shop_required_size_template', $insert, $update); + } + + public function getShopRequiredSizeTemplateCids($shopId, $cids) { + if (empty($cids)) { + return []; + } + + return $this->db->queryFirstColumn('select cid from move_shop_required_size_template where shop_id = %i and cid in %li', $shopId, $cids); + } + + private function getApiMatchCidLog($productDetailBase, $accessToken) { + $productInfoMatchLog = $this->getApiMatchProductInfoLog($productDetailBase, $accessToken); + $productInfoMatchLog = $this->getApiMatchSmartPublishLog($productDetailBase, $productInfoMatchLog, $accessToken); + return $productInfoMatchLog; + } + + private function getApiMatchProductInfoLog($productDetailBase, $accessToken) { + $productDetailBase['name'] = $productDetailBase['title']; + $ret = $this->productGetRecommendCategory(ProductConst::sceneTypeProductInfo, $productDetailBase, $accessToken); + if (CommonTool::isFailRet($ret)) { + return []; + } + $categoryDetails = $ret['categoryDetails']; + if (empty($categoryDetails)) { + return []; + } + + return $this->getProductLeafCateAndPathMap($categoryDetails); + } + + private function getProductLeafCateAndPathMap($categoryDetails, $leafCateAndPathMap = []) { + foreach ($categoryDetails as $categoryDetail) { + $cid = $this->productDao->getProductLeafCate($categoryDetail); + $path = $this->productDao->getProductCatePath($categoryDetail); + $leafCateAndPathMap[$cid] = array( + 'cid' => $cid, + 'path' => $path, + ); + } + + return $leafCateAndPathMap; + } + + private function getApiMatchSmartPublishLog($productDetailBase, $productInfoMatchLog, $accessToken) { + $pic = []; + $mainImgUrls = explode('|', $productDetailBase['mainImgUrls']); + foreach ($mainImgUrls as $imgUrl) { + $pic[] = array( + 'url' => $imgUrl + ); + } + + $ret = $this->productGetRecommendCategory(ProductConst::sceneTypeSmartPublish, array('pic' => $pic), $accessToken); + if (CommonTool::isFailRet($ret)) { + return $productInfoMatchLog; + } + $categoryDetails = $ret['categoryDetails']; + if (empty($categoryDetails)) { + return $productInfoMatchLog; + } + + return $this->getProductLeafCateAndPathMap($categoryDetails, $productInfoMatchLog); + } + + public function productGetRecommendCategory($scene, $params, $accessToken) { + $req = new ProductGetRecommendCategoryRequest(); + $req->setScene($scene); + if ($params['pic']) { + $req->setPic($params['pic']); + } + if ($params['categoryLeafId']) { + $req->setCategoryLeafId($params['categoryLeafId']); + } + if ($params['name']) { + $req->setName($params['name']); + } + if ($params['productFormatNew']) { + $req->setProductFormatNew($params['productFormatNew']); + } + if ($params['standardBrandId']) { + $req->setStandardBrandId($params['standardBrandId']); + } + + $ret = $this->dd->execute($req, $accessToken); + $checkRet = CommonTool::checkDdApiRetStatus($ret); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + return CommonTool::successResult('categoryDetails', $ret['data']['categoryDetails']); + } + + public function saveTaskFailLog($shopId, $request, $server, $ip, $type) { + $this->db->useDbIdOnce('ac')->insert('save_task_fail_log', [ + 'shop_id' => $shopId, + 'type' => $type, + 'params' => json_encode(['request' => $request, 'server' => $server]), + 'ip' => $ip, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]); + } + + public function rebuildTaskDetailCategoryMatch($taskDetailList) { + $detailIds = ZcArrayHelper::getSub($taskDetailList, 'move_collect_task_detail_id'); + if (empty($detailIds)) { + return $taskDetailList; + } + + $categoryLogList = $this->db->query('select * from move_collect_task_detail_category_log where move_collect_task_detail_id in %li', $detailIds); + $categoryLogList = ZcArrayHelper::changeKeyRow($categoryLogList, 'move_collect_task_detail_id'); + + $finalMoveCids = ZcArrayHelper::getSub($categoryLogList, 'final_move_cid'); + $systemMatchCids = ZcArrayHelper::getSub($categoryLogList, 'system_match_cid'); + $cids = array_unique(CommonTool::safeArrayMerge($finalMoveCids, $systemMatchCids)); + + $allCidAndMameMap = $this->getCidAndPathMap($cids); + + foreach ($taskDetailList as &$taskDetail) { + $categoryMatchLog = $categoryLogList[$taskDetail['move_collect_task_detail_id']]; + if (empty($categoryMatchLog)) { + continue; + } + $finalMoveCid = $categoryMatchLog['final_move_cid']; + $categoryMatchLog['finalMoveCategoryPath'] = $allCidAndMameMap[$finalMoveCid]; + $systemMoveCid = $categoryMatchLog['system_match_cid']; + $categoryMatchLog['systemMoveCategoryPath'] = $allCidAndMameMap[$systemMoveCid]; + $categoryMatchLog['api_match_cid_log'] = json_decode($categoryMatchLog['api_match_cid_log'], true); + $taskDetail['categoryMatchLog'] = $categoryMatchLog; + } + + return $taskDetailList; + } + + public function getCidAndPathMap($cids) { + if (empty($cids)) { + return []; + } + + $categoryList = $this->db->query('select category_id, path from category_v2 where category_id in %li', $cids); + return ZcArrayHelper::mapNameValue($categoryList, 'category_id', 'path'); + } + + public function appendCatePah($dataList, $cidName = 'cid') { + if (!$dataList) { + return $dataList; + } + $cids = array_unique(array_column($dataList, $cidName)); + $cidAndPathMap = $this->getCidAndPathMap($cids); + foreach ($dataList as &$data) { + $data['catePath'] = $cidAndPathMap[$data[$cidName]]; + } + return $dataList; + } + + public function saveSameProductCopyLog($sameType, $searchSameProductMap, $shopId, $isDs) { + $inserts = []; + $allNum = count($searchSameProductMap); + $index = 0; + foreach ($searchSameProductMap as $productInfo) { + $index++; + $sourceItemInfo = $productInfo; + unset($sourceItemInfo['sameWareList']); + $sameWareList = $productInfo['sameWareList']; + + $inserts[] = [ + 'shop_id' => $shopId, + 'same_type' => $sameType, + 'source_product_info' => json_encode($sourceItemInfo), + 'same_product_info' => json_encode($sameWareList ?: []), + 'index' => $index, + 'is_ds' => $isDs, + 'all_num' => $allNum, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]; + } + + $this->db->useDbIdOnce('ac')->insert('move_same_product_log', $inserts); + } + + public function appendMovedInfoToSourceItemList($sourceItemList, $shopId) { + $sourceItemMap = array_column($sourceItemList, null, 'sourceItemId'); + + $existIds = $this->db->queryFirstColumn('select source_item_id from move_collect_task_detail where shop_id = %i and source = %s and source_item_id in %ls', $shopId, FetchClientConst::collectTaskSourceTaote, array_keys($sourceItemMap)); + foreach ($existIds as $existId) { + $sourceItemMap[$existId]['isMoved'] = true; + } + return $sourceItemMap; + } + + public function searchSameProductCopyLog($search, $currPageNo, $pageSize){ + $where = []; + if ($search['shopId']) { + $where[] = $this->db->prepare('and shop_id in %li', $search['shopId']); + } + if ($search['sameType']) { + $where[] = $this->db->prepare('and same_type = %s', $search['sameType']); + } + if (strlen($search['isDs']) > 0) { + $where[] = $this->db->prepare('and is_ds = %i', $search['isDs']); + } + $whereStr = implode(' ', $where); + + list($sameProductCopyLogs, $total) = $this->db->useDbIdOnce('ac')->queryPage('select * from move_same_product_log where 1 %l order by move_same_product_log_id desc', $whereStr, $currPageNo, $pageSize); + + foreach ($sameProductCopyLogs as &$sameProductCopyLog) { + $sameProductCopyLog['source_product_info'] = json_decode($sameProductCopyLog['source_product_info'], true) ?: []; + $sameProductCopyLog['same_product_info'] = json_decode($sameProductCopyLog['same_product_info'], true) ?: []; + $isSelects = array_column($sameProductCopyLog['same_product_info'], 'isSelect'); + array_multisort($isSelects, SORT_DESC, $sameProductCopyLog['same_product_info']); + + unset($sameProductCopyLog); + } + + return [$sameProductCopyLogs, $total]; + } + + public function createSpuToDd($shopId, $createSpuInfo, $accessToken) { + $req = new SpuCreateSpuRequest(); + if ($createSpuInfo['cid']) { + $req->setCategoryLeafId($createSpuInfo['cid']); + } + + if ($createSpuInfo['materials']) { + $req->setMaterials($createSpuInfo['materials']); + } + + if($createSpuInfo['proofs']) { + $req->setProofs($createSpuInfo['proofs']); + } + + if ($createSpuInfo['spuPropertyInfos']) { + $req->setPropertyInfos($createSpuInfo['spuPropertyInfos']); + } + $resp = $this->dd->execute($req, $accessToken); + $checkRet = CommonTool::checkDdApiRetStatus($resp); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + $logInfo = $createSpuInfo; + $logInfo['shopId'] = $shopId; + $logInfo['spuId'] = $resp['data']['spu_id']; + $this->addCreateSpuLog($logInfo); + + return CommonTool::successResult('spuId', $resp['data']['spu_id']); + } + + private function addCreateSpuLog($logInfo) { + $isbn = $bookName = null; + foreach ($logInfo['spuPropertyInfos'] as $propInfo) { + if ($propInfo['property_name'] == 'ISBN编号') { + $isbn = $propInfo['values'][0]['value_name']; + } elseif ($propInfo['property_name'] == '书名') { + $bookName = $propInfo['values'][0]['value_name']; + } + } + return $this->db->insert('create_spu_log', [ + 'shop_id' => $logInfo['shopId'], + 'spu_id' => $logInfo['spuId'], + 'cid' => $logInfo['cid'], + 'isbn' => $isbn, + 'book_name' => $bookName, + 'spu_images' => json_encode($logInfo['spuImages']), + 'spu_actual_images' => json_encode($logInfo['spuActualImages']), + 'property_infos' => json_encode($logInfo['spuPropertyInfos']), + 'status' => StatusConst::spuStatusAuditing, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ]); + } + + public function createSpu($shopId, $post, $accessToken) { + if (empty($post['cid'])) { + return CommonTool::failResult('未知类目'); + } + $cid = $post['cid']; + $spuRuleRet = $this->getSpuRuleFromDd($cid, $accessToken); + if (CommonTool::isFailRet($spuRuleRet)) { + return $spuRuleRet; + } + $spuRule = $spuRuleRet['ruleInfo']; + if (!$spuRule['support_create_spu']) { + return CommonTool::failResult('该类目不能发布SPU'); + } + + $data = [ + 'cid' => $cid, + ]; + foreach ($spuRule['spu_property_rule'] as $propRule) { + $propertyName = $propRule['property_name']; + if (!isset($post['props'][$propertyName]) || (is_string($post['props'][$propertyName]) && (trim($post['props'][$propertyName]) == ''))) { + if ($propRule['is_required']) { + return CommonTool::failResult("请填写属性:$propertyName"); + } + continue; + } + + $values = []; + foreach ((array)$post['props'][$propertyName] as $postValue) { + $postValue = trim($postValue); + if (in_array($propRule['value_type'], [MoveConst::attrInputTypeSelect, MoveConst::attrInputTypeMultiSelect, MoveConst::attrInputTypeSearch])) { + if (!$postValue) { + continue; + } + $optionMap = array_column($propRule['values'], 'value_name', 'value_id'); + if (!isset($optionMap[$postValue]) && $propertyName !== '品牌') { + return CommonTool::failResult("属性名[$propertyName]未知值[$postValue]"); + } + $item = [ + 'value_id' => $postValue, + 'value_name' => $optionMap[$postValue], + ]; + if($propertyName == '品牌') { + $item['value_name'] = $post['brandName']; + } + $values[] = $item; + } else { + $values[] = [ + 'value_id' => 0, + 'value_name' => $postValue, + ]; + } + } + + if ($values) { + $data['spuPropertyInfos'][] = [ + 'property_id' => $propRule['property_id'], + 'property_name' => $propertyName, + 'values' => $values, + ]; + } + } + + $ret = $this->checkSpuImgs('标品主图', $post['spu_images'], $spuRule['spu_images_rule'], $accessToken); + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + $materialsList = []; + foreach ($spuRule['spu_material_rules'] as $rule) { + if ($rule['material_type'] == 1) { + $content = []; + foreach ($ret['imgUrls'] as $index => $spuImage) { + $content[] = [ + 'content' => $spuImage, + 'name' => $rule['material_rule']['name'] . $index + ]; + } + $materialsList[] = [ + 'type' => $rule['material_type'], + 'name' => $rule['material_rule']['name'], + 'description' => '该图用于标品主图', + 'content' => $content + ]; + + break; + } + } + + $data['materials'] = $materialsList; + + $ret = $this->checkSpuImgs('版权页图片', $post['spu_actual_images'], $spuRule['spu_actual_images_rule'], $accessToken); + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + $proofsList = []; + foreach ($spuRule['spu_proof_rules'] as $rule) { + if ($rule['proof_type'] == 6) { + $content = []; + foreach ($ret['imgUrls'] as $index => $spuActualImage) { + $content[] = [ + 'content' => $spuActualImage, + 'name' => $rule['proof_rule']['name'] . $index + ]; + } + $proofsList[] = [ + 'type' => $rule['proof_type'], + 'name' => $rule['proof_rule']['name'], + 'description' => '该图用于版权页图片', + 'content' => $content + ]; + + break; + } + } + + $data['proofs'] = $proofsList; + + return $this->createSpuToDd($shopId, $data, $accessToken); + } + + + public function getSpuProofRules($ruleInfo, $baseData, $accessToken) { + $proofsList = []; + foreach ($ruleInfo['spu_proof_rules'] as $rule) { + if($rule['proof_rule']['is_required']) { + $spuImages = array_slice($baseData['image_paths'], 0, $rule['proof_rule']['max_num']); + $uploadSpuActualImagesRet = $this->uploadSpuImgToDd($spuImages, $accessToken); + if (CommonTool::isFailRet($uploadSpuActualImagesRet)) { + continue; + } + $spuActualImages = array_column($uploadSpuActualImagesRet['success_list'], 'spu_url'); + $content = []; + foreach ($spuActualImages as $index => $spuActualImage) { + $content[] = [ + 'content' => $spuActualImage, + 'name' => $rule['proof_rule']['name'] . $index + ]; + } + $proofsList[] = [ + 'type' => $rule['proof_type'], + 'name' => $rule['proof_rule']['name'], + 'description' => '该图用于' . $baseData['title'], + 'content' => $content + ]; + } + } + + return $proofsList; + } + + public function getSpuMaterialsRules($ruleInfo, $baseData, $accessToken) { + $materialsList = []; + foreach ($ruleInfo['spu_material_rules'] as $rule) { + if ($rule['material_rule']['is_required']) { + $spuImages = array_slice($baseData['image_paths'], 0, $rule['material_rule']['max_num']); + $uploadSpuImagesRet = $this->uploadSpuImgToDd($spuImages, $accessToken); + if (CommonTool::isFailRet($uploadSpuImagesRet)) { + continue; + } + $spuImages = array_column($uploadSpuImagesRet['success_list'], 'spu_url'); + $content = []; + foreach ($spuImages as $index => $spuImage) { + $content[] = [ + 'content' => $spuImage, + 'name' => $rule['material_rule']['name'] . $index + ]; + } + $materialsList[] = [ + 'type' => $rule['material_type'], + 'name' => $rule['material_rule']['name'], + 'description' => '该图用于' . $baseData['title'], + 'content' => $content + ]; + } + } + + return $materialsList; + } + + private function checkSpuImgs($labelName, $imgUrls, $rule, $accessToken) { + if ($rule['is_required'] && !$imgUrls) { + return CommonTool::failResult("请上传{$labelName}"); + } + $newImgUrls = []; + if ($imgUrls) { + $imgCount = count($imgUrls); + if ($imgCount < $rule['min_num']) { + return CommonTool::failResult("请至少上传{$rule['min_num']}张{$labelName}"); + } + if ($imgCount > $rule['max_num']) { + return CommonTool::failResult("最多只能上传{$rule['max_num']}张{版权页图片}"); + } + + $uploadSpuImagesRet = $this->uploadSpuImgToDd($imgUrls, $accessToken); + if (CommonTool::isFailRet($uploadSpuImagesRet)) { + return $uploadSpuImagesRet; + } + $newImgUrls = array_column($uploadSpuImagesRet['success_list'], 'spu_url'); + } + + return CommonTool::successResult([ + 'imgUrls' => $newImgUrls + ]); + } + + public function getCreateSpuLog($shopId, $logId) { + $logInfo = $this->db->queryFirstRow('select spu_id, property_infos, status, reason from create_spu_log where shop_id = %i and create_spu_log_id = %i', $shopId, $logId); + if ($logInfo) { + $logInfo['property_infos'] = json_decode($logInfo['property_infos'], true); + } + return $logInfo; + } + + public function getCreateSpuLogList($filter, $page, $pageSize) { + $whereArr = []; + if ($filter['shopId']) { + $whereArr[] = $this->db->prepare('and `shop_id` = %i', $filter['shopId']); + } + if ($filter['status']) { + $whereArr[] = $this->db->prepare('and `status` = %i', $filter['status']); + } + if ($filter['isbn']) { + $whereArr[] = $this->db->prepare('and `isbn` = %s', $filter['isbn']); + } + if ($filter['bookName']) { + $whereArr[] = $this->db->prepare('and `book_name` like %ss', $filter['bookName']); + } + if ($filter['startDt']) { + $whereArr[] = $this->db->prepare('and `gmt_create` >= %s', $filter['startDt']); + } + if ($filter['endDt']) { + $whereArr[] = $this->db->prepare('and `gmt_create` <= %s', $filter['endDt']); + } + return $this->db->queryPage('select shop_id, spu_id, cid, isbn, book_name, status, gmt_create from create_spu_log where 1 %l order by create_spu_log_id desc', implode(' ', $whereArr), $page, $pageSize); + } + + public function checkSpuStatus($log) { + $log->info('start'); + $startLogId = 0; + $startDt = date('Y-m-d', strtotime('-7 day')); + $limit = 500; + $shopAccessTokenMap = []; + do { + $log->info("startLogId[$startLogId]"); + $logList = $this->db->query('select create_spu_log_id, shop_id, spu_id from create_spu_log where status = %s and gmt_create > %s and create_spu_log_id > %i order by create_spu_log_id asc limit %i', StatusConst::spuStatusAuditing, $startDt, $startLogId, $limit); + if (!$logList) { + break; + } + foreach ($logList as $logInfo) { + if (!isset($shopAccessTokenMap['shop_id'])) { + $shopInfo = $this->shopDao->getShop($logInfo['shop_id']); + $shopAccessTokenMap['shop_id'] = $shopInfo['access_token']; + } + $ret = $this->getSpuAuditInfoFromDd($logInfo['spu_id'], $shopAccessTokenMap['shop_id']); + if (CommonTool::isFailRet($ret)) { + $log->info('getSpuAuditInfoFromDd fail:' . json_encode([$logInfo, $ret])); + continue; + } + if ($ret['auditInfo']['spu_status'] != StatusConst::spuStatusAuditing) { + $res = $this->db->update('create_spu_log', [ + 'status' => $ret['auditInfo']['spu_status'], + 'reason' => $ret['auditInfo']['reject_reason'], + 'gmt_modified' => ZcDbEval::now(), + ], 'create_spu_log_id = %i', $logInfo['create_spu_log_id']); + if (!$res) { + $log->info('update create_spu_log fail:' . json_encode([$logInfo, $ret])); + } + } + } + + $startLogId = $logInfo['create_spu_log_id']; + } while (count($logList) == $limit); + $log->info('end'); + } + + public function statCreateSpuLog($log) { + $log->info('start'); + $yesterdayStart = date('Y-m-d', strtotime('-1 day')); + $yesterdayEnd = $yesterdayStart . ' 23:59:59'; + $statList = $this->db->query('select shop_id, count(*) create_total, sum(case status when %i then 1 else 0 end) online_total from create_spu_log where gmt_create >= %s and gmt_create <= %s group by shop_id', StatusConst::spuStatusOnline, $yesterdayStart, $yesterdayEnd); + foreach ($statList as $stat) { + $res = $this->db->insertUpdate('create_spu_stat', [ + 'shop_id' => $stat['shop_id'], + 'create_total' => $stat['create_total'], + 'online_total' => $stat['online_total'], + 'gmt_modified' => date('Y-m-d H:i:s'), + 'gmt_create' => date('Y-m-d H:i:s'), + ], [ + 'create_total' => new ZcDbEval('create_total + ' . $stat['create_total']), + 'online_total' => new ZcDbEval('online_total + ' . $stat['online_total']), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]); + $stat['res'] = $res; + $log->info(json_encode($stat)); + } + $log->info('end'); + } + + public function getSpuCreateSpuStatList($filter, $page, $pageSize) { + $whereArr = []; + if ($filter['shopId']) { + $whereArr[] = $this->db->prepare('and `shop_id` = %i', $filter['shopId']); + } + if ($filter['startDt']) { + $whereArr[] = $this->db->prepare('and `gmt_create` >= %s', $filter['startDt']); + } + if ($filter['endDt']) { + $whereArr[] = $this->db->prepare('and `gmt_create` <= %s', $filter['endDt']); + } + list($rangeStatList, $total) = $this->db->queryPage('select shop_id, count(*) range_create_total from create_spu_log where 1 %l group by shop_id order by range_create_total desc', implode(' ', $whereArr), $page, $pageSize); + if ((count($rangeStatList) == 1) && !$rangeStatList[0]['shop_id']) { + $rangeStatList = []; + } + if ($rangeStatList) { + $shopIds = array_column($rangeStatList, 'shop_id'); + $statList = $this->db->query('select shop_id, create_total, online_total from create_spu_stat where shop_id in %li', $shopIds); + $statList = array_column($statList, null, 'shop_id'); + foreach ($rangeStatList as &$stat) { + $stat['create_total'] = isset($statList[$stat['shop_id']]['create_total']) ? $statList[$stat['shop_id']]['create_total'] : $stat['range_create_total']; + $stat['online_total'] = isset($statList[$stat['shop_id']]['online_total']) ? $statList[$stat['shop_id']]['online_total'] : 0; + } + } + return [$rangeStatList, $total]; + } + + public function getSpuListByIsbn($shopId, $isbn, $accessToken, $cid = null) { + $spuListRet = $this->getSpuListByIsbnFromDd($isbn, $accessToken, $cid); + + $where = ''; + if ($cid) { + $where .= $this->db->prepare(' and cid = %i', $cid); + } + $shopSpuList = $this->db->query('select create_spu_log_id, spu_id, book_name, cid category_leaf_id, status, reason from create_spu_log where status != %s and shop_id = %i and isbn = %s %l order by create_spu_log_id desc limit 100', StatusConst::spuStatusOnline, $shopId, $isbn, $where); + + $result = []; + foreach ($spuListRet['spuList'] as $spu) { + $key = implode('_', [$spu['category_leaf_id'], $spu['book_name']]); + $spu['status'] = StatusConst::spuStatusOnline; + $result[$key] = $spu; + } + + foreach ($shopSpuList as $shopSpu) { + $key = implode('_', [$shopSpu['category_leaf_id'], $shopSpu['book_name']]); + if (!isset($result[$key])) { + $result[$key] = $shopSpu; + } + } + + return $result; + } + + public function getSpuListByIsbnFromDd($isbn, $accessToken, $cid = null) { + $req = new SpuQueryBookNameByISBNRequest(); + $req->setIsbn($isbn); + $req->setPageNo(0); + $req->setPageSize(100); + if ($cid) { + $req->setCategoryLeafId($cid); + } + + $ret = $this->dd->execute($req, $accessToken); + $checkRet = CommonTool::checkDdApiRetStatus($ret); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + return CommonTool::successResult('spuList', $ret['data']['data']); + } + + public function getSpuFromDd($cid, $keyProperties, $spuId, $accessToken) { + $req = new SpuGetSpuRequest(); + $req->setCid($cid); + if ($keyProperties) { + $req->setKeyProperties($keyProperties); + } + + if ($spuId) { + $req->setSpuId($spuId); + } + $resp = $this->dd->execute($req, $accessToken); + $checkRet = CommonTool::checkDdApiRetStatus($resp); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + return CommonTool::successResult('spuInfo', $resp['data']); + } + + public function getSpuAuditInfoFromDd($spuId, $accessToken) { + $req = new SpuGetAuditInfoRequest(); + $req->setSpuId($spuId); + $resp = $this->dd->execute($req, $accessToken); + $checkRet = CommonTool::checkDdApiRetStatus($resp); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + return CommonTool::successResult('auditInfo', $resp['data']); + } + + public function uploadSpuImgToDd($urls, $accessToken) { + $imgInfos = []; + foreach ($urls as $url) { + $imgInfos[] = [ + 'name' => uniqid(), + 'url' => $url, + ]; + } + $req = new SpuBatchUploadImgRequest(); + $req->setImageUrlList($imgInfos); + $resp = $this->dd->execute($req, $accessToken); + + $checkRet = CommonTool::checkDdApiRetStatus($resp); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + return CommonTool::successResult($resp['data']); + } + + public function getSpuRuleFromDd($cid, $accessToken, $useCache = true) { + if ($useCache && ($cache = $this->getSpuRuleFromCache($cid))) { + return CommonTool::successResult('ruleInfo', $cache['data']); + } + + $req = new SpuGetSpuRuleRequest(); + $req->setCid((int)$cid); + $resp = $this->dd->execute($req, $accessToken); + + $checkRet = CommonTool::checkDdApiRetStatus($resp); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + $this->setCategoryAttrV2Cache($cid, $resp); + return CommonTool::successResult('ruleInfo', $resp['data']); + } + + private function getSpuRuleFromCache($cid) { + $cacheFile = $this->getSpuRuleCacheFile($cid); + if (!file_exists($cacheFile)) { + return null; + } + $cache = json_decode(file_get_contents($cacheFile), true); + if (!$cache || ($cache['create_time'] < time() - 3600)) { + return null; + } + return $cache['data']; + } + + private function getSpuRuleCacheFile($cid) { + return Zc::C(ZcConfigConst::LogDir) . 'cache/move/spu_rule_' . $cid . '.json'; + } + + private function setCategoryAttrV2Cache($cid, $data) { + $cacheFile = $this->getSpuRuleCacheFile($cid); + $dir = dirname($cacheFile); + if (!file_exists($dir)) { + mkdir($dir, 0755, true); + } + $cache = [ + 'create_time' => time(), + 'data' => $data, + ]; + file_put_contents($cacheFile, json_encode($cache)); + } + + public function ltaoMoveStat() { + $shopIdAndGetCntMap = $this->redis->hGetAll(RedisKeyConst::getLtaoDetailTimesDayMap()); + $searchLtaoListTimesDayMap = $this->redis->hGetAll(RedisKeyConst::searchLtaoListTimesDayMap()); + $searchLtaoListTimesDayMapChunks = array_chunk($searchLtaoListTimesDayMap, 50, true); + + $startTimeStamp = strtotime(date('Ymd')); + $endTimeStamp = strtotime(date('YmdHi')); + $searchLtaoListTimesMinuteMaxCountMap = []; + + while(true) { + $searchLtaoListTimesMinuteMap = $this->redis->hGetAll(RedisKeyConst::searchLtaoListTimesMinuteMap(date('YmdHi', $startTimeStamp))); + if(!empty($searchLtaoListTimesMinuteMap)) { + + if(empty($searchLtaoListTimesMinuteMaxCountMap)) { + $searchLtaoListTimesMinuteMaxCountMap = $searchLtaoListTimesMinuteMap; + } else { + foreach ($searchLtaoListTimesMinuteMap as $shopId => $count) { + if(isset($searchLtaoListTimesMinuteMaxCountMap[$shopId]) && $count > $searchLtaoListTimesMinuteMaxCountMap[$shopId]) { + $searchLtaoListTimesMinuteMaxCountMap[$shopId] = $count; + } + + if(empty($searchLtaoListTimesMinuteMaxCountMap[$shopId])) { + $searchLtaoListTimesMinuteMaxCountMap[$shopId] = $count; + } + } + } + } + + $startTimeStamp += 60; + if($startTimeStamp > $endTimeStamp) { + break; + } + } + + foreach ($searchLtaoListTimesDayMapChunks as $searchLtaoListTimesDayMapChunk) { + $inserts = []; + $shopAndMoveCntMap = $this->db->query('select shop_id, count(*) as cnt from move_collect_task_detail where shop_id in %li and source = %s and gmt_create > %s group by shop_id', array_keys($searchLtaoListTimesDayMapChunk), FetchClientConst::collectTaskSourceTaote, date('Y-m-d 00:00:00', time() - 3600 * 24)); + $shopAndMoveCntMap = array_column($shopAndMoveCntMap, null, 'shop_id'); + + foreach ($searchLtaoListTimesDayMapChunk as $shopId => $getCnt) { + $inserts[] = [ + 'shop_id' => $shopId, + 'get_source_item_detail_times' => !empty($shopIdAndGetCntMap[$shopId]) ? $shopIdAndGetCntMap[$shopId] : 0, + 'get_list_times' => $getCnt, + 'get_list_times_min_max' => !empty($searchLtaoListTimesMinuteMaxCountMap[$shopId]) ? $searchLtaoListTimesMinuteMaxCountMap[$shopId] : 0, + 'move_cnt' => $shopAndMoveCntMap[$shopId]['cnt'], + 'dt' => date('Ymd'), + 'gmt_create' => date('Y-m-d H:i:s'), + 'gmt_modified' => date('Y-m-d H:i:s'), + ]; + } + $this->db->insert('ltao_move_stat', $inserts); + } + } + + public function searchLtaoMoveCnt($filter, $pageNo, $pageSize) { + $wheres = [1]; + if ($filter['shopId']) { + $wheres[] = $this->db->prepare('shop_id = %i', $filter['shopId']); + } + + if ($filter['startDt']) { + $wheres[] = $this->db->prepare('dt >= %i', date('Ymd', strtotime($filter['startDt']))); + } + + if ($filter['endDt']) { + $wheres[] = $this->db->prepare('dt <= %i', date('Ymd', strtotime($filter['endDt']))); + } + + return $this->db->queryPage('select * from ltao_move_stat where %l order by ltao_move_stat_id desc', implode(' and ', $wheres), $pageNo, $pageSize); + } + + public function getMovePublishAllImgs($productDetailBase) { + $imgUrls = []; + $imgUrls = array_merge($imgUrls, (array)explode('|', $productDetailBase['mainImgUrls'])); + $imgUrls = array_merge($imgUrls, (array)explode('|', $productDetailBase['noteImgUrls'])); + $imgUrls = array_merge($imgUrls, (array)explode(',', $productDetailBase['specPic'])); + + if (!empty($productDetailBase['whiteBgImgUrl'])) { + $imgUrls[] = $productDetailBase['whiteBgImgUrl']; + } + if (!empty($productDetailBase['longPicUrl'])) { + $imgUrls[] = $productDetailBase['longPicUrl']; + } + + foreach ($productDetailBase['qualityList'] as $quality) { + foreach ($quality['quality_attachments'] as $temp) { + if ($temp['url']) { + $imgUrls[] = $temp['url']; + } + } + } + $imgUrls = array_unique($imgUrls); + $imgUrls = array_filter($imgUrls); + return $imgUrls; + } + + public function fixupMaterialBizQueue() { + $log = Zc::getLog('timer/move_task/fixupMaterialBizQueue'); + $queues = $this->db->query('select * from material_biz_queue where gmt_create < %s', date('Y-m-d H:i:s', time() - 1800)); + foreach ($queues as $queue) { + $shopInfo = $this->shopDao->getShop($queue['shop_id']); + $accessToken = $shopInfo['access_token']; + $rows = $this->db->query('SELECT * from material_biz_audit_status_log where material_id in ( SELECT material_id FROM `material_biz_to_material` where material_biz_queue_id = %i) and status = %s', $queue['material_biz_queue_id'], StatusConst::wait); + foreach ($rows as $row) { + $ret = $this->materialDao->getMaterialQueryMaterialDetailFromDd($row['material_id'], $accessToken); + $materialInfo = $ret['data']['material_info']; + $auditStatus = $materialInfo['audit_status']; + if(in_array($auditStatus, [MaterialConst::materialAuditStatusWait, MaterialConst::materialAuditStatusProcess])) { + $materialInfo['audit_reject_desc'] = '审核超时,不在等待'; + } + + $status = ($auditStatus == MaterialConst::materialAuditStatusSuccess) ? StatusConst::success : StatusConst::fail; + $byteUrl = $materialInfo['byte_url']; + $auditRejectDesc = $materialInfo['audit_reject_desc']; + $update = [ + 'status' => $status, + 'fail_reason' => $auditRejectDesc, + 'byte_url' => $byteUrl + ]; + + $affect = $this->db->update('material_biz_audit_status_log', $update, 'material_id = %s', $row['material_id']); + $log->info($row['material_id'] . ' status : ' . $status . '; affect: ' . $affect); + } + } + } + + public function sandboxProcessMaterialAudit() { + if (Zc::C('env') != 'sandbox') { + die('e'); + } + $log = Zc::getLog('timer/move_task/fixupMaterialBizQueue'); + $queues = $this->db->query('select * from material_biz_queue where gmt_create < now()'); + foreach ($queues as $queue) { + $shopInfo = $this->shopDao->getShop($queue['shop_id']); + $accessToken = $shopInfo['access_token']; + $rows = $this->db->query('SELECT * from material_biz_audit_status_log where material_id in ( SELECT material_id FROM `material_biz_to_material` where material_biz_queue_id = %i) and status = %s', $queue['material_biz_queue_id'], StatusConst::wait); + foreach ($rows as $row) { + $ret = $this->materialDao->getMaterialQueryMaterialDetailFromDd($row['material_id'], $accessToken); + $materialInfo = $ret['data']['material_info']; + $auditStatus = $materialInfo['audit_status']; + if(in_array($auditStatus, [MaterialConst::materialAuditStatusWait, MaterialConst::materialAuditStatusProcess])) { + $materialInfo['audit_reject_desc'] = '审核超时,不在等待'; + } + + $status = ($auditStatus == MaterialConst::materialAuditStatusSuccess) ? StatusConst::success : StatusConst::fail; + $byteUrl = $materialInfo['byte_url']; + $auditRejectDesc = $materialInfo['audit_reject_desc']; + $update = [ + 'status' => $status, + 'fail_reason' => $auditRejectDesc, + 'byte_url' => $byteUrl + ]; + + $affect = $this->db->update('material_biz_audit_status_log', $update, 'material_id = %s', $row['material_id']); + $log->info($row['material_id'] . ' status : ' . $status . '; affect: ' . $affect); + } + } + } + + public function getDsAliPriceType($shopId) { + $dsAliPriceType = $this->db->queryFirstField('select show_ali_price_type from shop_ds_common_config where shop_id = %i', $shopId); + if (!empty($dsAliPriceType)) { + return $dsAliPriceType; + } + + return MoveConst::aliPriceTypeConfig; + } + + public function getDsCommonConfig($shopId) { + $dsCommonConfig = $this->db->queryFirstRow('select * from shop_ds_common_config where shop_id = %i', $shopId); + if (!empty($dsCommonConfig)) { + return $dsCommonConfig; + } + + $dsCommonConfig = array( + 'show_ali_price_type' => MoveConst::aliPriceTypeConfig, + ); + + return $dsCommonConfig; + } + + public function saveDsCommonConfig($shopId, $aliPriceType) { + $insert = array( + 'shop_id' => $shopId, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now() + ); + if ($aliPriceType) { + $insert['show_ali_price_type'] = $aliPriceType; + } + $update = $insert; + unset($update['gmt_create']); + $this->db->insertUpdate('shop_ds_common_config', $insert, $update); + return CommonTool::successResult(); + } + + public function insertDsAsyncNoticeTask($shopId, $type, $params) { + return $this->moveDao->insertDsAsyncNoticeTask($shopId, $type, $params); + } + + public function searchDsAsyncNoticeTaskFailLog($search, $currPageNo, $pageSize){ + $where = []; + if ($search['shopId']) { + $where[] = $this->db->prepare('and shop_id in %li', $search['shopId']); + } + + if ($search['sourceItemId']) { + $where[] = $this->db->prepare('and source_item_id = %i', $search['sourceItemId']); + } + + if ($search['productId']) { + $where[] = $this->db->prepare('and product_id = %i', $search['productId']); + } + + if ($search['retryStatus']) { + $where[] = $this->db->prepare('and retry_status = %s', $search['retryStatus']); + } + + $whereStr = implode(' ', $where); + + return $this->db->queryPage('select * from ds_async_notice_task_fail_log where 1 %l order by ds_async_notice_task_fail_log_id desc', $whereStr, $currPageNo, $pageSize); + } + + public function retryDsAsyncNoticeTask($logId) { + $logInfo = $this->db->queryFirstRow('select * from ds_async_notice_task_fail_log where ds_async_notice_task_fail_log_id = %i', $logId); + if (empty($logInfo)) { + return CommonTool::failResult('失败日志不存在'); + } + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $this->db->insert('ds_async_notice_task', array( + 'shop_id' => $logInfo['shop_id'], + 'type' => $logInfo['type'], + 'params' => $logInfo['params'], + 'locked' => 0, + 'try_times' => 0, + 'gmt_exec' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + $taskId = $this->db->lastInsertId(); + $this->db->update('ds_async_notice_task_fail_log', array( + 'ds_async_notice_task_id' => $taskId, + 'is_retry' => 1, + 'retry_status' => '', + 'gmt_modified' => ZcDbEval::now(), + ), 'ds_async_notice_task_fail_log_id = %i', $logId); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult($ex->getMessage()); + } + } + + public function searchDiyAttrValueLog($filter, $pageNo, $pageSize) { + $where[] = '1=1'; + if ($filter['shopId']) { + $where[] = $this->db->prepare('shop_id = %i', $filter['shopId']); + } + if ($filter['productId']) { + $where[] = $this->db->prepare('product_id = %i', $filter['productId']); + } + if ($filter['startDt']) { + $where[] = $this->db->prepare('gmt_create > %s', $filter['startDt']); + } + if ($filter['endDt']) { + $where[] = $this->db->prepare('gmt_create < %s', $filter['endDt']); + } + + return $this->db->useDbIdOnce('ac')->queryPage('select * from diy_attr_value_log where %l', implode(' and ', $where), $pageNo, $pageSize); + } + + public function getMovePublishStatistics($filter, $pageNo, $pageSize) { + $whereString = $this->getPublishQueueCountFilter($filter); + //后台统计 + + $publishList = $this->db->query("SELECT shop_id, the_day, min(the_hour) the_hour_min, max(the_hour) the_hour_max, min(priority) priority_min, max(priority) priority_max, sum(total_num) total_num, SUM(success_num) success_num, SUM(error_num) error_num FROM move_shop_publish_count WHERE TRUE %l GROUP BY the_day, shop_id order by total_num desc limit %i, %i", $whereString, ($pageNo - 1) * $pageSize, $pageSize); + return $publishList; + } + + public function getShopDateMovedCount($shopIds, $isYesterday = false) { + if (empty($shopIds)) { + return array(); + } + $date = $isYesterday ? date('Y-m-d', strtotime('-1 day')) : date('Y-m-d'); + + $shopPublishWareCountList = $this->db->query("SELECT shop_id, sum(success_num) as total FROM move_shop_publish_count WHERE shop_id IN %li AND success_num > 0 AND the_day = %s GROUP BY shop_id", $shopIds, $date); + $shopPublishWareTotalList = array(); + foreach ($shopPublishWareCountList as $shopPublishWareCountDetail) { + $currShopId = $shopPublishWareCountDetail['shop_id']; + $shopPublishWareTotalList[$currShopId]['total'] += $shopPublishWareCountDetail['total']; + + } + return $shopPublishWareTotalList; + } + + public function getMoveTaskImagesAuditRecord($taskDetailId) { + $materialBizQueueId = $this->db->queryFirstField('select mbq.material_biz_queue_id from move_product_publish_to_pic_queue mpptpq left join material_biz_queue mbq on mpptpq.move_product_publish_to_pic_queue_id = mbq.biz_id where mpptpq.move_collect_task_detail_id = %i', $taskDetailId); + + if(empty($materialBizQueueId)) { + return CommonTool::failResult('任务不存在或者已经完成'); + } + + return $this->getMoveTaskImagesAuditRecordByBizQueueId($materialBizQueueId); + } + + public function getMoveTaskImagesAuditRecordByBizQueueId($materialBizQueueId) { + $materialIds = $this->db->queryFirstColumn('select material_id from material_biz_to_material where material_biz_queue_id = %i', $materialBizQueueId); + if(empty($materialIds)) { + return CommonTool::failResult('任务不存在或者已经完成'); + } + + $rows = $this->db->query('select status, fail_reason, origin_url from material_biz_audit_status_log where material_id in %ls and status in %ls', $materialIds, [StatusConst::wait, StatusConst::fail]); + + return CommonTool::successResult('data', $rows); + } + + public function getMoveCollectTaskDetailIdByBizQueueId($BizQueueId) { + return $this->db->queryFirstField('select move_collect_task_detail_id from move_product_publish_to_pic_queue where move_product_publish_to_pic_queue_id = %i', $BizQueueId); + } + + public function getMoveCollectTaskDetailNoticeByTaskDetailId($moveCollectTaskDetailId) { + return $this->db->queryFirstRow('select * from move_collect_task_detail_notice where move_collect_task_detail_id = %i', $moveCollectTaskDetailId); + } + + public function checkMoveTaskDetailId($taskDetailId, $shopId) { + return $this->db->queryFirstField('select move_collect_task_detail_id from move_collect_task_detail where move_collect_task_detail_id = %i and shop_id = %i', $taskDetailId, $shopId); + } + + public function getMoveConfigImageTask($taskId) { + return $this->db->queryFirstRow('select * from move_config_image_task where move_config_image_task_id = %i', $taskId); + } + + public function updateMoveConfigImageTask($taskId, $status) { + return $this->db->update('move_config_image_task', array( + 'status' => $status, + 'gmt_modified' => ZcDbEval::now(), + ), 'move_config_image_task_id = %i', $taskId); + } + + public function updateMoveShopSettingQualityById($moveShopSettingQualityId, $update) { + $update['gmt_modified'] = ZcDbEval::now(); + $this->db->update('move_shop_setting_quality', $update, 'move_shop_setting_quality_id = %i', $moveShopSettingQualityId); + } + + public function updateMoveShopSettingBigField($update, $bigFieldId) { + $update['gmt_modified'] = ZcDbEval::now(); + $this->db->update('move_shop_setting_big_field', $update, 'move_shop_setting_big_field_id = %i', $bigFieldId); + } + + public function addShopToSupplierLog($shopId, $shopName, $fetchMethod, $shopUrl) { + return $this->db->insert('shop_to_supplier_log', array( + 'shop_id' => $shopId, + 'shop_name' => $shopName, + 'fetch_method' => $fetchMethod, + 'shop_url' => $shopUrl, + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + )); + } + + public function recordTriggerAppVersionLimitLog($shopId, $appVersion, $total, $usedTotal, $currSubmitTotal, $triggerType) { + return $this->moveDao->recordTriggerAppVersionLimitLog($shopId, $appVersion, $total, $usedTotal, $currSubmitTotal, $triggerType); + } + + public function triggerAppVersionLimitLog($filter, $pageNo, $pageSize) { + $wheres[] = $this->db->prepare('1=1'); + if ($filter['shopId']) { + $wheres[] = $this->db->prepare('shop_id = %i', $filter['shopId']); + } + if ($filter['version']) { + $wheres[] = $this->db->prepare('version = %s', $filter['version']); + } + if ($filter['triggerType']) { + $wheres[] = $this->db->prepare('trigger_type = %s', $filter['triggerType']); + } + if ($filter['starDate']) { + $wheres[] = $this->db->prepare('gmt_create > %s', $filter['starDate'] . ' 00:00:00'); + } + if ($filter['endDate']) { + $wheres[] = $this->db->prepare('gmt_create < %s', $filter['endDate'] . ' 23:59:48'); + } + + if($filter['isUpgrade'] == 1) { + $wheres[] = $this->db->prepare('is_upgrade = 1'); + } + + if($filter['isUpgrade'] == 2) { + $wheres[] = $this->db->prepare('is_upgrade = 0'); + } + + if($filter['type'] == 'shop') { + $rows = $this->db->useDbIdOnce('ac')->queryPage('select MAX( trigger_app_version_limit_log_id ) trigger_app_version_limit_log_id from trigger_app_version_limit_log where %l group by shop_id order by trigger_app_version_limit_log_id desc', implode(' and ', $wheres), $pageNo, $pageSize); + $data = $this->db->useDbIdOnce('ac')->query('select * from trigger_app_version_limit_log where trigger_app_version_limit_log_id in %li order by trigger_app_version_limit_log_id desc', array_column($rows[0], 'trigger_app_version_limit_log_id')); + return [$data, $rows[1]]; + }else { + return $this->db->useDbIdOnce('ac')->queryPage('select * from trigger_app_version_limit_log where %l order by trigger_app_version_limit_log_id desc', implode(' and ', $wheres), $pageNo, $pageSize); + } + } + + public function searchShopToSupplierLog($filter, $pageNo, $pageSize) { + $where[] = '1=1'; + if ($filter['startDt']) { + $where[] = $this->db->prepare(' and gmt_create > %s', $filter['startDt']); + } + + if ($filter['endDt']) { + $where[] = $this->db->prepare(' and gmt_create < %s', $filter['endDt']); + } + + if ($filter['shopId']) { + $where[] = $this->db->prepare(' and shop_id = %s', $filter['shopId']); + } + + if ($filter['shopName']) { + $where[] = $this->db->prepare(' and shop_name like %ss', $filter['shopName']); + } + + if ($filter['fetchMethod']) { + $where[] = $this->db->prepare(' and fetch_method = %s', $filter['fetchMethod']); + } + + $whereStr = implode(' ', $where); + return $this->db->queryPage("SELECT * FROM shop_to_supplier_log WHERE %l ORDER BY shop_to_supplier_log_id DESC", $whereStr, $pageNo, $pageSize); + } + + + public function getMoveLtaoProductSkuRelationList($shopId, $platformItemId, $sourceItemId) { + $moveProductManualSource = $this->db->queryFirstRow('select * from move_ltao_product_manual_source where shop_id = %i and platform_item_id = %s and source_item_id = %s', $shopId, $platformItemId, $sourceItemId); + + $skuRelationList = []; + $rows = $this->db->query('select * from move_ltao_product_manual_source_sku_relation where move_ltao_product_manual_source_id = %i', $moveProductManualSource['move_ltao_product_manual_source_id']); + foreach ($rows as $temp) { + $skuRelationList[] = [ + 'platformSkuId' => $temp['platform_sku_id'], + 'sourceSkuId' => $temp['source_sku_id'], + 'sourceNum' => $temp['source_num'], + ]; + } + return $skuRelationList; + } + + public function findDsNewDdSkuId($skuStr, $productInfo, $moveColorMap, $moveSizeMap) { + $findNewDdSkuIds = []; + $specs = $productInfo['specs']; + $specPrices = $productInfo['spec_prices']; + + $specIdAndValueMap = $this->productDao->getProductSpecIdAndNameMap($specs); + foreach ($specPrices as $specPrice) { + $skuId = $specPrice['sku_id']; + $specDetailIds = $specPrice['spec_detail_ids']; + $isMatch = $this->matchSkuStr($skuStr, $specIdAndValueMap, $specDetailIds, $moveColorMap, $moveSizeMap); + if ($isMatch) { + $findNewDdSkuIds[] = $skuId; + } + } + + return $findNewDdSkuIds; + } + + private function matchSkuStr($skuStr, $specIdAndValueMap, $specDetailIds, $moveColorMap, $moveSizeMap) { + if (empty($specDetailIds)) { + return false; + } + + if (count($specDetailIds) >= 2) { + list($specId1, $specId2) = $specDetailIds; + } else { + list($specId1) = $specDetailIds; + $specId2 = 0; + } + + $specName1 = isset($specIdAndValueMap[$specId1]) ? $specIdAndValueMap[$specId1] : ''; + $specName2 = isset($specIdAndValueMap[$specId2]) ? $specIdAndValueMap[$specId2] : ''; + + $moveColorName = $moveColorMap[$specName1]; + $moveSizeName = $moveSizeMap[$specName2]; + if (($skuStr == ';' . $moveColorName . ';' . $moveSizeName . ';') || ($skuStr == ';' . $moveSizeName . ';' . $moveColorName . ';')) { + return true; + } + + $moveColorName = $moveColorMap[$specName2]; + $moveSizeName = $moveSizeMap[$specName1]; + if (($skuStr == ';' . $moveColorName . ';' . $moveSizeName . ';') || ($skuStr == ';' . $moveSizeName . ';' . $moveColorName . ';')) { + return true; + } + + return false; + } + + public function getSourceProductInfoByManualSource($productInfo) { + $saleAttrAndValMap = []; + $skuIdMap = []; + $saleVidAndNameMap = []; + $salePidAndNameMap = []; + + foreach ($productInfo['skuBase']['props'] as $props) { + $attributeName = $props['name']; + $salePidAndNameMap[$props['pid']] = $attributeName; + foreach ($props['values'] as $value) { + $saleAttrAndValMap[$attributeName][$value['name']] = $value['name']; + $saleVidAndNameMap[$props['pid']][$value['vid']] = $value['name']; + } + } + + foreach ($productInfo['skuBase']['skus'] as $skuInfo) { + $skuId = $skuInfo['skuId']; + $propPathArr = explode(';', $skuInfo['propPath']); + foreach ($propPathArr as $propPath) { + list($pid, $vid) = explode(':', $propPath); + $attributeValue = $saleVidAndNameMap[$pid][$vid]; + $pValue = $salePidAndNameMap[$pid]; + $skuIdMap[$skuId][$pValue] = $attributeValue; + } + } + if (empty($saleAttrAndValMap)) { + $saleAttrAndValMap['默认规格']['默认规格'] = '默认规格'; + $skuIdMap[$productInfo['itemId']]['默认规格'] = '默认规格'; + } + + return [ + 'saleAttrAndValMap' => $saleAttrAndValMap, + 'skuIdMap' => $skuIdMap, + 'title' => $productInfo['item']['title'], + 'imgUrl' => $productInfo['item']['images'][0], + ]; + } + + public function addMovevenderLimit($shopId, $data) { + if (empty($shopId)) { + return false; + } + $update = array( + 'shop_id' => $shopId, + 'gmt_modified' => ZcDbEval::now() + ); + + if (isset($data['limit'])) { + $update['limit'] = is_numeric($data['limit']) ? (int)$data['limit'] : null; + } + + if (isset($data['batch_limit'])) { + $update['batch_limit'] = is_numeric($data['batch_limit']) ? (int)$data['batch_limit'] : null; + } + + if (isset($data['export_limit'])) { + $update['export_limit'] = is_numeric($data['export_limit']) ? (int)$data['export_limit'] : null; + } + + if (isset($data['video_limit'])) { + $update['video_limit'] = is_numeric($data['video_limit']) ? (int)$data['video_limit'] : null; + } + + if (isset($data['ykt_video_limit'])) { + $update['ykt_video_limit'] = is_numeric($data['ykt_video_limit']) ? (int)$data['ykt_video_limit'] : null; + } + + if (isset($data['notes'])) { + $update['notes'] = $data['notes']; + } + + if (array_key_exists('expiry_time', $data)) { + $update['expiry_time'] = $data['expiry_time'] ?: null; + } + + $insert = $update; + $insert['gmt_create'] = ZcDbEval::now(); + $ret = $this->db->insertUpdate('move_shop_limit', $insert, $update); + return ($ret === false) ? false : true; + } + + public function logPftShopStat($type, $shopId) { + $today = ZcDateHelper::today(); + $redisKey = DsConst::getPftUserStatRedisKeyByType($type, $today); + if (empty($redisKey)) { + return CommonTool::failResult('无效类型'); + } + + if (in_array($type, DsConst::getPftStatUserType())) { + $this->statRedis->sAdd($redisKey, $shopId); + } else { + $this->statRedis->incr($redisKey); + } + + $this->statRedis->expire($redisKey, 3600 * 24 * 2); + return CommonTool::successResult(); + } + + public function getPftStat($day) { + $result = []; + foreach (DsConst::getPftStatType() as $type) { + $redisKey = DsConst::getPftUserStatRedisKeyByType($type, $day); + if (in_array($type, DsConst::getPftStatUserType())) { + $value = $this->statRedis->sMembers($redisKey); + } else { + $value = $this->statRedis->get($redisKey); + } + + $result[$type] = $value; + } + + return $result; + } + + public function trySyncDsShopSkuRelationTypeList($shopId) { + $alibabaMemberId = $this->getAlibabaMemberId($shopId); + if (empty($alibabaMemberId)) { + return; + } + + $dsList = $this->db->query('select product_id, source_item_id, sku_relation_type from product_to_ds_item where shop_id = %i and sku_relation_type is null', $shopId); + if (empty($dsList)) { + return; + } + + $productIds = ZcArrayHelper::getSub($dsList, 'product_id'); + $existBufferIds = $this->db->queryFirstColumn('select product_id from ds_sku_relation_import_task_buffer where shop_id = %i and product_id in %li', $shopId, $productIds); + $existQueueIds = $this->db->queryFirstColumn('select product_id from ds_sku_relation_import_task_queue where shop_id = %i and product_id in %li', $shopId, $productIds); + $inserts = []; + foreach ($dsList as $row) { + if (!empty($row['sku_relation_type'])) { + continue; + } + + $productId = $row['product_id']; + if (in_array($productId, $existBufferIds) || in_array($productId, $existQueueIds)) { + continue; + } + + $inserts[] = array( + 'ds_sku_relation_import_task_id' => 0, + 'shop_id' => $shopId, + 'source_item_id' => $row['source_item_id'], + 'product_id' => $row['product_id'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + } + + if ($inserts) { + $this->db->insert('ds_sku_relation_import_task_buffer', $inserts); + } + } + + public function recordDeleteMoveProductPublishToPicQueueLog($moveCollectTaskDetailId, $position) { + return $this->moveDao->recordDeleteMoveProductPublishToPicQueueLog($moveCollectTaskDetailId, $position); + } + + private function buildSyncMoveSettingData($moveSetting, $syncTitlePrefix, $syncTitleSuffix, $syncMobile) { + $columns = $this->getMoveShopSettingColumn(); + $notSyncColumns = $this->getNoSyncMoveSettingColums(); + + $syncData = array(); + foreach ($columns as $column) { + if (in_array($column, $notSyncColumns)) { + continue; + } + if (($column == 'title_prefix') && !$syncTitlePrefix) { + continue; + } + if (($column == 'title_suffix') && !$syncTitleSuffix) { + continue; + } + if (($column == 'mobile') && !$syncMobile) { + continue; + } + $syncData[$column] = $moveSetting[$column]; + } + + return $syncData; + } + + public function syncMoveSettingToAuthShops($shopId, $authShopIds, $moveSettingId, $preShopIdList, $syncTitlePrefix, $syncTitleSuffix, $syncMobile, $syncQuality, $operatorInfo) { + if (CommonTool::anyEmpty($shopId, $authShopIds, $moveSettingId)) { + return CommonTool::failResult('参数不能为空'); + } + + $checkRet = $this->shopDao->checkAuthShopIdsHasPermission($shopId, $authShopIds, $preShopIdList); + if (CommonTool::isFailRet($checkRet)) { + return $checkRet; + } + + $moveSetting = $this->getMoveSettingInfo($shopId, $moveSettingId); + + $syncData = $this->buildSyncMoveSettingData($moveSetting, $syncTitlePrefix, $syncTitleSuffix, $syncMobile); + unset($syncData['preset_cate_attrs']); + unset($syncData['desc_replace']); + unset($syncData['desc_replace_id']); + + if ($syncQuality) { + // 同步资质图片 + $qualityList = $this->db->query('select * from move_shop_setting_quality where shop_id = %i and move_shop_setting_id = %i', $shopId, $moveSettingId); + } + + $this->syncMoveSettingLog->info("start syncMoveSettingToAuthShops shopId[$shopId] uid[{$operatorInfo['uid']}] authShopIds[" . implode(',', $authShopIds) . "] syncData[" . json_encode($syncData) . "]"); + + $shopsMoveSettingList = $this->db->query('SELECT * FROM move_shop_setting WHERE shop_id in %li and is_config_default = 1', $authShopIds); + $shopsMoveSettingList = ZcArrayHelper::changeKeyRow($shopsMoveSettingList, 'shop_id'); + + list($logDbId, $realLogTbl) = DbRoute::getDbAndTbl(TblConst::move_shop_setting_sync_log); + + $oldErrorMode = $this->db->setErrorMode(ZcDb::ERROR_MODE_EXCEPTION); + $transStatus = $this->db->startTransaction(); + try { + $syncLogs = array(); + foreach ($authShopIds as $authShopId) { + $authShopMoveSetting = $shopsMoveSettingList[$authShopId]; + $this->syncMoveSettingLog->info("syncMoveSettingToAuthShops shopId[$shopId] authShopId[$authShopId] authShopMoveSetting[" . json_encode($authShopMoveSetting) . "] syncData[" . json_encode($syncData) . "]"); + $authShopMoveSettingId = $authShopMoveSetting['move_shop_setting_id']; + $tmpSyncData = $syncData; + + $tmpSyncData['shop_id'] = $authShopId; + if ($authShopMoveSettingId) { + $update = $this->updateMoveSettingBigField($tmpSyncData, $authShopMoveSettingId, $authShopId); + $update['shop_id'] = $authShopId; + $update['gmt_modified'] = ZcDbEval::now(); + $this->db->update('move_shop_setting', $update, ' shop_id = %i AND move_shop_setting_id = %i', $authShopId, $authShopMoveSettingId); + $newSetting = $update; + } else { + $insert = $this->buildMoveSettingBigField($tmpSyncData, array()); + $insert['shop_id'] = $authShopId; + $insert['gmt_modified'] = ZcDbEval::now(); + $insert['gmt_create'] = ZcDbEval::now(); + $this->db->insert('move_shop_setting', $insert); + $newSetting = $insert; + $authShopMoveSettingId = $this->db->lastInsertId(); + } + if ($syncQuality && $qualityList) { + $authQualityList = $this->db->query('select * from move_shop_setting_quality where shop_id = %i and move_shop_setting_id = %i', $authShopId, $authShopMoveSettingId); + foreach ($qualityList as $quality) { + $existQuality = $this->db->queryFirstRow('select * from move_shop_setting_quality where shop_id = %i and move_shop_setting_id = %i and cid = %i and quality_key = %s', $authShopId, $authShopMoveSettingId, $quality['cid'], $quality['quality_key']); + if ($existQuality) { + $update = []; + $update['contents'] = $quality['contents']; + $update['gmt_modified'] = ZcDbEval::now(); + $this->db->update('move_shop_setting_quality', $update, 'shop_id = %i and move_shop_setting_id = %i and cid = %i and quality_key = %s', $authShopId, $authShopMoveSettingId, $quality['cid'], $quality['quality_key']); + } else { + $insert = $quality; + unset($insert['move_shop_setting_quality_id']); + $insert['shop_id'] = $authShopId; + $insert['move_shop_setting_id'] = $authShopMoveSettingId; + $insert['gmt_create'] = ZcDbEval::now(); + $insert['gmt_modified'] = ZcDbEval::now(); + $this->db->insert('move_shop_setting_quality', $insert); + } + + // 如果是oss图片需要提交审核 + $imgList = json_decode($quality['contents'], true); + $fieldName = BizConst::bizMoveConfigImageFieldQuality; + $extField = serialize([ + 'cid' => $quality['cid'], + 'quality_key' => $quality['quality_key'] + ]); + $needAuditUrls = CommonTool::getImageUrlArrNotDdUrl($imgList); + if (!empty($needAuditUrls)) { + $this->addMaterialBizMoveConfigImageTask($authShopId, $authShopMoveSettingId, $fieldName, $extField, $needAuditUrls); + } + + } + $syncLogs[] = array( + 'shop_id' => $authShopId, + 'operate_shop_id' => $shopId, + 'operate_ip' => $operatorInfo['ip'], + 'old_setting' => $authQualityList ? serialize($authQualityList) : null, + 'new_setting' => serialize($qualityList), + 'gmt_modified' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now(), + ); + } + + // 如果是oss图片需要提交审核 + if (!empty($syncData['desc_prefix_img'])) { + $fieldName = BizConst::bizMoveConfigImageFieldDescPrefixImg; + $extField = serialize(['desc_prefix_img_id' => $syncData['desc_prefix_img_id']]); + $needAuditUrls = CommonTool::getImageUrlArrNotDdUrl([$syncData['desc_prefix_img']]); + if (!empty($needAuditUrls)) { + $this->addMaterialBizMoveConfigImageTask($authShopId, $authShopMoveSettingId, $fieldName, $extField, $needAuditUrls); + } + + } + if (!empty($syncData['desc_suffix_img'])) { + $fieldName = BizConst::bizMoveConfigImageFieldDescSuffixImg; + $extField = serialize(['desc_suffix_img_id' => $syncData['desc_suffix_img_id']]); + $needAuditUrls = CommonTool::getImageUrlArrNotDdUrl([$syncData['desc_suffix_img']]); + if (!empty($needAuditUrls)) { + $this->addMaterialBizMoveConfigImageTask($authShopId, $authShopMoveSettingId, $fieldName, $extField, $needAuditUrls); + } + } + + $syncLogs[] = array( + 'shop_id' => $authShopId, + 'operate_shop_id' => $shopId, + 'operate_ip' => $operatorInfo['ip'], + 'old_setting' => $authShopMoveSetting ? serialize($authShopMoveSetting) : null, + 'new_setting' => serialize($newSetting), + 'gmt_modified' => ZcDbEval::now(), + 'gmt_create' => ZcDbEval::now(), + ); + } + + $syncLogsChunks = array_chunk($syncLogs, 50); + foreach ($syncLogsChunks as $syncLogsChunk) { + $affRow = $this->db->useDbIdOnce($logDbId)->insert($realLogTbl, $syncLogsChunk); + if (!$affRow) { + throw new Exception('备份日志失败'); + } + } + + $this->syncMoveSettingLog->info("end syncMoveSettingToAuthShops shopId[$shopId] authShopIds[" . implode(',', $authShopIds) . "] success"); + + $this->db->commit($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::successResult(); + } catch (Exception $ex) { + $this->syncMoveSettingLog->info("end syncMoveSettingToAuthShops shopId[$shopId] authShopIds[" . implode(',', $authShopIds) . "] errorMsg[" . $ex->getMessage() . "]"); + $this->db->rollback($transStatus); + $this->db->setErrorMode($oldErrorMode); + return CommonTool::failResult('保存数据失败'); + } + } + + public function findNewDdSkuInfo($skuStr, $productInfo, $moveColorMap, $moveSizeMap) { + $findNewDdSkuInfo = []; + $specs = $productInfo['specs']; + $specPrices = $productInfo['spec_prices']; + + $specIdAndValueMap = $this->productDao->getProductSpecIdAndNameMap($specs); + foreach ($specPrices as $specPrice) { + $skuId = $specPrice['sku_id']; + $specDetailIds = $specPrice['spec_detail_ids']; + $isMatch = $this->matchSkuStr($skuStr, $specIdAndValueMap, $specDetailIds, $moveColorMap, $moveSizeMap); + if ($isMatch) { + if (count($specDetailIds) >= 2) { + list($specId1, $specId2) = $specDetailIds; + } else { + list($specId1) = $specDetailIds; + $specId2 = 0; + } + + $specName1 = isset($specIdAndValueMap[$specId1]) ? $specIdAndValueMap[$specId1] : ''; + $specName2 = isset($specIdAndValueMap[$specId2]) ? $specIdAndValueMap[$specId2] : ''; + $findNewDdSkuInfo[] = array( + 'skuId' => $skuId, + 'skuPropStr' => $specName1 . MoveConst::skuKeyInterval . $specName2, + ); + } + } + + return $findNewDdSkuInfo; + } + + public function addSkuMinPriceRelation($shopId, $productId, $sourceItemId, $skuRelationList) { + $inserts = []; + foreach ($skuRelationList as $skuRelation) { + $inserts[] = array( + 'shop_id' => $shopId, + 'product_id' => $productId, + 'source_item_id' => $sourceItemId, + 'sku_id' => $skuRelation['platformSkuId'], + 'platform_sku_name' => $skuRelation['platformSkuName'], + 'source_sku_id' => $skuRelation['sourceSkuId'], + 'source_sku_name' => $skuRelation['sourceSkuName'], + 'gmt_create' => ZcDbEval::now(), + 'gmt_modified' => ZcDbEval::now(), + ); + } + + $affect = $this->db->insert('product_sku_min_price_relation', $inserts); + return $affect !== false ? CommonTool::successResult() : CommonTool::failResult('插入数据失败'); + } + + public function getSkuMinPriceRelation($shopId, $productId) { + return $this->db->query('select * from product_sku_min_price_relation where shop_id = %i and product_id = %i', $shopId, $productId); + } +} \ No newline at end of file diff --git a/doc/source/tool/class.CommonTool.php b/doc/source/tool/class.CommonTool.php new file mode 100644 index 00000000..91545a15 --- /dev/null +++ b/doc/source/tool/class.CommonTool.php @@ -0,0 +1,4178 @@ + 'fail', + 'reason' => $reason + ); + } + + public static function failCodeResult($code, $reason, $solution = '', $subErrors = '', $logId = '') { + $result = array ( + 'result' => 'fail', + 'code' => $code, + 'reason' => $reason + ); + if (!empty($solution)) { + $result['solution'] = $solution; + } + if (!empty($subErrors)) { + $result['subErrors'] = $subErrors; + } + if (!empty($logId)) { + $result['logId'] = $logId; + } + + return $result; + } + + public static function failCodeResultFromResp($resp) { + return array ( + 'result' => 'fail', + 'code' => is_object($resp) ? $resp->code : $resp['error_code'], + 'reason' => $resp['error_msg'] + ); + } + + public static function successResult($key = null, $value = null) { + $base = array ( + 'result' => 'success', + ); + + if (is_array($key)) { + return array_merge($base, $key); + } else if (is_scalar($key)) { + $base[$key] = $value; + } + + return $base; + } + + public static function markSuccess(&$array) { + $array['result'] = 'success'; + } + + public static function markFail(&$array, $reason = null) { + $array['result'] = 'fail'; + if (!empty($reason)) { + $array['reason'] = $reason; + } + } + + public static function getFailReason($resp) { + $zhDesc = is_object($resp) ? $resp->errorCode : $resp['error_code']; + $zhDescArr = $zhDesc; + + if (is_array($zhDescArr)) { + return $zhDescArr['msg']; + } elseif (is_string($zhDesc)) { + return $zhDesc; + } + + return print_r($resp, true); + } + + public static function getUuidName() { + try { + $name = Rhumsaa\Uuid\Uuid::uuid4()->toString(); + } catch (Exception $ex) { + $name = str_replace('.', '-', uniqid('', true)); + } + return $name; + } + + public static function ts() { + return date('Ymd-His'); + } + + public static function redisSMembers($key, $cacheType = RedisKeyConst::redisTypeBizCache) { + static $redisMap; + + if (!is_object($redisMap[$cacheType])) { + $redisMap[$cacheType] = RedisExt::factory($cacheType); + } + $redis = $redisMap[$cacheType]; + + $datas = []; + + $iterator = 0; + $pattern = '*'; + $count = 1000; + while (true) { + $result = $redis->rawCommand("SSCAN", $key, $iterator, 'match', $pattern, 'count', $count); + if ($result === false) { + break; + } + + $temp = $result[1]; + $iterator = $result[0]; + + $datas = array_merge($datas, $temp); + + if($iterator == 0){ + break; + } + } + + return $datas; + } + + public static function getAppSpecConstKeyMap($forceGroupList = array()) { + $allSpecAppConstKeyMap = array( + AppConst::specAppKeyGroupPlugin => array( + 'chromeExtReady' => array( + AppConst::appDd => 'J_newMsFetchChromeExtReady', + AppConst::appddmsV2 => 'J_dzFetchChromeExtReady', + ), + 'pluginTag' => array( + AppConst::appDd => 'msft', + AppConst::appddmsV2 => 'dzft', + ), + 'enablePlugin' => array( + AppConst::appDd => false, + AppConst::appddmsV2 => true, + ), + 'pluginCrxUrl' => array( + AppConst::appDd => 'https://honor-pub.oss-cn-beijing.aliyuncs.com/msfetch/msfetch-plugin.crx', + AppConst::appddmsV2 => 'https://cs-rt-c1.jiancent.com/browser-plugin/dzfetch/dzfetch-plugin.crx', + ), + 'pluginZipUrl' => array( + AppConst::appDd => 'https://honor-pub.oss-cn-beijing.aliyuncs.com/msfetch/msfetch-plugin.zip', + AppConst::appddmsV2 => 'https://cs-rt-c1.jiancent.com/browser-plugin/dzfetch/dzfetch-plugin.zip', + ), + 'shopCopyUrl' => array( + AppConst::appDd => Zc::url(RouteConst::moveBatchTarget, ['copyType' => 'shopCopy']), + AppConst::appddmsV2 => Zc::url(RouteAliasConst::moveBatchTarget, ['copyType' => 'shopCopy']), + ), + 'removeBatchClass' => array( + AppConst::appDd => '', + AppConst::appddmsV2 => 'row-title before-purple m-t-0', + ), + 'productQuantityCircleProgressColor' => array( + AppConst::appDd => '#34D19D', + AppConst::appddmsV2 => '#5CB85C', + ), + 'moveConfigProductQualityVersion' => array( + AppConst::appDd => 'v1', + AppConst::appddmsV2 => 'v2', + ), + 'rotateImgUrl' => array( + AppConst::appDd => HtmlTool::getStaticFile('rotate1.png'), + AppConst::appddmsV2 => HtmlTool::getStaticFile('rotate1.png'), + ), + 'checkAppName' => array( + AppConst::appDd => 'dd', + AppConst::appddmsV2 => 'ddmsV2' + ) + ) + ); + + $specAppConstKeyMap = array(); + $currAppName = Zc::C('appName'); + foreach ($allSpecAppConstKeyMap as $currGroup => $groupAppValueList) { + if (!empty($forceGroupList) && !in_array($currGroup, $forceGroupList)) { + continue; + } + foreach ($groupAppValueList as $key => $appValueList) { + if (!array_key_exists($currAppName, $appValueList)) { + continue; + } + $specAppConstKeyMap[$key] = $appValueList[$currAppName]; + } + } + + return $specAppConstKeyMap; + } + + public static function htmlPurifier($content, $config = null) { + Zc::import('zc.vendors.htmlpurifier-4#6#0-standalone.HTMLPurifier#standalone'); + + $configInstance = \HTMLPurifier_Config::createDefault(); + $configInstance->autoFinalize = false; + + $configInstance->set('Core.Encoding', 'utf-8'); + $configInstance->set('HTML.Doctype', 'HTML 4.01 Transitional'); + $configInstance->set('Attr.AllowedFrameTargets', array('_blank', '_self', '_parent', '_top')); + + $cacheDir = Zc::C('temp.dir') . 'runtime/html_purifier'; + !file_exists($cacheDir) && mkdir($cacheDir, 0777, true); + + $purifier=\HTMLPurifier::instance($configInstance); + $purifier->config->set('Cache.SerializerPath', $cacheDir); + + return $purifier->purify($content); + } + + public static function isPriceEqual($v1, $v2) { + return abs($v1 - $v2) < 0.001; + } + + public static function comparePercent($v1, $v2, $percent) { + $isTodayZero = ($v1 == 0 && $v2 > 0); + $isLwZero = ($v1 > 0 && $v2 == 0); + $isDiff = ($v1 > 0) && ($v2 > 0) && (((abs($v1 - $v2) / $v1) * 100) >= $percent); + + $ret = $isTodayZero || $isLwZero || $isDiff; + return $ret; + } + + public static function getImageLengthByUrl($imageUrl) { + $curl = self::getCurl(); + $content = $curl->head($imageUrl); + preg_match('/Content-Length: (\d+)[^\d]/isU', $content, $matches); + return (int)$matches[1] > 0 ? (int)$matches[1] : false; + } + + public static function getCurl($timeout = 5, $setopt = array(), $forceNew = false) { + static $curlMap = null; + $cacheKey = $timeout . md5(serialize($setopt)); + $curl = $curlMap[$cacheKey]; + + if (empty($curl) || $forceNew === true) { + Zc::import('zc.vendors.YwCurl'); + $setopt['timeOut'] = $timeout; + $setopt['ssl'] = true; + $curl = new YwCurl($setopt); + $headers = array ( + 'Connection: keep-alive', + 'Cache-Control: max-age=0', + 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36', + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Encoding: gzip,deflate,sdch', + 'Accept-Language: zh-CN,zh;q=0.8,de;q=0.6,en;q=0.4,es;q=0.2,nl;q=0.2,pt;q=0.2,ru;q=0.2,zh-TW;q=0.2,fr;q=0.2,ja;q=0.2' + ); + $curl->setCurlOpt(CURLOPT_HTTPHEADER, $headers); + + $curlMap[$cacheKey] = $curl; + } + + return $curl; + } + + public static function isTrustIpFromJflow() { + if(Zc::C('env') != 'live') { + return self::isTrustyIp(); + } + + $cliIp = self::clientIp(); + if(!empty($_SESSION[SessionConst::trustIp]) && ($_SESSION[SessionConst::trustIp] == $cliIp)) { + return true; + } + + static $authApiCurl; + if (empty($authApiCurl)) { + $authApiCurl = new \JxJflowClient\lib\AuthApiCurl(); + } + if (!$authApiCurl->verifyTrustIp()) { + unset($_SESSION[SessionConst::trustIp]); + return false; + } + + $_SESSION[SessionConst::trustIp] = $cliIp; + return true; + } + + public static function isTrustyIp($ip = null){ + $ip = (filter_var($ip, FILTER_VALIDATE_IP) !== false) ? $ip : self::clientIp(); + + $trustyIpList = array ( + '127.0.0.1', + '112.51.31.49', + '112.51.31.50' + ); + return in_array($ip, $trustyIpList) || (substr($ip, 0, 7) == '192.168'); + } + + /** + * 获取访问ip地址 + * @return NULL|Ambigous + */ + public static function clientIp() { + static $realip = NULL; + if ($realip !== NULL) { + return $realip; + } + if (isset ( $_SERVER )) { + if (isset ( $_SERVER ['HTTP_X_FORWARDED_FOR'] )) { + $arr = explode ( ',', $_SERVER ['HTTP_X_FORWARDED_FOR'] ); + // 取X-Forwarded-For中第一个非unknown的有效IP字符串 + foreach ( $arr as $ip ) { + $ip = trim ( $ip ); + if ($ip != 'unknown') { + $realip = $ip; + break; + } + } + } elseif (isset ( $_SERVER ['HTTP_CLIENT_IP'] )) { + $realip = $_SERVER ['HTTP_CLIENT_IP']; + } else { + if (isset ( $_SERVER ['REMOTE_ADDR'] )) { + $realip = $_SERVER ['REMOTE_ADDR']; + } else { + $realip = '0.0.0.0'; + } + } + } else { + if (getenv ( 'HTTP_X_FORWARDED_FOR' )) { + $realip = getenv ( 'HTTP_X_FORWARDED_FOR' ); + } elseif (getenv ( 'HTTP_CLIENT_IP' )) { + $realip = getenv ( 'HTTP_CLIENT_IP' ); + } else { + $realip = getenv ( 'REMOTE_ADDR' ); + } + } + preg_match ( "/[\d\.]{7,15}/", $realip, $onlineip ); + $realip = ! empty ( $onlineip [0] ) ? $onlineip [0] : '0.0.0.0'; + + return $realip; + } + + public static function makedir($dir){ + if(!is_dir($dir)) { + $tempPath = rtrim(preg_replace(array ( + "/\\\\/", + "/\/{2,}/" + ), "/", $dir), "/"); + @mkdir($tempPath, 0755, TRUE); + } + } + + public static function buildDwzUrl($url) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://dwz.cn/create.php"); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $data = array ( + 'url' => $url + ); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + $strRes = curl_exec($ch); + curl_close($ch); + $ret = json_decode($strRes, true); + if($ret['status'] != 0) { + return self::failResult($ret['err_msg']); + } + + return self::successResult('url', $ret['tinyurl']); + } + + /** + * 上次文件到某个目录 + * @param unknown $filename + * @param string $target + * @return string + */ + public static function uploadFile($filename, $target = 'temp', $name = null){ + @set_time_limit(0); + @ini_set('max_input_time', '-1'); + @ini_set('memory_limit', '512M'); + + // set tempdir + $target = Zc::C('temp.dir') . 'runtime/' . date('Y-m-d') . '/' . $target; + if (!is_dir($target)) { + mkdir($target, 755, true); + } + // 处理file表单上传的文件 + if (isset($_FILES[$filename])) { + // global $_FILES; + if(!is_array($_FILES[$filename]['name'])){ + $file = array ( + 'name' => $_FILES[$filename]['name'], + 'type' => $_FILES[$filename]['type'], + 'size' => $_FILES[$filename]['size'], + 'tmp_name' => $_FILES[$filename]['tmp_name'] + ); + + if (is_uploaded_file($file['tmp_name'])) { + if (substr($target, -1) != '/') { + $target .= '/'; + } + if($name) { + $pathInfo = pathinfo($file['name']); + $name = $name . '.' . $pathInfo['extension']; + $target .= $name; + } else { + $target .= $file['name']; + } + move_uploaded_file($file['tmp_name'], $target); + // 文件路径 + return $target; + } + } else { + $targets = []; + foreach ($_FILES[$filename]['name'] as $index => $value) { + $curTarget = ''; + $file = array ( + 'name' => $_FILES[$filename]['name'][$index], + 'type' => $_FILES[$filename]['type'][$index], + 'size' => $_FILES[$filename]['size'][$index], + 'tmp_name' => $_FILES[$filename]['tmp_name'][$index] + ); + + if (is_uploaded_file($file['tmp_name'])) { + if (substr($target, -1) != '/') { + $curTarget = $target . '/'; + } + if($name) { + $pathInfo = pathinfo($file['name']); + $name = $name . '.' . $pathInfo['extension']; + $curTarget .= $name; + } else { + $curTarget .= $file['name']; + } + move_uploaded_file($file['tmp_name'], $curTarget); + // 文件路径 + $targets[] = $curTarget; + } + } + return $targets; + } + } + + return false; + } + + public static function checkUploadFileSize($uploadName, $maxSize) { + if (!isset($_FILES[$uploadName])) { + return false; + } + + $size = $_FILES[$uploadName]['size']; + if ($size > $maxSize) { + return false; + } + + return true; + } + + /** + * 上次文件到某个目录 + * @param unknown $filename + * @param string $target + * @return string + */ + public static function uploadFileSafe($filename, $name = null){ + @set_time_limit(0); + @ini_set('max_input_time', '-1'); + @ini_set('memory_limit', '512M'); + + // 处理file表单上传的文件 + if (!isset($_FILES[$filename])) { + return false; + } + + $file = $_FILES[$filename]; + if (!is_uploaded_file($file['tmp_name'])) { + return false; + } + + if($name) { + $pathInfo = pathinfo($file['name']); + $name = $name . '.' . $pathInfo['extension']; + } else { + $name = $file["name"]; + } + + $tmpDir = dirname($file["tmp_name"]); + $destination = $tmpDir . DIRECTORY_SEPARATOR . $name; + $rn = rename($file["tmp_name"], $destination); + + return $rn ? $destination : false; + } + + public static function uploadImgFileToOss($imgUrl, $moveDir = 'move/watermark') { + $baseName = basename($imgUrl); + $ext = explode('.', $baseName); + $ext = $ext[1]; + if ($ext == 'jpg' || $ext == 'jpeg') { + $options = array ( + 'jpeg_quality' => 90 + ); + } else { + $options = array ( + 'quality' => 100 + ); + } + if(!in_array($ext, array('png', 'jpg', 'jpeg'))){ + return CommonTool::failResult("只允许格式为jpg、jpeg、png的图片上传"); + } + + $moveDir = $moveDir ? $moveDir : 'temp'; + $ossPath = sprintf('%s/%s/%s.%s', $moveDir, date('Y-m-d'), self::getUuidName(), $ext); + + $ret = self::getImageDataFromUrlUseProxy($imgUrl); + if(CommonTool::isFailRet($ret)) { + return $ret; + } + + $imageInfo = getimagesize($imgUrl); + $ret = OssTool::uploadImmutableObjectByContent($ossPath, $ret['imageData']); + + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + return CommonTool::successResult(array( + 'src' => OssTool::getPubOssUrlByOssPath($ossPath), + 'ossPath' => $ossPath, + 'width' => $imageInfo[0], + 'height' => $imageInfo[1], + 'bits' => $imageInfo['bits'], + 'mime' => $imageInfo['mime'] + )); + } + + public static function uploadLocalImgFileToOss($uploadName, $moveDir){ + return self::uploadLocalFileToOss($uploadName, $moveDir, array ('png','gif','jpg','jpeg')); + } + + public static function uploadLocalFileToOss($uploadName, $moveDir, $rules, $contentType = null){ + $filename = self::uploadFile($uploadName); + if(!$filename){ + return CommonTool::failResult("上传文件错误"); + } + $ext = strtolower(pathinfo($_FILES[$uploadName]['name'], PATHINFO_EXTENSION)); + if (!in_array($ext, $rules)) { + return CommonTool::failResult("只允许上传".implode(',', $rules)."格式的素材"); + } + $imageData = file_get_contents($filename); + $name = sprintf('ms_material_%s_', uniqid()); + $ossPath = sprintf("%s/%s.%s", $moveDir, $name, $ext); + $ret = OssTool::uploadImmutableObjectByContent($ossPath, $imageData, '', '', $contentType); + unlink($filename); + + return $ret; + } + + public static function deleteDir($dirname) { + if(stripos($dirname, Zc::C('temp.dir')) !== 0){ + return CommonTool::failResult('只能处理temp目录'); + } + + if(!file_exists($dirname)){ + return false; + } + + if(!is_dir($dirname)){ + unlink($dirname); + return true; + } + + $handle = opendir($dirname); + if ($handle === false) { + return CommonTool::failResult('没有权限'); + } + + while(($file = readdir($handle)) !== false) { + if($file == '.' || $file == '..'){ + continue; + } + + $curPath = $dirname . DIRECTORY_SEPARATOR . $file; + if(is_dir($curPath)){ + self::deleteDir($curPath . "/"); + }else{ + self::deleteDir($curPath); + } + } + + closedir($handle); + rmdir($dirname); + return true; + } + + public static function convertEncoding($string, $to = 'gbk', $from = 'utf-8') { + if (function_exists('mb_convert_encoding')) { + $result = mb_convert_encoding($string, $to, $from); + } + if (!$result && function_exists('iconv')) { + $result = iconv($from, $to, $string); + } + + return $result ? $result : $string; + } + + public static function checkNeedProcessSamesiteUserAgent($userAgent) { + return true; + preg_match('#\s+Chrome\/(\d+)\.#is', $userAgent, $matchChromeUaVersion); + if ($matchChromeUaVersion[1] >= 80) { + return true; + } + + return false; + } + + public static function anyFalse() { + $args = func_get_args(); + foreach ($args as $arg) { + if ($arg === false) { + return true; + } + } + return false; + } + + public static function anyEmpty() { + $args = func_get_args(); + foreach ($args as $arg) { + if (empty($arg)) { + return true; + } + } + return false; + } + + public static function anyNotNumeric() { + $args = func_get_args(); + foreach ($args as $arg) { + if (!is_numeric($arg)) { + return true; + } + } + return false; + } + + public static function allEmpty() { + $args = func_get_args(); + foreach ($args as $arg) { + if (!empty($arg)) { + return false; + } + } + return true; + } + + public static function getRandByNumber($num) { + $rand = ''; + for ($i = 0; $i < $num; $i++) { + if ($i === 0) { + $rand = mt_rand(1, 9); + } + $rand = $rand . mt_rand(0, 9); + } + + return (string)$rand; + } + + public static function uploadMobileDescToOss($shopId, $productCode, $data, $type){ + $wareIdPath = substr($productCode,0,3); + + if ($type == 'md') { + $objUrl = "md/{$shopId}/{$wareIdPath}/{$productCode}/mobile_desc.txt"; + } else { + $objUrl = "md/{$shopId}/{$wareIdPath}/{$productCode}/mobile_desc_after.txt"; + } + return OssTool::uploadImmutableObjectByContent($objUrl, $data); + } + + public static function getMobileDescFromOss($shopId, $wareId, $type) { + $wareIdPath = substr($wareId, 0, 3); + + if ($type == 'md') { + $objUrl = "md/{$shopId}/{$wareIdPath}/{$wareId}/mobile_desc.txt"; + } else { + $objUrl = "md/{$shopId}/{$wareIdPath}/{$wareId}/mobile_desc_after.txt"; + } + + return OssTool::getImmutableObjectByContent($objUrl); + } + + public static function getRandomTestMobile() { + $mobileList = array('18650333503', '18558617121', '18650704428', '15705963332', '15659108118'); + return $mobileList[array_rand($mobileList, 1)]; + } + + /** + * 汉字转Unicode编码 + * @param string $str 原始汉字的字符串 + * @param string $encoding 原始汉字的编码 + * @param boot $ishex 是否为十六进制表示(支持十六进制和十进制) + * @param string $prefix 编码后的前缀 + * @param string $postfix 编码后的后缀 + */ + public static function unicodeEncode($str, $encoding = 'UTF-8', $ishex = false, $prefix = '&#', $postfix = ';') { + $str = iconv($encoding, 'UCS-2', $str); + $arrstr = str_split($str, 2); + $unistr = ''; + for($i = 0, $len = count($arrstr); $i < $len; $i++) { + $dec = $ishex ? bin2hex($arrstr[$i]) : hexdec(bin2hex($arrstr[$i])); + $unistr .= $prefix . $dec . $postfix; + } + return $unistr; + } + + /** + * Unicode编码转汉字 + * @param string $str Unicode编码的字符串 + * @param string $decoding 原始汉字的编码 + * @param boot $ishex 是否为十六进制表示(支持十六进制和十进制) + * @param string $prefix 编码后的前缀 + * @param string $postfix 编码后的后缀 + */ + public static function unicodeDecode($unistr, $ishex = false) { + if($ishex) { + return json_decode('"'.$unistr.'"'); + } + + $word = preg_replace_callback('/&#(\d{5});/i', function($descMap){ + return mb_convert_encoding($descMap[0], 'UTF-8', 'HTML-ENTITIES'); + }, $unistr); + + return $word; + } + + public static function createWatermark($sourceFilePath, $watermarkImg, $posX, $posY, $quality, $opacity, $outputFilePath, $respType = 'file'){ + list ($sourceWidth, $sourceHeight, $sourceType) = getimagesize($sourceFilePath); + if ($sourceType === NULL) { + return false; + } + + switch ($sourceType) { + case IMAGETYPE_GIF : + $sourceGdimage = imagecreatefromgif($sourceFilePath); + break; + case IMAGETYPE_JPEG : + $sourceGdimage = imagecreatefromjpeg($sourceFilePath); + break; + case IMAGETYPE_PNG : + $sourceGdimage = imagecreatefrompng($sourceFilePath); + break; + default : + return false; + } + list ($overlayWidth, $overlayHeight, $overlayType) = getimagesize($watermarkImg); + switch ($overlayType) { + case IMAGETYPE_GIF : + $overlayGdImage = imagecreatefromgif($watermarkImg); + break; + case IMAGETYPE_JPEG : + $overlayGdImage = imagecreatefromjpeg($watermarkImg); + break; + case IMAGETYPE_PNG : + $overlayGdImage = imagecreatefrompng($watermarkImg); + break; + default : + return false; + } + + imagecopymerge($sourceGdimage, $overlayGdImage, $posX, $posY, 0, 0, $overlayWidth, $overlayHeight, $opacity); + if($respType == 'file' && !empty($outputFilePath)){ + imagejpeg($sourceGdimage, $outputFilePath, $quality); + imagedestroy($sourceGdimage); + imagedestroy($overlayGdImage); + return $outputFilePath; + } else { + ob_start(); + ob_implicit_flush(0); + + imagejpeg($sourceGdimage, null, $quality); + imagedestroy($sourceGdimage); + imagedestroy($overlayGdImage); + + $data = ob_get_clean(); + return $data; + } + } + + + public static function isTrue($val){ + return ($val == 1) ? true : false; + } + + public static function stringIsTrue($val, $returnNull = false) + { + $boolVal = (is_string($val) ? filter_var($val, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : (bool) $val); + return ($boolVal === null && !$returnNull ? false : $boolVal); + } + + public static function isCurrAdminSelfShop($shopId) { + if (empty($shopId)) { + $shopId = $_SESSION[SessionConst::shopId]; + } + return in_array($shopId, self::adminSelfShopIds()); + } + + public static function adminRealSelfShopList() { + $selfShopList = [ + '16700961' => '漂亮毛衣', + '16412356' => '时尚喇叭裤', + '4463798' => '抖店开放平台测试专用店', + '30450753' => '我的滑板鞋', + '30459766' => '蕾丝袜', + ]; + + return $selfShopList; + } + + public static function adminSelfShopIds($excludeShopIds = array()) { + static $shopIds; + if (empty($shopIds)) { + $shopIds = self::getAdminSelfShopIdsFromCache(); + } + if(!empty($excludeShopIds)) { + $excludeShopIds = is_array($excludeShopIds) ? $excludeShopIds : array($excludeShopIds); + $shopIds = array_diff($shopIds, $excludeShopIds); + $shopIds = array_values($shopIds); + } + + if (empty($shopIds)) { + $shopIds = array(1); + } + return $shopIds; + } + + public static function getAdminSelfShopIdsFromCache(){ + static $redis; + if (!is_object($redis)) { + $redis = RedisExt::factory('bizCache'); + } + + $selfShopInfo = $redis->get(RedisKeyConst::adminSelfShopInfo); + $selfShopInfo = unserialize($selfShopInfo); + + if (!empty($selfShopInfo['selfShopIds'])) { + return $selfShopInfo['selfShopIds']; + } + + /* @var $shopService ShopService */ + $shopService = Zc::singleton('ShopService'); + $selfShopIds = $shopService->getAdminSelfShopIds(); + + if (!empty($selfShopIds)) { + $v = array('selfShopIds' => $selfShopIds, 'hostname' => gethostname()); + $setRet = $redis->setex(RedisKeyConst::adminSelfShopInfo, 72 * 3600, serialize($v)); + $logger = Zc::getLog('self_admin'); + $logger->info("getAdminSelfShopIdsFromCache SetRet {$setRet} shopIdIds " . print_r($v, true)); + } + + return $selfShopIds; + } + + public static function getCountryMap() { + return array( + '' => '--请选择产地--', + 'CN' => '中国', + 'TW' => '中国台湾', + 'MO' => '中国澳门', + 'HK' => '中国香港', + 'NT' => 'NATO', + 'PM' => 'St. Pierre and Miquelon', + 'BT' => '不丹', + 'TP' => '东帝汶岛', + 'CF' => '中非共和国', + 'DK' => '丹麦', + 'UA' => '乌克兰', + 'UZ' => '乌兹别克斯坦', + 'UG' => '乌干达', + 'UY' => '乌拉圭', + 'TD' => '乍得', + 'GE' => '乔治亚', + 'YE' => '也门', + 'AM' => '亚美尼亚', + 'IL' => '以色列', + 'IQ' => '伊拉克', + 'IR' => '伊朗伊斯兰教共和国', + 'BZ' => '伯利兹', + 'CV' => '佛得角群岛', + 'RU' => '俄罗斯联邦', + 'BG' => '保加利亚', + 'HR' => '克罗地亚', + 'GU' => '关岛', + 'GM' => '冈比亚', + 'IS' => '冰岛', + 'GN' => '几内亚', + 'GW' => '几内亚比绍', + 'LI' => '列支敦士登', + 'CG' => '刚果共和国', + 'CD' => '刚果民主共和国', + 'LY' => '利比亚', + 'LR' => '利比里亚', + 'CA' => '加拿大', + 'GH' => '加纳', + 'GA' => '加蓬', + 'HU' => '匈牙利', + 'KP' => '北朝鲜', + 'MP' => '北马绍尔群岛', + 'GS' => '南乔治亚和南三维治岛', + 'AQ' => '南极洲', + 'ZA' => '南非共和国', + 'BW' => '博茨瓦纳', + 'QA' => '卡塔尔', + 'RW' => '卢旺达', + 'LU' => '卢森堡', + 'IN' => '印度', + 'ID' => '印度尼西亚', + 'GT' => '危地马拉', + 'EC' => '厄瓜多尔', + 'SY' => '叙利亚', + 'CU' => '古巴', + 'KG' => '吉尔吉斯斯坦', + 'DJ' => '吉布提', + 'KZ' => '哈萨克斯坦', + 'CO' => '哥伦比亚', + 'CR' => '哥斯答黎加', + 'CM' => '喀麦隆', + 'TV' => '图瓦卢', + 'TM' => '土库曼斯坦人', + 'TR' => '土耳其共和国', + 'KN' => '圣基茨和那维斯联盟', + 'ST' => '圣多美和普林西比民主共和国', + 'VC' => '圣文森特和格林纳丁斯', + 'CX' => '圣诞岛', + 'SH' => '圣赫勒拿岛', + 'LC' => '圣路西亚', + 'SM' => '圣马力诺共和国', + 'GY' => '圭亚那', + 'TZ' => '坦桑尼亚', + 'EG' => '埃及', + 'ET' => '埃塞俄比亚', + 'ER' => '埃立特里亚', + 'KI' => '基里巴斯', + 'TJ' => '塔吉克斯坦', + 'SN' => '塞内加尔', + 'CS' => '塞尔维亚和门的内哥罗', + 'SL' => '塞拉利昂', + 'CY' => '塞浦路斯', + 'SC' => '塞舌尔群岛', + 'MX' => '墨西哥', + 'TG' => '多哥', + 'DM' => '多米尼加', + 'DO' => '多米尼加共和国', + 'GB' => '大不列颠联合王国', + 'AT' => '奥地利', + 'VE' => '委内瑞拉', + 'BD' => '孟加拉国', + 'AO' => '安哥拉', + 'AI' => '安圭拉岛', + 'AG' => '安提瓜和巴布达', + 'AD' => '安道尔共和国', + 'FM' => '密克罗尼西亚', + 'NI' => '尼加拉瓜', + 'NG' => '尼日利亚', + 'NE' => '尼日尔', + 'NP' => '尼泊尔', + 'BS' => '巴哈马(群岛)', + 'PK' => '巴基斯坦', + 'PS' => '巴基斯坦', + 'BB' => '巴巴多斯', + 'PG' => '巴布亚新几内亚独立国', + 'PY' => '巴拉圭', + 'PA' => '巴拿马', + 'BH' => '巴林', + 'BR' => '巴西', + 'BF' => '布基纳法索', + 'BV' => '布维群岛', + 'BI' => '布隆迪', + 'GR' => '希腊', + 'PW' => '帕劳共和国', + 'CC' => '库科纳群岛', + 'KY' => '开曼群岛', + 'DE' => '德国', + 'IT' => '意大利', + 'SB' => '所罗门群岛', + 'TK' => '托客劳群岛', + 'LV' => '拉脱维亚', + 'NO' => '挪威', + 'CZ' => '捷克共和国', + 'MD' => '摩尔多瓦', + 'MA' => '摩洛哥', + 'MC' => '摩纳哥', + 'EH' => '撒哈拉西部', + 'BN' => '文莱达鲁萨兰', + 'FJ' => '斐济', + 'SZ' => '斯威士兰', + 'SK' => '斯洛伐克共和国', + 'SI' => '斯洛文尼亚', + 'LK' => '斯里兰卡', + 'SG' => '新加坡', + 'NC' => '新喀里多尼亚', + 'NZ' => '新西兰', + 'JP' => '日本', + 'CL' => '智利', + 'KH' => '柬埔寨', + 'GD' => '格林纳达', + 'GL' => '格陵兰岛', + 'VA' => '梵蒂冈城', + 'OR' => '橙色', + 'EU' => '欧盟', + 'BE' => '比利时', + 'MR' => '毛里塔尼亚', + 'MU' => '毛里求斯', + 'TO' => '汤加', + 'SA' => '沙特阿拉伯', + 'FR' => '法国', + 'TF' => '法国南部地区', + 'GF' => '法属圭亚那', + 'PF' => '法属波利尼西亚', + 'FO' => '法罗群岛', + 'PL' => '波兰共和国', + 'PR' => '波多黎哥', + 'BA' => '波斯尼亚和黑塞哥维那', + 'TH' => '泰国', + 'ZW' => '津巴布韦', + 'HN' => '洪都拉斯', + 'HT' => '海地', + 'AU' => '澳大利亚', + 'IE' => '爱尔兰', + 'EE' => '爱沙尼亚', + 'JM' => '牙买加', + 'TC' => '特克斯和凯科斯岛', + 'TT' => '特立尼达和多巴哥共和国', + 'BO' => '玻利维亚', + 'NR' => '瑙鲁', + 'SE' => '瑞典', + 'CH' => '瑞士', + 'GP' => '瓜达洛普', + 'WF' => '瓦利斯群岛和富图纳群岛', + 'VU' => '瓦努阿图', + 'BY' => '白俄罗斯', + 'BM' => '百慕大群岛', + 'PN' => '皮特克恩岛', + 'SJ' => '皮特肯岛', + 'GI' => '直布罗陀', + 'FK' => '福克兰群岛', + 'CK' => '科克群岛', + 'KW' => '科威特', + 'KM' => '科摩罗群岛', + 'PE' => '秘鲁共和国', + 'TN' => '突尼斯', + 'LT' => '立陶宛', + 'SO' => '索马里', + 'JO' => '约旦', + 'NA' => '纳米比亚', + 'NU' => '纽埃群岛', + 'RE' => '统一', + 'MM' => '缅甸', + 'RO' => '罗马尼亚', + 'US' => '美国', + 'UM' => '美属小奥特兰群岛', + 'VI' => '美属维尔京群岛', + 'AS' => '美属萨摩亚群岛', + 'LA' => '老挝', + 'UN' => '联合国', + 'KE' => '肯尼亚', + 'FI' => '芬兰', + 'SD' => '苏丹', + 'SR' => '苏里南', + 'TL' => '英国', + 'IO' => '英属印度洋区', + 'VG' => '英属维尔京群岛', + 'NL' => '荷兰王国', + 'AN' => '荷属安的列斯岛', + 'HM' => '荷德和马克多纳群岛', + 'MZ' => '莫桑比克', + 'LS' => '莱索托', + 'PH' => '菲律宾', + 'SV' => '萨尔瓦多', + 'PT' => '葡萄牙共和国', + 'MN' => '蒙古', + 'MS' => '蒙塞拉特岛', + 'BL' => '蓝色', + 'ES' => '西班牙', + 'NF' => '诺福克岛', + 'CI' => '象牙海岸', + 'BJ' => '贝宁', + 'ZM' => '赞比亚', + 'GQ' => '赤道几内亚', + 'VN' => '越南', + 'AZ' => '阿塞拜疆', + 'AF' => '阿富汗', + 'DZ' => '阿尔及利亚', + 'AL' => '阿尔巴尼亚', + 'AE' => '阿拉伯联合酋长国', + 'OM' => '阿曼', + 'AR' => '阿根廷', + 'AW' => '阿鲁巴', + 'KR' => '韩国', + 'MK' => '马其顿', + 'MV' => '马尔代夫', + 'MW' => '马拉维', + 'MQ' => '马提尼克', + 'MY' => '马来西亚', + 'YT' => '马约特岛', + 'MH' => '马绍尔群岛共和国', + 'MT' => '马耳他', + 'MG' => '马达加斯加', + 'ML' => '马里', + 'LB' => '黎巴嫩', + ); + + } + + public static function getImageDataFromUrlUseProxy($imageUrl, $retryTimes = 5) { + $log = Zc::getLog('tool/common/get_image_data_error'); + $isRequestLocal = true; + if (strpos($imageUrl, 'k3cdn') !== false) { + $isRequestLocal = false; + } + $curl = new ProxyCenterCurl(FetchClientConst::proxyPlatformTypePicUrl, $isRequestLocal); + $referer = ''; + if (stripos($imageUrl, '17qcc.com') !== false) { + $referer = 'http://www.17qcc.com/'; + } + if (stripos($imageUrl, 'dhresource.com') !== false) { + $imageUrl = str_replace('webp/m/', '', $imageUrl); + } + + if(!preg_match('/^http(s)?:\\/\\/.+/', $imageUrl)){ + $imageUrl = 'https:' . $imageUrl; + } + + for ($i = 1; $i <= $retryTimes; $i++) { + $imageData = $curl->get($imageUrl, array(), $referer); + $info = $curl->getInfo(); + $after = $info['after']; + + if (($after['curl_error'] == 'SSL connect error') && (preg_match('#https:\/\/([^\.]*).xiedu.biz#isU', $imageUrl))) { + $imageUrl = str_ireplace('https', 'http', $imageUrl); + $log->info("change image uri to http: $imageUrl"); + continue; + } + + if ($after['http_code'] != 200) { + continue; + } + + if (($after['download_content_length'] > 0) && ($after['download_content_length'] == strlen($imageData))) { + return CommonTool::successResult('imageData', $imageData); + } + $imageHtmlReturnComplete = self::checkImageHtmlReturnComplete($imageUrl); + $log->info('checkImageHtmlReturnComplete'.print_r($imageHtmlReturnComplete, true)); + if (!$imageHtmlReturnComplete) { + return CommonTool::successResult('imageData', $imageData); + } + } + + $log->info("$imageUrl, curlInfo:" . print_r($curl->getInfo(), true)); + + return CommonTool::failCodeResult($after['http_code'], '获取图片数据失败'); + } + + public static function getVideoDataFromUrlUseProxy($videoUrl, $retryTimes = 5) { + $curl = new ProxyCenterCurl(FetchClientConst::proxyPlatformTypePicUrl, true); + for ($i = 1; $i <= $retryTimes; $i++) { + $videoData = $curl->get($videoUrl); + $info = $curl->getInfo(); + $after = $info['after']; + + if ($after['http_code'] != 200) { + continue; + } + + if (($after['download_content_length'] > 0) && ($after['download_content_length'] == strlen($videoData))) { + return CommonTool::successResult('videoData', $videoData); + } + } + + return CommonTool::failCodeResult($after['http_code'], '获取视频数据失败'); + } + + public static function headerUrlUseProxy($videoUrl) { + $curl = new ProxyCenterCurl(FetchClientConst::proxyPlatformTypePicUrl, true); + $headers = $curl->head($videoUrl); + $info = $curl->getInfo(); + $after = $info['after']; + + if (($after['download_content_length'] > 0)) { + return CommonTool::successResult(['headers' => $headers, 'after' => $after]); + } + + return CommonTool::failCodeResult($after['http_code'], '获取数据失败'); + } + + public static function saveVideoToLocalFromUrl($url, $localPath) { + $options = array( + CURLOPT_FILE => fopen($localPath, 'w'), + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_URL => $url, + CURLOPT_FAILONERROR => true, + CURLOPT_HTTPHEADER => array ( + 'Connection: keep-alive', + 'Cache-Control: max-age=0', + 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36', + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Encoding: gzip,deflate,sdch', + 'Accept-Language: zh-CN,zh;q=0.8,de;q=0.6,en;q=0.4,es;q=0.2,nl;q=0.2,pt;q=0.2,ru;q=0.2,zh-TW;q=0.2,fr;q=0.2,ja;q=0.2' + ), + ); + + $ch = curl_init(); + curl_setopt_array($ch, $options); + return curl_exec($ch); + } + + public static function getImageExtendByData($imageData, $imgUrl = '') { + $sub = substr($imageData, 0, 2); + switch ($sub) + { + case "BM": + return 'bmp'; + case "GI": + return 'gif'; + case chr(0xFF).chr(0xd8): + return 'jpeg'; + case chr(0x89).'P': + return 'png'; + default: + if (substr($imgUrl, strlen($imgUrl)-3) == 'jpg') { + return 'jpeg'; + } + return false; + } + } + + public static function getImageDataFromUrl($imageUrl, $retryTimes = 5) { + $log = Zc::getLog('tool/common/get_image_data_error'); + $curl = self::getCurl(5); + for ($i = 1; $i <= $retryTimes; $i++) { + $imageData = $curl->get($imageUrl); + $info = $curl->getInfo(); + $after = $info['after']; + + if (($after['curl_error'] == 'SSL connect error') && (preg_match('#https:\/\/([^\.]*).xiedu.biz#isU', $imageUrl))) { + $imageUrl = str_ireplace('https', 'http', $imageUrl); + $log->info("change image uri to http: $imageUrl"); + continue; + } + + if ($after['http_code'] != 200) { + continue; + } + + if (($after['download_content_length'] > 0) && ($after['download_content_length'] == strlen($imageData))) { + return CommonTool::successResult(['imageData' => $imageData , 'imageType' => $after['content_type']]); + } + + $imageHtmlReturnComplete = self::checkImageHtmlReturnComplete($imageUrl); + if (!$imageHtmlReturnComplete) { + return CommonTool::successResult(['imageData' => $imageData , 'imageType' => $after['content_type']]); + } + } + + $log->info("$imageUrl, curlInfo:" . print_r($curl->getInfo(), true)); + + return CommonTool::failCodeResult($after['http_code'], '获取图片数据失败'); + } + + public static function checkImageHtmlReturnComplete($imageUrl) { + $htmlReturnComplete = true; + $htmlReturnNotCompleteUrls = FetchClientTool::getHtmlReturnNotCompleteUrls(); + + foreach ($htmlReturnNotCompleteUrls as $url) { + if (stripos($imageUrl, $url) !== false) { + $htmlReturnComplete = false; + break; + } + } + + return $htmlReturnComplete; + } + + public static function clearAliasSpechars($subject) { + $subject = str_replace(array ( + '(', + ')', + '—', + '-', + '×', + ), array ( + '(', + ')', + '-', + '-', + 'x', + ), $subject); + + $filterSubject = preg_replace('/[^a-zA-Z0-9\x{4e00}-\x{9fa5}\s@#\$%&+\-\/\\\_()=.*!]/u', '', $subject); + $filterSubject = $filterSubject ? $filterSubject : $subject; + return $filterSubject; + } + + /** + * @link https://apigen.ci/github/mmeyer2k/dcrypt/namespace-Dcrypt.html + */ + public static function encrypt($plaintext, $shopId = 0) { + if (empty($plaintext)) { + return $plaintext; + } + $password = sprintf('%s*%s', Zc::C('shop.encrypt.key'), (int)($shopId / 19)); + $encrypted = \Dcrypt\Mcrypt::encrypt($plaintext, $password); + return base64_encode($encrypted); + } + + public static function decrypt($encrypted, $shopId = 0) { + if (empty($encrypted)) { + return $encrypted; + } + $password = sprintf('%s*%s', Zc::C('shop.encrypt.key'), (int)($shopId / 19)); + try { + $plaintext = \Dcrypt\Mcrypt::decrypt(base64_decode($encrypted), $password); + return $plaintext; + }catch (Exception $ex){ + Zc::getLog()->monitor($ex->getMessage()); + } + } + + /** + * @link https://apigen.ci/github/mmeyer2k/dcrypt/namespace-Dcrypt.html + */ + public static function jxEncrypt($plaintext, $venderId) { + $password = sprintf('%s*%s', Zc::C('jx.group.token'), (int)($venderId / 19)); + $encrypted = \Dcrypt\Mcrypt::encrypt($plaintext, $password); + return base64_encode($encrypted); + } + + /** + * @link https://apigen.ci/github/mmeyer2k/dcrypt/namespace-Dcrypt.html + */ + public static function jxDecrypt($plaintext, $venderId) { + $password = sprintf('%s*%s', Zc::C('jx.group.token'), (int)($venderId / 19)); + $plaintext = \Dcrypt\Mcrypt::decrypt(base64_decode($plaintext), $password); + return $plaintext; + } + + public static function smd5Value($value) { + if ($value === null) { + return null; + } + if ($value === '') { + return ''; + } + $smd5Key1 = Zc::C('smd5.key1'); + $smd5Key2 = Zc::C('smd5.key2'); + return md5(md5($smd5Key1 . $value) . $smd5Key2); + } + + public static function extractImgUrls($string) { + $matchUrls = array(); + + $pattern = '#background\s*=\s*(?:\'|\")\s*([^<>]*)(?:\'|\")\s*#isU'; + if (preg_match_all($pattern, $string, $matchBackgroundImgs)) { + $matchUrls = array_merge($matchUrls, $matchBackgroundImgs[1]); + } + + $pattern = '#background\s*:\s*url\((?:\'|\"|)([^<>]*)(?:\'|\"|)\)#isU'; + if (preg_match_all($pattern, $string, $matchBackgroundImgs)) { + $matchUrls = array_merge($matchUrls, $matchBackgroundImgs[1]); + } + + $pattern = '/src\s*=\s*["|\'](.*)["|\']/isU'; + if (preg_match_all($pattern, $string, $matchBackgroundImgs)) { + $srcImages = preg_grep('/.*(?]*{$filterImgUrl}[^<>]*>#isU"; + $string = preg_replace("#]*{$filterImgUrl}[^<>]*>#isU", '', $string); + + if (preg_match("#background[^<>]*{$filterImgUrl}#", $string)) { + $string = str_replace($filterImgUrl, '#', $string); + } + } + return $string; + } + + public static function replaceOuterTagString($search, $replace, $inputString) { + preg_match_all('#<[^<>]*>|[^<>]+?#isU', $inputString, $matchStringList); + + $outputString = ''; + foreach ($matchStringList[0] as $string) { + if (preg_match('#^<.*>$#s', $string, $matchTag)) { + $outputString .= $string; + } else { + $outputString .= str_ireplace($search, $replace, $string); + } + } + return $outputString; + } + + public static function convertPatternString($pattern) { + return str_replace( + array('.', '+', '*', '?', '-', '^', '$', '/', '(', ')', '[', ']'), + array('\.', '\+', '\*', '\?', '\-', '\^', '\$', '\/', '\(', '\)', '\[', '\]'), + $pattern + ); + } + + private static function getFilterWordPattern($filterString) { + preg_match_all('/./iu', $filterString, $matchFilterWord); + + $pattern = ''; + foreach ($matchFilterWord[0] as $filterWord) { + if (trim($filterWord) == '') { + continue; + } + $filterWord = preg_quote($filterWord); + $filterWord = str_replace([ + '/', + ], [ + '\/', + ], $filterWord); + $pattern .= '\s*' . $filterWord; + } + $pattern = sprintf('/%s/isUu', $pattern); + return $pattern; + } + + public static function filterContent($filterWords, $needFilterString) { + if (is_array($filterWords)) { + $filterArray = array_unique($filterWords); + foreach($filterArray as $filterWord) { + $filterWordPattern = CommonTool::getFilterWordPattern($filterWord); + $needFilterString = preg_replace($filterWordPattern, '', $needFilterString); + } + } else { + $filterWordPattern = CommonTool::getFilterWordPattern($filterWords); + $needFilterString = preg_replace($filterWordPattern, '', $needFilterString); + } + return $needFilterString; + } + + public static function getFileUrlExtend($fileUrl) { + return strtolower(substr(strrchr($fileUrl, '.'), 1)); + } + + public static function clearUrlScheme($url) { + $url = trim($url); + if (strncasecmp($url, "http:", 5) == 0) { + $url = substr($url, 5); + return $url; + } + + if (strncasecmp($url, "https:", 6) == 0) { + $url = substr($url, 6); + return $url; + } + return $url; + } + + public static function addUrlScheme($url) { + $url = trim($url); + if (empty($url)) { + return $url; + } + if (substr($url, 0, 4) == 'http') { + return $url; + } + + $url = "http://" . trim($url, '\/:'); + return $url; + } + + + public static function getMultiImageSizeAndType($imgUrls){ + if (empty($imgUrls)) { + return array(); + } + static $rim = null; + if (empty($rim)) { + Zc::import('@.vendor.rim.rim'); + $rim = new rim(); + } + + foreach ($imgUrls as $k => $imgUrl) { + if (!filter_var($imgUrl, FILTER_VALIDATE_URL)) { + if (substr($imgUrl, 0, 2) == '//') { + $imgUrl = 'http:' . $imgUrl; + } + if (substr($imgUrl, 0, 4) != 'http') { + $imgUrl = 'http://' . $imgUrl; + } + + $imgUrls[$k] = $imgUrl; + } + } + + return $rim->getMultiImageTypeAndSize($imgUrls); + } + + public static function getLocalImageSize($localImgUrl) { + if (empty($localImgUrl)) { + return false; + } + + static $imagine = null; + try { + if (empty($imagine)) { + $imagine = new Imagine\Gd\Imagine(); + } + /* @var $gdImage Imagine\Gd\Image */ + $gdImage = $imagine->open($localImgUrl); + $size = $gdImage->getSize(); + return array ( + $size->getWidth(), + $size->getHeight() + ); + } catch (Exception $ex) { + return false; + } + } + + public static function trimImgScheme($imgUrl) { + $imgUrl = trim($imgUrl); + if (substr($imgUrl, 0, 2) == '//') { + return $imgUrl; + } + + if (strtolower(substr($imgUrl, 0, 4)) == 'http') { + return str_ireplace(['https:', 'http:'], '', $imgUrl); + } + + return $imgUrl; + } + + public static function buildImgScheme($imgUrl, $scheme = 'https') { + $imgUrl = trim($imgUrl); + if (stripos($imgUrl, $scheme) === 0) { + return $imgUrl; + } + if (substr($imgUrl, 0, 2) == '//') { + return $scheme . ':' . $imgUrl; + } + if (strtolower(substr($imgUrl, 0, 4)) == 'http') { + return $scheme . ':' . str_ireplace(['https:', 'http:'], '', $imgUrl); + } + return $imgUrl; + } + + /** + * 去掉url参数 + * @param unknown $url + * @return string + */ + public static function clearUrlcan($url){ + + $rstr=''; + + $tmparr=parse_url($url); + + $rstr=empty($tmparr['scheme'])?'http://':$tmparr['scheme'].'://'; + + $rstr.=$tmparr['host'].$tmparr['path']; + + return $rstr; + + } + + + /** + * 翻译route把大字字母转换成下划线加小写字母 + */ + public static function transLateRoute($string) { + $translateString = ''; + for($i = 0; $i < strlen($string) ; $i++) { + if(ord($string[$i]) >= 65 && ord($string[$i]) <= 90) { + $translateString .= ($i != 0) ? ("_" . chr(ord($string[$i])+32)) : chr(ord($string[$i])+32); //将大写字母转换成小写,且非首字母转换的加个下划线 + } else { + $translateString .= $string[$i]; + } + } + return $translateString; + } + + public static function getErrorReasonResetName($reason) { + $errorMap = array( + 'sys.oauth.check.access_token:inexistence' => '授权已经过期,请重新登录之后重试', + 'biz.custom.childItem.invalid-biz:pars--G00001' => '尺码重命名错误,请联系客服', + ); + + if ($errorMap[$reason]) { + return $errorMap[$reason]; + } + + return $reason; + } + + public static function getImageEtagByUrl($imgUrl) { + for($tryTimes = 0; $tryTimes < 5; $tryTimes++) { + $curl = self::getCurl(); + $curl->head($imgUrl); + $curlInfo = $curl->getInfo(); + if ($curlInfo['after']['http_code'] != 200) { + return ''; + } + + $headInfo = $curlInfo['header']; + preg_match('/Etag: (.*)\n/isU', $headInfo, $match); + if (!empty($match[1])) { + return $match[1]; + } + sleep(2); + } + } + + public static function getImageExtArr() { + return array( + 'bmp', + 'jpg', + 'png', + 'tiff', + 'gif', + 'pcx', + 'tga', + 'exif', + 'fpx', + 'svg', + 'psd', + 'cdr', + 'pcd', + 'dxf', + 'ufo', + 'eps', + 'ai', + 'raw', + 'wmf', + ); + + } + + public static function getImageForbiddenSourceSite() { + return ['591wx','yedemall','yunchepin','mmgg', 'zlycw']; + return FetchClientTool::getImageForbiddenSourceSite(); + } + + /** + * + * 求最大公约数 + */ + public static function getCommonDivisor ($m, $n) { + do { + $r = $m % $n; + + $m = $n; + $n = $r; + } while($r); + + return $m; + } + + public static function convertGifToJpgDataByImgData($imageData) { + $imageInfo = getimagesizefromstring($imageData); + if ($imageInfo['mime'] !== 'image/gif') { + return $imageData; + } + $imagine = new Imagine\Gd\Imagine(); + /* @var $image Imagine\GD\Image */ + $image = $imagine->load($imageData); + $imageData = $image->get('jpg'); + + unset($image, $imagine); //加快GC,节省内存 + return $imageData; + } + + public static function convertBmpToJpgDataByImgData($imageData) { + $pointer = 0; + $size = strlen($imageData); + $read = function ($length) use ($imageData, &$pointer) { + $string = substr($imageData, $pointer, $length); + $pointer += $length; + + return $string; + }; + $turnRound = false; + $meta = unpack('vtype/Vfilesize/Vreserved/Voffset', $read(14)); + if ($meta['type'] != 19778) { + return $imageData; + } + $meta += unpack( + 'Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', + $read(40) + ); + if ($meta['height'] < 0) { + $meta['height'] = abs($meta['height']); + $turnRound = true; + } elseif ($meta['height'] > 10000) { + $imageInfo = getimagesizefromstring($imageData); + $meta['height'] = $imageInfo[1]; + $turnRound = true; + } + $bytesRead = 40; + if ($meta['compression'] == 3) { + $meta += unpack('VrMask/VgMask/VbMask', $read(12)); + $bytesRead += 12; + } + + $meta['bytes'] = $meta['bits'] / 8; + $meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4) - floor($meta['width'] * $meta['bytes'] / 4))); + if ($meta['decal'] == 4) { + $meta['decal'] = 0; + } + if ($meta['imagesize'] < 1) { + $meta['imagesize'] = $meta['filesize'] - $meta['offset']; + if ($meta['imagesize'] < 1) { + $meta['imagesize'] = $size - $meta['offset']; + } + } + $meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors']; + + $palette = []; + if ($meta['bits'] < 16) { + $palette = unpack('l' . $meta['colors'], $read($meta['colors'] * 4)); + if ($palette[1] < 0) { + foreach ($palette as $i => $color) { + $palette[$i] = $color + 16777216; + } + } + } + + if ($meta['headersize'] > $bytesRead) { + $read($meta['headersize'] - $bytesRead); + } + $im = imagecreatetruecolor($meta['width'], $meta['height']); + $data = $read($meta['imagesize']); + switch ($meta['compression']) { + case 1: + $data = rle8_decode($data, $meta['width']); + break; + case 2: + $data = rle4_decode($data, $meta['width']); + break; + } + + $p = 0; + $vide = chr(0); + $y = $meta['height'] - 1; + while ($y >= 0) { + $x = 0; + while ($x < $meta['width']) { + switch ($meta['bits']) { + case 32: + case 24: + $part = substr($data, $p, 3 /*$meta['bytes']*/); + if (!$part) { + return $imageData; + } + $color = unpack('V', $part . $vide); + break; + case 16: + $part = substr($data, $p, 2 /*$meta['bytes']*/); + if (!$part) { + return $imageData; + } + + $color = unpack('v', $part); + if (empty($meta['rMask']) || $meta['rMask'] != 0xf800) { + $color[1] = (($color[1] & 0x7c00) >> 7) * 65536 + (($color[1] & 0x03e0) >> 2) * 256 + (($color[1] & 0x001f) << 3); // 555 + } else { + $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3); // 565 + } + break; + case 8: + $color = unpack('n', $vide . substr($data, $p, 1)); + $color[1] = $palette[$color[1] + 1]; + break; + case 4: + $color = unpack('n', $vide . substr($data, floor($p), 1)); + $color[1] = ($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F; + $color[1] = $palette[$color[1] + 1]; + break; + case 1: + $color = unpack('n', $vide . substr($data, floor($p), 1)); + switch (($p * 8) % 8) { + case 0: + $color[1] = $color[1] >> 7; + break; + case 1: + $color[1] = ($color[1] & 0x40) >> 6; + break; + case 2: + $color[1] = ($color[1] & 0x20) >> 5; + break; + case 3: + $color[1] = ($color[1] & 0x10) >> 4; + break; + case 4: + $color[1] = ($color[1] & 0x8) >> 3; + break; + case 5: + $color[1] = ($color[1] & 0x4) >> 2; + break; + case 6: + $color[1] = ($color[1] & 0x2) >> 1; + break; + case 7: + $color[1] = ($color[1] & 0x1); + break; + } + $color[1] = $palette[$color[1] + 1]; + break; + default: + return $imageData; + } + + imagesetpixel($im, $x, $y, $color[1]); + $x++; + $p += $meta['bytes']; + } + $y--; + $p += $meta['decal']; + } + if ($turnRound) { + $im = imagerotate($im, 180, 0); + $new = imagecreatetruecolor($meta['width'], $meta['height']); + for ($x = 0; $x < $meta['width']; $x++) { + imagecopy($new, $im, $meta['width'] - $x - 1, 0, $x, 0, 1, $meta['height']); + } + + $quality = 95; + $newJpgFilePath = sys_get_temp_dir() . '/' . uniqid() . '.jpg'; + imagejpeg($new, $newJpgFilePath, $quality); + imagedestroy($new); + imagedestroy($im); + $imageData = file_get_contents($newJpgFilePath); + unlink($newJpgFilePath); + return $imageData; + } + + $quality = 95; + $newJpgFilePath = sys_get_temp_dir() . '/' . uniqid() . '.jpg'; + imagejpeg($im, $newJpgFilePath, $quality); + imagedestroy($im); + $imageData = file_get_contents($newJpgFilePath); + unlink($newJpgFilePath); + return $imageData; + } + + public static function getIpInfoFromAliYun($ip = null){ + static $ipInfoMap; + $ip = trim($ip); + if (empty($ip) || filter_var($ip, FILTER_VALIDATE_IP) === false) { + $ip = CommonTool::clientIp(); + } + if(!empty($ipInfoMap[$ip])){ + return $ipInfoMap[$ip]; + } + + $appcode = "caa2e6c5a99f40e0bdecf1aa387033af"; + $url = sprintf("https://hcapi22.market.alicloudapi.com/ip?ip=%s", $ip); + + $curl = self::getCurl(5); + $headers = array ( + sprintf('Authorization:APPCODE %s', $appcode) + ); + $curl->setCurlOpt(CURLOPT_HTTPHEADER, $headers); + $geoData = array(); + for ($i = 0; $i < 3; $i++){ + $jsonData = $curl->get($url); + $geoInfo = json_decode($jsonData, true); + + $geoInfo = $geoInfo['data']; + if (!empty($geoInfo['city'])) { + $geoData = [ + 'city' => $geoInfo['city'], + 'region' => $geoInfo['region'], + 'ip' => $ip, + 'adcode' => $geoInfo['city_id'], + 'source' => 'ali', + ]; + $ipInfoMap[$ip] = $geoData; + break; + } + } + if (empty($geoData)) { + $geoData = self::getIpInfoFromBaidu($ip); + if (!empty($geoData)) { + $ipInfoMap[$ip] = $geoData; + } + } + + return $geoData ? $geoData : array(); + } + + public static function getIpInfoFromBaidu($ip = null) { + $ip = $ip ? trim($ip) : self::clientIp(); + + $ak = "O8Qdd3oCFwb5BlTm8MSASUVy3jhvx4uQ"; + $apiUrl = "http://api.map.baidu.com/location/ip"; + + $curl = self::getCurl(5); + $geoData = array(); + for ($i = 0; $i < 3; $i++){ + $jsonData = $curl->post($apiUrl, array( + 'ip' => $ip, + 'ak' => $ak + )); + $geoInfo = json_decode($jsonData, true); + $addressDetail = $geoInfo['content']['address_detail']; + if (empty($addressDetail['city'])) { + continue; + } + + $geoData = array( + 'city' => $addressDetail['city'], + 'ip' => $ip, + 'region' => $addressDetail['province'], + 'source' => 'baidu' + ); + + break; + } + + return $geoData; + } + + + public static function getFamilyNameAndChineseNameMap() { + return array( + 'HYShuSongYiJ' => '汉仪书宋一(简)', + 'HYShuSongErF' => '汉仪书宋二(繁)', + 'HYZhongHeiJ' => '汉仪中黑(简)', + 'HYZhongHeiF' => '汉仪中黑(繁)', + 'HYCuFangSongJ' => '汉仪粗仿宋(简)', + 'HYKaiTiJ' => '汉仪楷体(简)', + 'HYKaiTiF' => '汉仪楷体(繁)', + 'HYShuiDiTiJ' => '汉仪水滴体(简)', + 'HYShuiDiTiF' => '汉仪水滴体(繁)', + 'HYXiJianHeiJ' => '汉仪细简黑(简)', + 'HYZhongJianHeiJ' => '汉仪中简黑(简)', + 'HYZhenZhuLiJ' => '汉仪珍珠隶书(简)', + 'HYZhenZhuLiF' => '汉仪珍珠隶书(繁)', + + 'msyh' => '微软雅黑', + 'SimHei' => '黑体', + 'ZongYi' => '综艺', + 'QianTi' => '倩体', + 'YaoYang' => '摇扬', + 'PangTouYu' => '胖头鱼体', + 'MengDu' => '梦度', + 'kaiti' => '楷书', + 'songti' => '宋体', + 'lishu' => '隶书', + 'xingkai' => '华文行楷', + 'Arial' => 'Arial', + 'Helvetica Bold' => 'Helvetica Bold', + 'Times New Roman' => 'Times New Roman', + 'Courier New' => 'Courier New', + 'Verdana' => 'Verdana', + 'Mildy' => 'Mildy', + 'Ink Chancery' => 'Ink Chancery', + 'Blackie' => 'Blackie', + 'Elgatino' => 'Elgatino', + 'Rayna' => 'Rayna', + 'Geometr415 Blk BT Black' => 'Geometr415 Blk BT Black', + 'FuturnMdBT' => 'Futura Md BT', + 'MStiffHei-PRC-UltraBold' => 'MStiffHei PRC UltraBold', + + 'SYBold' => '思源黑体Bold', + 'SYExtralight' => '思源黑体Extralight', + 'SYHeavy' => '思源黑体Heavy', + 'SYLight' => '思源黑体Light', + 'SYMedium' => '思源黑体Medium', + 'SYNormal' => '思源黑体Normal', + 'SYRegular' => '思源黑体Regular', + + 'jianmeihei' => '迷你简美黑', + 'jianshuizhu' => '迷你简水柱', + 'jianxihei' => '迷你简细黑', + 'minijiankaiti' => '迷你简楷体', + 'minijianlibian' => '迷你简隶变', + + 'FZLTDHJW' => '方正兰亭大黑简体', + 'FZLTCH_GBK' => '方正兰亭粗黑GBK', + 'FZLTZH_GBK' => '方正兰亭中黑GBK', + 'FZLTHJT' => '方正兰亭中黑简体', + 'FZZZZJT' => '方正正中黑简体', + 'yingbikaishu' => '方正硬笔楷书', + 'qianheijianti' => '方正正纤黑简体', + 'zhunyuan' => '方正准圆简体', + 'zhunheijianti' => '方正正准黑简体', + 'dabiaosong' => '方正大标宋简体', + 'daheijianti' => '方正大黑简体', + 'cuyuan' => '方正粗圆简体', + 'shaoer' => '方正少儿简体', + 'cusong' => '方正粗宋', + 'jianyingbixingshu' => '方正硬笔行书简体', + 'chaocuhei' => '方正超粗黑简体', + 'cuqian' => '方正粗倩简体', + 'miaowuti' => '方正喵呜体', + 'ShuTi' => '方正舒体', + 'xiqian' => '方正细倩简体', + 'xiaobiaosong' => '方正小标宋简体', + 'yiheiti' => '方正艺黑简体', + 'fangzhengzhanbiheijianti' => '方正毡笔黑简体', + 'zhengcuhei' => '方正正粗黑简体', + 'zhiyiti' => '方正稚艺简体', + 'FZLTQH_GBK' => '方正兰亭纤黑_GBK', + 'FZSHANGKJW' => '方正尚酷简体', + 'FZLTDH_GBK' => '方正兰亭大黑_GBK', + ); + } + + /** + * 一下字体在php中暂不支持中文 + */ + public static function invalidChinesesFamilyNameArr() { + return array( + 'Arial', + 'Times New Roman', + 'Courier New', + 'Verdana', + 'Helvetica Bold', + 'Mildy', + 'Ink Chancery', + 'Blackie', + 'Elgatino', + 'Rayna' + ); + } + + public static function getFamilyNameAndTtfMap() { + return array( + 'Arial' => 'arial.ttf', + 'Times New Roman' => 'timesNewRoman.ttf', + 'Courier New' => 'courierNew.ttf', + 'Verdana' => 'verdana.ttf', + + 'SimHei' => 'simhei.ttf', + 'ZongYi' => 'zongyi.ttf', + 'QianTi' => 'qianti.ttf', + 'YaoYang' => 'yaoyan.ttf', + 'PangTouYu' => 'pantouyu.ttf', + 'ShuTi' => 'suti.ttf', + 'MengDu' => 'mengdu.ttf', + + + 'FZLTDHJW' => 'FZLTDHJW.ttf', + 'FZZZZJT' => 'fzzzhjt.ttf', + 'FZLTCH_GBK' => 'FZLTCH_GBK.TTF', + 'FZLTZH_GBK' => 'FZLTZH_GBK.TTF', + 'FZLTHJT' => 'FZLTHJT.ttf', + 'msyh' => 'msyh.ttf', + 'Helvetica Bold' => 'HelveticaBold.ttf', + + 'HYShuSongYiJ' => 'HYShuSongYiJ.ttf', + 'HYShuSongErF' => 'HYShuSongErF.ttf', + 'HYZhongHeiJ' => 'HYZhongHeiJ.ttf', + 'HYZhongHeiF' => 'HYZhongHeiF.ttf', + 'HYCuFangSongJ' => 'HYCuFangSongJ.ttf', + 'HYKaiTiJ' => 'HYKaiTiJ.ttf', + 'HYKaiTiF' => 'HYKaiTiF.ttf', + 'HYShuiDiTiJ' => 'HYShuiDiTiJ.ttf', + 'HYShuiDiTiF' => 'HYShuiDiTiF.ttf', + 'HYXiJianHeiJ' => 'HYXiJianHeiJ.ttf', + 'HYZhongJianHeiJ' => 'HYZhongJianHeiJ.ttf', + 'HYZhenZhuLiJ' => 'HYZhenZhuLiJ.ttf', + 'HYZhenZhuLiF' => 'HYZhenZhuLiF.ttf', + 'Mildy' => 'Mildy.ttf', + 'Ink Chancery' => 'InkChancery.ttf', + 'Blackie' => 'Blackie.ttf', + 'Elgatino' => 'Elgatino.ttf', + 'Rayna' => 'Rayna.ttf', + 'Geometr415 Blk BT Black' => 'geometr415_blk_bt_black.ttf', + 'FuturnMdBT' => 'FuturnMdBT.ttf', + 'MStiffHei-PRC-UltraBold' => 'MStiffHei-PRC-UltraBold.ttf', + + 'SYBold' => 'SOURCEHANSANSCN-BOLD.OTF', + 'SYExtralight' => 'SOURCEHANSANSCN-EXTRALIGHT.OTF', + 'SYHeavy' => 'SOURCEHANSANSCN-HEAVY.OTF', + 'SYLight' => 'SOURCEHANSANSCN-LIGHT.OTF', + 'SYMedium' => 'SOURCEHANSANSCN-MEDIUM.OTF', + 'SYNormal' => 'SOURCEHANSANSCN-NORMAL.OTF', + 'SYRegular' => 'SOURCEHANSANSCN-REGULAR.OTF', + 'yingbikaishu' => 'FZYBKS.ttf', + 'kaiti' => 'kaiti.ttf', + 'qianheijianti' => 'FZZQHJT.ttf', + 'zhunyuan' => 'FZZYJT.ttf', + 'zhunheijianti' => 'FZZZHJT.ttf', + 'dabiaosong' => 'FZDBSJT.ttf', + 'daheijianti' => 'FZDHJT.ttf', + 'cuyuan' => 'FZCYJT.ttf', + 'shaoer' => 'FZSRJT.ttf', + 'cusong' => 'FZCS_GBK.ttf', + 'songti' => 'simsun.ttf', + 'lishu' => 'LISHU.ttf', + 'xingkai' => 'HWXK.ttf', + 'jianyingbixingshu' => 'FZYBXSJT.ttf', + 'chaocuhei' => 'FZCCHJT.ttf', + 'cuqian' => 'FZCQJT.ttf', + 'jianmeihei' => 'MNJMH.ttf', + 'jianshuizhu' => 'MNJSZ.ttf', + 'jianxihei' => 'MNJXH.ttf', + 'minijiankaiti' => 'MNJKT.ttf', + 'minijianlibian' => 'MNJLB.ttf', + 'miaowuti' => 'FZMWT.ttf', + 'shuti' => 'FZSTK.TTF', + 'xiqian' => 'FZXQJT.ttf', + 'xiaobiaosong' => 'FZXBSJT.ttf', + 'yiheiti' => 'FZYHJT.ttf', + 'fangzhengzhanbiheijianti' => 'FZZBHJT.ttf', + 'zhengcuhei' => 'FZZCHJT.ttf', + 'zhiyiti' => 'FZZhiYiJT.ttf', + 'FZLTQH_GBK' => 'FZLTQH_GBK.TTF', + 'FZSHANGKJW' => 'FZSHANGKJW.TTF', + 'FZLTDH_GBK' => 'FZLTDH_GBK.ttf', + ); + } + + public static function getUrlFileContent($fileUrl, $retryTimes = 5, $timeOut = 120) { + $curl = self::getCurl($timeOut); + + for ($i = 1; $i <= $retryTimes; $i++) { + if(filter_var($fileUrl, FILTER_VALIDATE_URL) !== false) { + $imageData = $curl->get($fileUrl); + $info = $curl->getInfo(); + $after = $info['after']; + if (($after['http_code'] == 200) && ($after['download_content_length'] > 0) && ($after['download_content_length'] == strlen($imageData))) { + return $imageData; + } + + if(($after['http_code'] == 403)){ + $imageData = file_get_contents($fileUrl); + return $imageData; + } + } else { + $imageData = file_get_contents($fileUrl); + return $imageData; + } + + } + + return false; + } + + public static function camberTransToAngle($camber) { + return $camber * 180 / pi(); + } + + public static function isValidCsvType($type) { + if (in_array($type, array('application/vnd.ms-excel', 'application/octet-stream', 'application/csv', 'text/csv'))) { + return true; + } else { + return false; + } + } + + public static function isValidXlsxType($type) { + if (in_array($type, array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))) { + return true; + } else { + return false; + } + } + + public static function getRealOssUrl($imgUrl) { + if (Zc::C('isOssInternalDomain')) { + $imgUrl = str_replace(Zc::C('dy-honor-pub.domain'), Zc::C('dy-honor-pub.internal.domain'), $imgUrl); + } else { + $imgUrl = str_replace(Zc::C('dy-honor-pub.internal.domain'), Zc::C('dy-honor-pub.domain'), $imgUrl); + } + return $imgUrl; + } + + public static function getRandomString($length = 8) { + $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $charactersLength = strlen($characters); + $randomString = ''; + for ($i = 0; $i < $length; $i++) { + $randomString .= $characters[rand(0, $charactersLength - 1)]; + } + return $randomString; + } + + public static function getItemPluginUrl() { + if (Zc::C('env') == 'live') { + $jsUrl = HtmlTool::getStaticUrlPart(true); + } else { + $jsUrl = HtmlTool::getStaticUrlPart(); + } + + $jsUrl .= 'js/biz/empty_trash.js'; + return "javascript:void((function(){if($('#J_controlPane').length > 0){alert('此页面已加载插件');return false;} var d=document;e=d.createElement('script');e.setAttribute('id','J_MSEmptyTrash');e.setAttribute('charset','UTF-8');e.setAttribute('src','" . $jsUrl . "?'+Math.random());d.body.appendChild(e);})())"; + } + + public static function getCookieDomain() { + $host = $_SERVER['HTTP_HOST']; + if(filter_var($host, FILTER_VALIDATE_IP)) { + return $host; + } + + $domainArray = explode('.', $host); + $domainSize = count($domainArray); + if ($domainSize >= 3) { + return '.' . $domainArray[$domainSize - 3] . '.' . $domainArray[$domainSize - 2] . '.' . $domainArray[$domainSize - 1]; + } + if ($domainSize >= 2) { + return '.' . $domainArray[$domainSize - 2] . '.' . $domainArray[$domainSize - 1]; + } + return ''; + } + + public static function splitStrToArr($str) { + return array_unique(array_filter(array_map(function ($value) { + return trim($value); + }, preg_split('/,|,|;|;|\\s/isU', $str)))); + } + + + public static function chinaseNumToArabiaNum($string){ + $replaceMap = array( + '一' => '1', '二' => '2', '三' => '3', '四' => '4', '五' => '5', '六' => '6', '七' => '7', '八' => '8', '九' => '9', + '壹' => '1', '贰' => '2', '叁' => '3', '肆' => '4', '伍' => '5', '陆' => '6', '柒' => '7', '捌' => '8', '玖' => '9', + '零' => 0, '0' => 0, '十' => 0, + '两' => 2 + ); + foreach ($replaceMap as $cn => $num) { + $string = str_replace($cn, $num, $string); + } + return $string; + } + + public static function checkDdApiRetStatus($resp) { + $resp = (array)$resp; + if ($resp['success'] == true) { + return self::successResult(); + } else if ($resp['code'] == 504) { + return self::failCodeResult($resp['code'], $resp['msg'] . $resp['sub_msg'], '', '', $resp['log_id']); + } else if ($resp['code'] == 10000) { + return self::successResult(); + } else if ($resp['code'] == 400) { + return self::failCodeResult($resp['code'], $resp['msg'] . $resp['sub_msg'], '', '', $resp['log_id']); + } else if ($resp['code'] == 504) { + return self::failCodeResult($resp['code'], $resp['msg'] . $resp['sub_msg'], '', '', $resp['log_id']); + } else if ($resp['code'] == 505) { + return self::failCodeResult($resp['code'], $resp['msg'] . $resp['sub_msg'], '', '', $resp['log_id']); + } else if (isset($resp['code']) && $resp['code'] === 0) { + return self::failCodeResult($resp['code'], $resp['msg'] . $resp['sub_msg'], '', '', $resp['log_id']); + } else { + return self::failCodeResult($resp['code'], $resp['msg'] . $resp['sub_msg'], '', '', $resp['log_id']); + } + } + + public static function checkLtaoApiRetStatus($resp) { + $resp = (array)$resp; + if ($resp['code'] == 'success') { + return self::successResult(); + } else if (isset($resp['error_code'])) { + return self::failResult($resp['error_message']); + } else if (!isset($resp['code'])) { + return self::successResult(); + } else { + return self::failResult($resp['message']); + } + } + + public static function checkHasOtherKeyWord($word) { + if ((strpos($word, '其它') !== false) || (strpos($word, '其他') !== false) || (strpos($word, '通用') !== false)) { + return true; + } else { + return false; + } + } + + public static function mergeSpaces($string) { + return preg_replace("/\s(?=\s)/","\\1",$string); + } + + public static function substrAssignLen($string, $start, $length) { + return mb_substr($string, $start, $length, 'UTF-8'); + } + + private static function mbOrd($str, $from_encoding = false){ + $from_encoding = $from_encoding ? : 'UTF-8'; + + if (strlen($str) == 1) { + return ord($str); + } + + + $str = mb_convert_encoding($str, 'UCS-4BE', $from_encoding); + $tmp = unpack('N', $str); + return $tmp[1]; + } + + /** + * 抖店标题长度算法 + * @param $str + * @return false|float + */ + public static function countStringLength($str) { + $len = 0; + foreach (mb_str_split($str, 1, 'UTF-8') as $char) { + $ret = preg_match_all('/[\x{4e00}-\x{9fa5}]+/u', $char); + if ($ret) { + $len += mb_strwidth($char, 'utf-8'); + } else { + ++$len; + } + } + return $len; + } + + public static function cutTitle($title, $cutLen, $cutHead = false) { + $titleLen = self::countStringLength($title); + if ($cutLen >= $titleLen) { + return $title; + } + $cNum = 0; + $tmpTitle = ""; + + if ($cutHead) { + $tempStrArr = []; + foreach (mb_str_split($title, 1, 'UTF-8') as $char) { + $tempStrArr[] = $char; + } + $title = implode('', array_reverse($tempStrArr)); + } + + foreach (mb_str_split($title, 1, 'UTF-8') as $char) { + $len = self::countStringLength($char); + $cNum += $len; + if ($cNum > $cutLen) { + break; + } + $tmpTitle .= $char; + } + + if ($cutHead) { + $tempStrArr = []; + foreach (mb_str_split($tmpTitle, 1, 'UTF-8') as $char) { + $tempStrArr[] = $char; + } + $tmpTitle = implode('', array_reverse($tempStrArr)); + } + + + return $tmpTitle; + } + + public static function restoreRechargeOutTradeNo($outTradeNo) { + $tradeNoArray = explode('_', $outTradeNo); + return end($tradeNoArray); + } + + public static function getImgExt($imgUrl) { + $pathInfo = pathinfo($imgUrl); + return $pathInfo['extension']; + } + + public static function splitWithComma($keywordString) { + if (empty($keywordString)) { + return array(); + } + $splitArray = preg_split('/[,,\s\|;]/u', $keywordString); + return array_filter(array_map('trim', $splitArray)); + } + + public static function ensconceString($string, $type = '') { + if (empty($string)) { + return $string; + } + if ($type == 'mobile' && !preg_match('/^[0-9-\s]{6,}$/', $string)) { + $type = ''; + } + $newString = ''; + switch ($type) { + case 'mobile' : + $newString = substr_replace($string, '****', 3, 4); + break; + case 'sensitiveName': + $strlen = mb_strlen($string, 'utf-8'); + if ($strlen <= 2) { + $strBegin = mb_substr($string, 0, 1, 'utf-8'); + $newString = $strBegin . '*'; + } else { + $strBegin = mb_substr($string, 0, 1, 'utf-8'); + $strEnd = mb_substr($string, $strlen - 1, 1, 'utf-8'); + $newString = $strBegin . '*' . $strEnd; + } + break; + case 'sensitiveAddress': + $chineseNumAndNumMap = array( + '一' => '1', + '二' => '2', + '三' => '3', + '四' => '4', + '五' => '5', + '六' => '6', + '七' => '7', + '八' => '8', + '九' => '9', + '壹' => '1', + '贰' => '2', + '叁' => '3', + '肆' => '4', + '伍' => '5', + '陆' => '6', + '柒' => '7', + '捌' => '8', + '玖' => '9', + '零' => '0', + '十' => '10', + ); + $string = str_replace(array_keys($chineseNumAndNumMap), array_values($chineseNumAndNumMap), $string); + $hasNum = preg_match('/([0-9]){1}/', $string); + if ($hasNum) { + $newString = preg_replace('/([0-9])/', '*', $string); + } else { + $newString = $string; + } + break; + case 'sensitiveMobile': + $newString = substr_replace($string, '*******', 2, 7); + break; + default : + $strlen = mb_strlen($string, 'utf-8'); + if ($strlen >= 6) { + $strBegin = mb_substr($string, 0, 2, 'utf-8'); + $strEnd = mb_substr($string, $strlen - 2, 2, 'utf-8'); + $newString = $strBegin . '**' . $strEnd; + } elseif ($strlen <= 2) { + $strBegin = mb_substr($string, 0, 1, 'utf-8'); + $newString = $strBegin . '*'; + } else { + $strBegin = mb_substr($string, 0, 1, 'utf-8'); + $strEnd = mb_substr($string, $strlen - 1, 1, 'utf-8'); + $newString = $strBegin . '*' . $strEnd; + } + break; + } + return $newString; + } + + public static function buildDdProductUrl($productId) { + return sprintf('https://haohuo.jinritemai.com/views/product/detail?id=%s', $productId); + } + + public static function appendDdPreviewUrl(&$productList) { + foreach ($productList as &$product) { + $product['productUrl'] = self::buildDdProductUrl($product['product_id']); + } + } + + public static function processDdPrice(&$productList) { + foreach ($productList as &$productInfo) { + if ($productInfo['discount_price']) { + $productInfo['discount_price'] = $productInfo['discount_price'] / 100; + } + if ($productInfo['market_price']) { + $productInfo['market_price'] = $productInfo['market_price'] / 100; + } + if ($productInfo['sku_min_price']) { + $productInfo['sku_min_price'] = $productInfo['sku_min_price'] / 100; + } + if ($productInfo['sku_max_price']) { + $productInfo['sku_max_price'] = $productInfo['sku_max_price'] / 100; + } + } + } + + public static function buildDdOrderDetailUrl($orderId) { + return sprintf('https://fxg.jinritemai.com/index.html#/ffa/order/detail?id=%s', self::filterDdOrderIdSuffix($orderId)); + } + + public static function buildDdAftersaleDetailUrl($aftersaleId) { + return sprintf('https://fxg.jinritemai.com/ffa/morder/aftersale/detail-new?aftersale_id=%s', $aftersaleId); + } + + public static function filterDdOrderIdSuffix($orderId) { + return preg_replace('/A$/', '', $orderId); + } + + public static function filterDdOrderIdsSuffix($orderIds) { + if (!is_array($orderIds)) { + return self::filterDdOrderIdSuffix($orderIds); + } + foreach ($orderIds as &$orderId) { + $orderId = self::filterDdOrderIdSuffix($orderId); + } + return $orderIds; + } + + public static function batchFilterDdOrderIdsSuffix($orderIds) { + $newOrderIds = []; + foreach ($orderIds as $orderId) { + $newOrderIds[] = self::filterDdOrderIdSuffix($orderId); + } + return $newOrderIds; + } + + public static function rebuildDdOrderIdSuffix($orderId) { + $suffix = 'A'; + if (!preg_match('/' . $suffix . '$/', $orderId)) { + return $orderId . $suffix; + } + return $orderId; + } + + public static function rebuildDdOrderIdsSuffix($orderIds) { + $suffix = 'A'; + if (!is_array($orderIds)) { + if (!preg_match('/' . $suffix . '$/', $orderIds)) { + return $orderIds . $suffix; + } + return $orderIds; + } + array_walk($orderIds, function (&$currentOrderId, $key, $suffix) { + if (!preg_match('/' . $suffix . '$/', $currentOrderId)) { + $currentOrderId = $currentOrderId . $suffix; + } + }, $suffix); + return $orderIds; + } + + public static function createContactSellerLinkHtml($platform, $seller, $buyer, $orderSn) { + $contactSellerFactoryFuncs = array( + '1688' => function($seller, $buyer, $orderSn) { + $link = sprintf( + 'https://amos.alicdn.com/getcid.aw?v=3&groupid=0&s=1&charset=utf-8&uid=%s&site=%s&fromid=%s', + urlencode($seller), + 'cnalichn', + 'cnalichn'.urlencode($buyer) + ); + $icon = sprintf( + '', + urlencode($seller), + 'cnalichn' + ); + return array($link, $icon); + }, + 'jd' => function($seller, $buyer, $orderSn) { + $link = sprintf( + 'https://jdcs.jd.com/index.action?orderId=%s', + $orderSn + ); + $icon = ' 京东卖家'; + return array($link, $icon); + } + ); + if (!empty($contactSellerFactoryFuncs[$platform])) { + list($contactLink, $contactIcon) = $contactSellerFactoryFuncs[$platform]($seller, $buyer, $orderSn); + return '' . $contactIcon . ''; + } else { + return $seller; + } + } + + public static function getOperatorInfo() { + $operatorInfo = array( + 'mockAdminId' => $_SESSION[SessionConst::mockAdminId], + 'shopId' => $_SESSION[SessionConst::shopId], + 'ip' => self::clientIp(), + 'hostname' => gethostname(), + 'shopName' => $_SESSION[SessionConst::shopName], + 'currentUrl' => ZcUrlHelper::getCurrentUrl(false), + 'sessionId' => session_id() + ); + return $operatorInfo; + } + + public static function correctCentToYuan($price) { + return empty($price) ? 0 : round(($price / 100), 2); + } + + public static function sendTraceToDingTalk($msg) { + $stacks = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $methodTraceArr = array(); + unset ($stacks[0], $stacks[1], $stacks[2]); + foreach ($stacks as $stack) { + if (in_array($stack['function'], array('call_user_func_array', 'execute', 'dispatch', 'runMVC'))) { + continue; + } + $currClass = $stack['class']; + $curFunction = $stack['function']; + $methodTraceArr[] = $currClass . '->' . $curFunction; + } + + $methodTraceStr = json_encode($methodTraceArr); + self::sendDingTalkMsg('3bddab3fcdabc54225d1c2d5d50b427e111d8487c5ee589f6523adab49990ba9', $msg . $methodTraceStr . ','); + } + + public static function sendDingTalkMsg($accessToken, $msg, $atMobiles = [], $isAtAll = false, $title = "监控预警") { + $curl = self::getCurl(); + $headers = array ( + 'Content-Type: application/json', + ); + $curl->setCurlOpt(CURLOPT_HTTPHEADER, $headers); + + $dingdingRobotUrl = 'https://oapi.dingtalk.com/robot/send?access_token='.$accessToken; + $msgData = array( + 'title' => $title, + 'msgtype' => 'text', + 'text' => array( + 'content' => $msg, + ), + ); + if (!empty($atMobiles) || $isAtAll) { + $msgData['at'] = array ( + 'atMobiles' => $atMobiles ? : [], + 'isAtAll' => $isAtAll + ); + } + + $msgData = json_encode($msgData); + return $curl->post($dingdingRobotUrl, $msgData); + } + + public static function getAuthorizationUrl($appName = '') { + if (empty($appName)) { + $appName = Zc::C('appName'); + } + $authorizationUrlMap = [ + AppConst::appMsDdOd => 'https://fuwu.jinritemai.com/authorize?service_id=276&from=cy', + AppConst::appDd => 'https://fuwu.jinritemai.com/authorize?service_id=234&from=isv.authorize', + AppConst::appddmsV2 => 'https://fuwu.jinritemai.com/authorize?service_id=20771&from=yinliu', + ]; + return $authorizationUrlMap[$appName]; + } + + public static function getWatermarkTypeArr() { + return array( + WatermarkConst::batchWatermark, + WatermarkConst::moveWatermark, + ); + } + + public static function numberFormatAndDeleteUselessZero($number, $decimals = 2) { + return floatval(number_format($number, $decimals, '.', '')); + } + + public static function buildDdEditUrl($productId, $draft = false) { + $editUrl = 'https://fxg.jinritemai.com/index.html#/ffa/goods/create?product_id=' . $productId; + if ($draft) { + $editUrl .= '&entrance=draft'; + } + return $editUrl; + } + + public static function getWatermarkImageTypeArr() { + return array( + WatermarkConst::watermarkImageTypeDesc, + WatermarkConst::watermarkImageTypeMainImg + ); + } + + public static function rebuildProductListPrice($productList) { + foreach ($productList as &$product) { + $product['discount_price'] = $product['discount_price'] / 100; + $product['market_price'] = $product['market_price'] / 100; + $product['sku_min_price'] = $product['sku_min_price'] / 100; + $product['sku_max_price'] = $product['sku_max_price'] / 100; + } + + return $productList; + } + + public static function isOptionsRequest() { + return strcasecmp($_SERVER['REQUEST_METHOD'], 'OPTIONS') === 0; + } + + public static function getSkuCodeSelectRule() { + return array( + BatchConst::selectRuleSourceItemId => '来源商品ID', + BatchConst::selectRuleProductIdAndSpec1AndSpec2 => '商品ID+规格1+规格2', + BatchConst::selectRuleProductIdAndSpec1AndSpec2Num => '商品ID+规格1流水号+规格2流水号', + BatchConst::selectRuleItemNum => '货号', + BatchConst::selectRuleItemNumAndSpec1AndSpec2 => '货号+规格1+规格2', + BatchConst::selectRuleItemNumAndSpec1AndSpec2Num => '货号+规格1流水号+规格2流水号', + BatchConst::selectRuleItemNumAndNum => '货号+流水号', + BatchConst::selectRuleSpec1AndSpec2 => '规格1+规格2', + BatchConst::selectRuleSpec1AndSpec2Num => '规格1流水号+规格2流水号', + BatchConst::selectRulePlatformInitialAndSourceItemId => '来源平台首字母+来源ID' + ); + } + + public static function getAllowFastModeBatchTypeArr() { + return array( + + ); + } + + public static function getAllowPlanModeBatchTypeArr() { + return [ + ]; + } + + public static function getBatchModifyModeName($batchType) { + $modifyModeName = ''; + switch ($batchType) { + case BatchConst::batchTypePrice : + $modifyModeName = 'newPrice'; + break; + case BatchConst::batchTypeStock : + $modifyModeName = 'stockType'; + break; + default: + $modifyModeName = 'contentType'; + } + return $modifyModeName; + } + + public static function convertProductPluginReason($reason, $batchType = '') { + if (empty($reason)) { + return $reason; + } + $patterns = [ + "/^(类目属性填写不完整,)/", + "/^(商品属性\[.+\]填写格式不正确,)/", + "/^(.+为必填属性,且可选择的属性值不包括.+?,)/", + ]; + $url = Zc::url(RouteConst::productDetectDiagnose); + if ($batchType != BatchConst::batchTypeCategory) { + foreach ($patterns as $pattern) { + preg_match($pattern, $reason, $matches); + if (!empty($matches)) { + $reason = "{$matches[0]}您可以点击商品快速编辑修改或属性一键检测 立即前往"; + break; + } + } + } + + if ($reason == 'img数量不对') { + $reason = '图片数量不对'; + } + if (strpos($reason, '预售结束时间需设置在距今30天范围内') !== false) { + $url1 = Zc::url(RouteConst::productBatchIndex, ['batchType' => 'presell_time']); + $url2 = Zc::url(RouteConst::productBatchIndex, ['batchType' => 'presell_type']); + $reason = '预售结束时间已过期,预售结束时间需设置在距今30天范围内,你可以通过 延长预售结束时间 或将商品改为 现货模式后重试 '; + } + + if (strpos($reason, '主图数量少于3张') !== false) { + $url = Zc::url(RouteConst::productDetectImageNumDiagnose); + if(AppConst::isddmsV2()) { + $url = Zc::url(RouteAliasConst::productDetectImageNumDiagnose); + } + + return '主图数量少于3张,您可以用【主图数量不达标检测】批量补齐主图后再提交修改立即前往'; + } + + return $reason; + } + + public static function buildSkuSubName($specDetailNames, $symbol = '-') { + return implode($symbol, json_decode($specDetailNames, true)); + } + + public static function uploadMultipleFile($filename, $isMultiple, $target = 'temp', $name = null, $nameMap = false){ + @set_time_limit(0); + @ini_set('max_input_time', '-1'); + @ini_set('memory_limit', '512M'); + + // set tempdir + $target = Zc::C('temp.dir') . 'runtime/' . date('Y-m-d') . '/' . $target; + if (!is_dir($target)) { + mkdir($target, 755, true); + } + + $result = array(); + if ($isMultiple) { + $finfos = self::parseMultipleFile($filename); + } else { + $finfos[] = $_FILES[$filename]; + } + foreach ($finfos as $finfo) { + $file = array ( + 'name' => $finfo['name'], + 'type' => $finfo['type'], + 'size' => $finfo['size'], + 'tmp_name' => $finfo['tmp_name'] + ); + $fpath = $target; + if (is_uploaded_file($file['tmp_name'])) { + if (substr($fpath, -1) != '/') { + $fpath .= '/'; + } + if($name) { + $pathInfo = pathinfo($file['name']); + $name = $name . '.' . $pathInfo['extension']; + $fpath .= $name; + } else { + $fpath .= $file['name']; + } + move_uploaded_file($file['tmp_name'], $fpath); + // 文件路径 + if ($nameMap) { + $result[$name ?: $file['name']] = $fpath; + } else { + $result[] = $fpath; + } + } + } + return $result; + } + + public static function getDdImageDomains() { + $ddImageDomains = array ( + 'sf1-ttcdn-tos.pstatp.com', + 'sf3-ttcdn-tos.pstatp.com', + 'sf6-ttcdn-tos.pstatp.com', + ); + return $ddImageDomains; + } + + public static function tryChangeDdImgDomain($imgUrl, $itt) { + if (stripos($imgUrl, 'pstatp.com') === false) { + return $imgUrl; + } + $ps = parse_url($imgUrl); + $currDomain = $ps['host']; + + $jdImageDomains = self::getDdImageDomains(); + $changeDomain = $jdImageDomains[abs($itt - 1) % count($jdImageDomains)]; + + $newImgUrl = str_replace($currDomain, $changeDomain, $imgUrl); + return $newImgUrl; + } + + public static function getOuterIdSelectRule() { + return array( + BatchConst::selectRuleProductIdAndSpec1AndSpec2 => '商品编码+规格1+规格2', + BatchConst::selectRuleProductIdAndSpec1AndSpec2Num => '商品编码+规格1流水号+规格2流水号', + BatchConst::selectRuleSpec1AndSpec2 => '规格1+规格2', + BatchConst::selectRuleSpec1AndSpec2Num => '规格1流水号+规格2流水号', + BatchConst::selectRuleItemNumAndSpec1AndSpec2 => '货号+规格1+规格2', + BatchConst::selectRuleItemNumAndSpec1 => '货号+规格1', + BatchConst::selectRuleItemNumAndSpec2 => '货号+规格2', + BatchConst::selectRuleItemNumAndSpec1AndSpec2Num => '货号+规格1流水号+规格2流水号', + BatchConst::selectRuleItemNumAndNum => '货号+流水号', + ); + } + + public static function getSpyShopIds() { + $shopIds = array(); + + return $shopIds; + } + + public static function getSpyLoginIps() { + $ips = array( + '115.236.53.210', //快麦旗舰店 + + '125.71.163.199', //枫蓝之家家居用品旗舰店 + '171.213.62.200', //daheima男鞋旗舰店 + '171.213.62.245', //daheima男鞋旗舰店 + '121.204.134.182', // 百思宜旗舰店 + + '123.118.3.69', //献世旗舰店 /情报360 + '58.250.252.120', //献世旗舰店 /情报360 + + '113.80.59.30', //络曼灯饰照明旗舰店 / 金豆云、质子魔方 + '171.221.131.251', //浪莎千帛专卖店、靖捷服饰专营店 / 金豆云、质子魔方 + '125.71.162.188', //daheima男鞋旗舰店 /金豆云、质子魔方 + '171.213.60.148', //瑞嘉玺影音娱乐专营店 /金豆云、质子魔方 + //'59.42.109.216', //帝兆服饰专营店 /金豆云、质子魔方 20191017注释 + '125.71.160.234', //枫蓝之家家居用品旗舰店 /金豆云、质子魔方 + '220.249.69.60', //格瑞雅居家居用品旗舰店 /金豆云、质子魔方 + '58.48.82.61', //诺必行数码旗舰店(卖家,号借给金豆云顶帖) + '110.184.151.2',//千汇服装专营店(卖家,号借给金豆云顶帖) + '119.96.253.49', //瑞嘉玺汽车用品专营店 /金豆云、质子魔方 + + '119.137.5.122', //创跃线材专营店 /智云管家 + '59.40.229.79', //哈达旗舰店/智云管家 + '183.39.175.231', //尚线大迈运动专营店 /智云管家 + '112.11.42.48', //佳龙童车专营店 /智云管家 + '112.109.150.177', //美丽的由来官方旗舰店、鑫惠豪旗舰店 /智云管家 + + '222.77.52.247', //童梭官方旗舰店,哈里顿箱包专营店 /牛盾、泰文 + '125.78.11.101', //滕泰鞋类专营店 /牛盾、泰文 + '117.24.72.207', //云中城服饰专营店 /牛盾、泰文 + + '113.107.24.186', //韩萨旗舰店, 开心礼物Happy Gift旗舰店, Venmer帷魅旗舰店 /京牛 + '223.102.1.162', //大连泊源科技有限公司测试店铺 /好麦 + '58.38.1.207', //青岛啤酒海帆专卖店 / 搬家宝 + '58.100.8.162', //顺熙辰官方旗舰店 /搬家宝 + '58.100.203.24', //顺熙辰官方旗舰店 /搬家宝 + + '183.134.110.210', //快麦旗舰店 / 超级妙手V2 + + '183.67.48.22', //扫图神盾 / 超级妙手V2 + + '221.218.210.200', //亿商汇食品专营店 / 生e无忧 + '220.112.193.71', //熊大深圳长城宽带 授权店 A.J.BB服装旗舰店 + '183.13.216.3', //熊大深圳电信 授权店 九月服饰专营店 + '113.110.202.151', //熊大深圳电信 授权店 郁渟服饰旗舰店 + '121.35.187.172', //熊大深圳电信 授权店 郁汀服饰旗舰店 + '111.222.21.112', //熊大深圳电信 九月女装专营店 + '171.221.142.36', //熊大成都电信 心仪宝女装专营店 + '111.147.162.212', //熊大 福建省南平市 妖精的家居日用拼购店,妖精的美妆拼购店 + '171.213.12.79', //熊大成都电信 九月女装专营店 + '118.112.61.198', //熊大成都电信 去年攻击我们的ip + '118.112.58.85', //熊大成都电信 去年攻击我们的ip2 + '118.112.154.61', //熊大成都电信 去年攻击我们的ip3 + '221.237.116.87' //熊大成都电信 去年攻击我们的ip4 + ); + return $ips; + } + + public static function isSpyShop($shopId) { + if (empty($shopId)) { + $shopId = $_SESSION[SessionConst::shopId]; + } + $spyShopIds = self::getSpyShopIds(); + $spyLoginIps = self::getSpyLoginIps(); + $curIp = CommonTool::clientIp(); + if (in_array($shopId, $spyShopIds) || in_array($curIp, $spyLoginIps)) { + return true; + } else { + return false; + } + } + + public static function isExtSpyShop($shopId, $denyCityMap) { + if (self::isSpyShop($shopId)) { + return true; + } + if (empty($shopId)) { + $shopId = $_SESSION[SessionConst::shopId]; + } + + $geoCity = $_SESSION[SessionConst::geoIpArea]['city']; + if (empty($geoCity)) { + return true; + } +// $denyCityMap = !empty($denyCityMap) ? $denyCityMap : array('成都', '厦门', '大连'); +// foreach ($denyCityMap as $city) { +// if (stripos($geoCity, $city) !== false){ +// return true; +// } +// } + + return false; + } + + /** + * 根据EXCEL列数字编码获取列字母符号 + * @param int $column + * @return boolean|string + */ + public static function getExcelColumnChar($column) { + if (!is_int($column) || $column <= 0) { + return false; + } + $chars = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']; + $char_num = ceil($column / 26); + $char = ''; + if ($char_num > 1) { + $char .= $chars[$char_num - 2]; + } + + $last_index = (($column - 1) % 26); + $char .= $chars[$last_index]; + + return $char; + } + + + public static function mapArray($map, $keys) { + $array = []; + foreach($keys as $key) { + $array[] = $map[$key]; + } + return $array; + } + + public static function pregSplitAndFilterStr($str) { + $valueArr = preg_split('/[,,]/isUu', $str); + $valueArr = array_map(function ($value) { + return trim($value); + } , $valueArr); + $valueArr = array_filter($valueArr); + $valueArr = array_unique($valueArr); + + return $valueArr; + } + + public static function moveSettingFieldMap() { + return [ + 'moveOnsaleType' => '上架设置/类目/品牌', + 'default' => '发货模式/发货时间/支付/库存扣减', + 'itemCode' => '货号/SKU商家编码/库存', + 'mobile' => '客服电话/运费模板', + 'img' => '主图/详情描述/SKU颜色图', + 'video' => '主图视频/白底图/长图', + 'price' => '价格设置/引流SKU', + 'title' => '标题/SKU别名', + 'recommendRemark' => '推荐语/同店商品推荐', + 'service' => '限购/违禁词', + ]; + } + + public static function safeArrayMerge($arr1, $arr2) { + $arr1 = is_array($arr1) ? $arr1 : []; + $arr2 = is_array($arr2) ? $arr2 : []; + return array_merge($arr1, $arr2); + } + + public static function buildSelectedShopMap($shopCountMap, $leftCount) { + shuffle($shopCountMap); + if (empty($shopCountMap)) { + return array (); + } + $selectedUserMap = array (); + + $allocCount = 0; + $markFullIdxList = array (); + $loop = true; + while (true) { + foreach ($shopCountMap as $vc) { + $selectShopId = $vc['shop_id']; + $cnt = $vc['cnt']; + + if (empty($selectShopId) || empty($cnt)) { + continue; + } + + if (in_array($selectShopId, $markFullIdxList)) { + continue; + } + + if (isset($selectedUserMap[$selectShopId])) { + $selectedUserMap[$selectShopId]++; + } else { + $selectedUserMap[$selectShopId] = 1; + } + $allocCount++; + if ($allocCount == $leftCount) { + $loop = false; + break; + } + if ($selectedUserMap[$selectShopId] == $vc['cnt']) { + $markFullIdxList[] = $selectShopId; + } + if (count($markFullIdxList) == count($shopCountMap)) { + $loop = false; + break; + } + } + if (!$loop) { + break; + } + } + + return $selectedUserMap; + } + + public static function featureRecommendGroupMap() { + return [ + 'recommend' => '常用功能', + 'move' => '商品上货', + 'edit' => '商品管理', + 'quantity' => '营销引流', + 'system_recommend' => '推荐功能', + 'image_tool' => '图片工具', + 'ddmsV2_user_defined' => '妙手V2自定义功能模块', + ]; + } + + public static function getExportOrderNeedVerifyCount($shopId) { + if (self::isCurrAdminSelfShop($shopId)) { + return 10; + } else { + return 100; + } + } + + public static function correctYuanToCent($price) { + return empty($price) ? 0 : round(($price * 100), 0); + } + + public static function getDiffTime() { + static $startTime; + if (empty($startTime)) { + $startTime = ZcNumberHelper::microtimeFloat(3); + } + + $endTime = ZcNumberHelper::microtimeFloat(3); + $diff = bcsub($endTime, $startTime, 3); + $startTime = $endTime; + return $diff; + } + + public static function fastArrayDiff($arraya, $arrayb) { + foreach ($arraya as $keya => $valuea) + { + if (in_array($valuea, $arrayb)) + { + unset($arraya[$keya]); + } + } + return $arraya; + } + + public static function calChineseStockNum($stockNum) { + if (preg_match('#^[0-9]*$#isU', $stockNum)) { + return $stockNum; + } + if (preg_match('#[\d\s]百$#isU', $stockNum)) { + return (int)$stockNum * 100; + } + if (preg_match('#[\d\s]千$#isU', $stockNum)) { + return (int)$stockNum * 1000; + } + if (preg_match('#[\d\s]万$#isU', $stockNum)) { + return (int)$stockNum * 10000; + } + + return false; + } + + public static function getCurlNew($timeout = 5, $setopt = array(), $forceNew = false) { + static $curlNewMap = null; + $cacheKey = $timeout . md5(serialize($setopt)); + $curl = $curlNewMap[$cacheKey]; + if (empty($curl) || $forceNew === true) { + Zc::import('zc.vendors.YwCurl'); + $setopt['timeOut'] = $timeout; + $setopt['ssl'] = true; + $curl = new YwCurl($setopt); + if(empty($setopt['header'])) { + $headers = array( + 'Connection: keep-alive', + 'Cache-Control: max-age=0', + 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36', + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Encoding: gzip,deflate,sdch', + 'Accept-Language: zh-CN,zh;q=0.8,de;q=0.6,en;q=0.4,es;q=0.2,nl;q=0.2,pt;q=0.2,ru;q=0.2,zh-TW;q=0.2,fr;q=0.2,ja;q=0.2' + ); + } + $curl->setCurlOpt(CURLOPT_HTTPHEADER, $headers); + $curlNewMap[$cacheKey] = $curl; + } + + return $curl; + } + + public static function convertValToArray($val) { + if (is_string($val)) { + return self::splitWithComma($val); + } + return $val; + } + + public static function rebuildFilterProvinceIds($provinceIds) { + $provinceIds = self::convertValToArray($provinceIds); + + $newProvinceIds = []; + foreach ($provinceIds as $provinceId) { + $newProvinceIds[] = $provinceId; + $newProvinceIds[] = (int)($provinceId . '0000'); + } + + return $newProvinceIds; + } + + public static function getOneRandomAiPsAutoDomain(){ + $aiPsAutoDomainList = Zc::C('ai-ps-auto.domain.list'); + $randomNum = array_rand($aiPsAutoDomainList, 1); + return $aiPsAutoDomainList[$randomNum]; + } + + public static function getOneRandomAiOcrAutoDomain(){ + $aiOcrAutoDomainList = Zc::C('ai-ocr-auto.domain.list'); + $randomNum = array_rand($aiOcrAutoDomainList, 1); + return $aiOcrAutoDomainList[$randomNum]; + } + + public static function rgbToHex($rgb){ + if (empty($rgb)) { + return ''; + } + $regexp = "/^rgb\(([0-9]{0,3})\,\s*([0-9]{0,3})\,\s*([0-9]{0,3})\)/"; + $re = preg_match($regexp, $rgb, $match); + $re = array_shift($match); + $hexColor = "#"; + $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); + for ($i = 0; $i < 3; $i++) { + $r = null; + $c = $match[$i]; + $hexAr = array(); + while ($c > 16) { + $r = $c % 16; + $c = ($c / 16) >> 0; + array_push($hexAr, $hex[$r]); + } + array_push($hexAr, $hex[$c]); + $ret = array_reverse($hexAr); + $item = implode('', $ret); + $item = str_pad($item, 2, '0', STR_PAD_LEFT); + $hexColor .= $item; + } + + return $hexColor; + } + + public static function downloadAndZipByNetworkImgs($downloadImgs, $zipName) { + $tmpDir = Zc::C('temp.dir') . 'temp/download/'; // 类似于/www/public/upload/ + + if (!file_exists($tmpDir)) { + //创建文件夹 + mkdir($tmpDir, 0777, true); + } + + $zipNameUrl = $tmpDir . date ( 'YmdHis' ) . mt_rand(1000,9999) .'.zip'; + + // 生成文件 + $zip = new \ZipArchive(); + if ($zip->open($zipNameUrl, \ZipArchive::OVERWRITE) !== true) { + //OVERWRITE 参数会覆写压缩包的文件 文件必须已经存在 + if ($zip->open($zipNameUrl, \ZipArchive::CREATE) !== true) { + // 文件不存在则生成一个新的文件 用CREATE打开文件会追加内容至zip + return '下载失败,文件夹不存在'; + } + } + + foreach ($downloadImgs as $imgInfo) { + $name = $imgInfo['name']; + $imageData = $imgInfo['imageData']; + $imageUrl = $imgInfo['imgUrl']; + + if (empty($imageData)) { + //抓取图片内容 + $imageDataRet = self::getImageDataFromUrl($imageUrl); + if (CommonTool::isFailRet($imageDataRet)) { + continue; + } + $imageData = $imageDataRet['imageData']; + } + //添加图片 + $zip->addFromString($name, $imageData); + } + // 关闭 + $zip->close(); + + //没有文件 + if (!file_exists($zipNameUrl)) { + return '下载失败,图片不存在或无法下载'; + } + + header("Cache-Control: public"); + header("Content-Description: File Transfer"); + header('Content-disposition: attachment; filename=' . $zipName); //文件名 + header("Content-Type: application/zip"); //zip格式的 + header("Content-Transfer-Encoding: binary"); //告诉浏览器,这是二进制文件 + header('Content-Length: ' . filesize($zipNameUrl)); //告诉浏览器,文件大小 + + // 下面2步必须要 + ob_clean(); + flush(); + + @readfile($zipNameUrl); + unlink($zipNameUrl); // 删除文件 + exit; + } + + public static function arraySortByKey($data, $key, $sortType = SORT_ASC) { + $sortBy = array_column($data, $key); + array_multisort($sortBy, $sortType, $data); + return $data; + } + + /** + * 提取描述图片地址 + * @param string $string 描述 + */ + public static function extractNotesImgUrls($notes) { + $pattern = '/(?:\ssrc\s?=\s?(?:"|\')|background\s?\((?:\'|")|background\s?=\s?(?:"|\'))([^\'"]+)(?:"|\'|\))/Uis'; + preg_match_all($pattern, $notes, $matches); + $imgUrls = $matches[1]; + + if (empty($imgUrls)) { + preg_match_all('/\s+src=\s*((http|\/\/)[\/\.:0-9a-z]*\.(jpg|png|jpeg))/isU', $notes, $matches); + $imgUrls = $matches[1]; + } + + if (!empty($tmpImgUrls)) { + foreach ($tmpImgUrls as $imgUrl) { + $imgUrl = (strtolower(substr($imgUrl, 0, 4)) == 'http') ? $imgUrl : ('http:' . $imgUrl); + $imgUrls[] = $imgUrl; + } + } + + return $imgUrls; + } + + public static function updateProductImgDomain($imgUrl) { + if (strpos($imgUrl, 'cdn-tos.pstatp.com/obj') !== false) { + preg_match('#https://(.*)/obj#', $imgUrl, $match); + $newImgUrl = str_replace($match[1], 'lf3-cm.ecombdstatic.com', $imgUrl); + } + + if (strpos($imgUrl, 'cdn-tos.pstatp.com/img') !== false) { + preg_match('#https://(.*)/img#', $imgUrl, $match); + $newImgUrl = str_replace($match[1], 'p3-aio.ecombdimg.com', $imgUrl); + } + + if (strpos($imgUrl, 'p3.pstatp.com') !== false) { + $newImgUrl = str_replace('p3.pstatp.com', 'p3-aio.ecombdimg.com', $imgUrl); + } + + if (strpos($imgUrl, 'p3a.pstatp.com') !== false) { + $newImgUrl = str_replace('p3a.pstatp.com', 'p3-aio.ecombdimg.com', $imgUrl); + } + + if (date('Ymd') > 20211101) { + // 用于抖店202110月修改图片域名,讲道理11月之后可以删除此方法,后续如果没有以下log可以删除此方法及其调用 + Zc::getLog('common/tool/updateProductImgDomain')->info('1'); + } + + if(!preg_match('/^http(s)?:\\/\\/.+/', $imgUrl)){ + $newImgUrl = 'https:' . $imgUrl; + } + return $newImgUrl ? $newImgUrl : $imgUrl; + } + + public static function ddImgUrlToPath($imgUrl) { + $imgUrl = CommonTool::updateProductImgDomain($imgUrl); + if (strpos($imgUrl, '-aio.ecombdimg.com/obj/ecom-shop-material/') !== false) { + return explode('/ecom-shop-material/', $imgUrl)[1]; + } else { + return $imgUrl; + } + } + + public static function batchDdImgUrlToPath($imgUrls) { + if ($imgUrls) { + foreach ($imgUrls as &$imgUrl) { + $imgUrl = CommonTool::ddImgUrlToPath($imgUrl); + } + } + return $imgUrls; + } + + public static function ddImgPathToUrl($imgPath) { + if (empty(parse_url($imgPath)['host'])) { + return HelpConst::imgUrlPrefix . 'ecom-shop-material/' . $imgPath; + } + return $imgPath; + } + + public static function batchDdImgPathToUrl($imgPaths) { + if ($imgPaths) { + foreach ($imgPaths as &$imgPath) { + $imgPath = CommonTool::ddImgPathToUrl($imgPath); + } + } + return $imgPaths; + } + + public static function checkIsForceNewPlugin($shopId, $percent = 0) { + return ($shopId % 100) < $percent; + } + + public static function encryptRemoteLoginDdodToken($text) { + $string = \Dcrypt\Mcrypt::encrypt(json_encode($text), Zc::C('acn.ds.token')); + return base64_encode($string); + } + + public static function fetchItemNeedProxyImgUrl() { + return ['591wx', 'yedemall', 'yunchepin', 'mmgg', 'zlycw']; + } + + public static function analyzeProductId($postProductId) { + $productIds = array(); + if (!empty($postProductId)) { + $postProductIds = array_map('trim', preg_split( "/,|,|\\s/", $postProductId)); + foreach ($postProductIds as $key => $productId){ + $productId = trim($productId); + if(empty($productId)){ + continue; + } + $productIds[] = $productId; + } + } + + return array_unique($productIds); + } + + public static function forbidCopySourceShopNameKeywordArr() { + return ['原创', '实拍', '独家', '同款', '正品', '专柜', '代购', '自制', '老字号', '专利']; + if (AppConst::isddmsV2()) { + return ['原创', '代购', '独家', '自制', '正品', '专柜' ,'同款', '老字号']; + } + if (strpos($shopName, '旗舰店') !== false || strpos($shopName, '专卖店') !== false || strpos($shopName, '专营店') !== false) { + return ['原创', '代购', '独家', '自制', '正品', '专柜' ,'同款', '老字号']; + } + + return ['旗舰店', '专营店', '专卖店', '原创', '代购', '独家', '自制', '正品', '专柜' ,'同款', '老字号']; + } + + public static function getToCWebsite() { + $toCWebsite = FetchClientTool::getToCWebsite(); + $newToCWebSite = []; + foreach ($toCWebsite as $source) { + if(in_array($source, [FetchClientConst::collectTaskSourceJd])) { + continue; + } + $newToCWebSite[] = $source; + } + + return $newToCWebSite; + } + + public static function isAnimatedGif($imageData) { + $animated = preg_match('#(\x00\x21\xF9\x04.{4}\x00\x2C.*){2,}#s', $imageData); + if ($animated != 1) { + $animated = (strpos($imageData, chr(0x21) . chr(0xff) . chr(0x0b) . 'NETSCAPE2.0') === false) ? 0 : 1; + } + + return ($animated == 1); + } + + public static function convertImageToJpg($imageData) { + $image = imagecreatefromstring($imageData); + $width = imagesx($image); + $height = imagesy($image); + + $bg = imagecreatetruecolor($width, $height); + imagefill($bg, 0, 0, imagecolorallocate($bg, 255, 255, 255)); + imagealphablending($bg, true); + imagecopy($bg, $image, 0, 0, 0, 0, $width, $height); + imagedestroy($image); + + $quality = 95; // 0 = worst / smaller file, 100 = better / bigger file + $newJpgFilePath = sys_get_temp_dir() . '/' . uniqid() . '.jpg'; + imagejpeg($bg, $newJpgFilePath, $quality); + imagedestroy($bg); + + $imageData = file_get_contents($newJpgFilePath); + unlink($newJpgFilePath); + return $imageData; + } + + public static function isGifImage($imgUrls) { + if (empty($imgUrls)) { + return false; + } + if(!is_array($imgUrls)) { + $imgUrls = [$imgUrls]; + } + static $rim; + if (empty($rim)) { + Zc::import('@.vendor.rim.rim'); + $rim = new rim(); + } + + $imageInfos = $rim->getMultiImageTypeAndSize($imgUrls); + foreach ($imageInfos as $info) { + $imgData = $info['image_data']; + if($imgData['type'] == 'gif') { + return true; + } + } + + return false; + } + + public static function moveMustUseSourceBrandTBCid() { + return [50010404, 16, 1625, 30, 122650005, 50022517, 50006842, 50011740, 50006843, 50510002, 50011699, 50012029, 50008165]; + } + + public static function checkProductIsSale($status, $checkStatus) { + return ($status == ProductStatusConst::onSale) && ($checkStatus == ProductStatusConst::checkSuccess); + } + + public static function arraySort($array, $keys, $sort='asc') { + $newArr = $valArr = array(); + foreach ($array as $key=>$value) { + $valArr[$key] = $value[$keys]; + } + + ($sort == 'asc') ? asort($valArr) : arsort($valArr); + reset($valArr); + + foreach($valArr as $key=>$value) { + $newArr[$key] = $array[$key]; + } + return $newArr; + } + + public static function getStrGbkEncodeLen($str) { + $pageEncode = mb_detect_encoding('编码', array('ASCII', 'UTF-8', 'GB2312', 'GBK','BIG5')); + $gbkStr = CommonTool::convertEncoding($str, 'GBK', $pageEncode); + return strlen($gbkStr); + } + + public static function getNewRoute($route) { + $oldUrlAndNewUrlMap = RouteAliasConst::ddmsV2OldUrlAndNewUrlMap(); + if(isset($oldUrlAndNewUrlMap[$route])) { + $route = $oldUrlAndNewUrlMap[$route]; + } + + return $route; + } + + public static function isNeedLimitMove() { + if (AppConst::isddmsV2()) { + return true; + } + + return false; + } + + public static function buildSign($data, $token) { + asort($data); + return md5(sha1(http_build_query($data) . $token)); + } + + public static function attachSign($data, $token) { + $data['sign'] = self::buildSign($data, $token); + return $data; + } + + public static function checkSign($data, $token) { + $sign = $data['sign'] ?: ''; + unset($data['sign']); + return $sign && $sign === self::buildSign($data, $token); + } + + public static function unifiedDateFormat($date, $format){ + $timeStamp = strtotime($date); + if( $timeStamp ){ + return date($format, $timeStamp); + } + $oriFormat = ''; + if(strpos($date, '.') !== false){ + $oriFormat = 'Y.m.d'; + }else if (strpos($date, '年') !== false && strpos($date, '月') !== false && strpos($date, '日') !== false){ + $oriFormat = 'Y年m月d日'; + } + return date_format(date_create_from_format($oriFormat, $date), $format); + } + + public static function buildTimeFormatBySecond($time){ + $minute = '00'; + $second = floor($time); + if(floatval($time) > 60){ + $minute = sprintf("%02d", floor($time / 60)); + $second = sprintf("%02d", floor($time % 60)); + } + + return sprintf('%s:%s', $minute, $second); + } + + public static function getImageWidthHeight($imageUrl) { + $imageDataRet = self::getImageDataFromUrl($imageUrl); + if (CommonTool::isFailRet($imageDataRet)) { + return array(null, null); + } + + try { + $imageData = $imageDataRet['imageData']; + $imagine = new Imagine\Gd\Imagine(); + /*@var $image Imagine\Gd\Image */ + $image = $imagine->load($imageData); + $size = $image->getSize(); + + $oriWidth = $size->getWidth(); + $oriHeight = $size->getHeight(); + } catch (Exception $ex) { + $log = Zc::getLog('img_load_error'); + $log->info("Imagine LoadImgDataError ImgUrl {$imageUrl} and Exception : " . $ex->getMessage()); + + return array(null, null); + } + + return array($oriWidth, $oriHeight); + } + + public static function isShowYiketu() { + return true; + $ip = CommonTool::clientIp(); + $num = array_sum(explode('.', $ip)); + $randNum = substr($num, strlen($num) - 1); + if ($randNum < 5) { + return true; + } + if ($_SESSION[SessionConst::shopId] == '16412356') { + return true; + } + return false; + } + + public static function getRemoteAiOcrText($imgUrl, ZcLog $log) { + $sign = md5(Zc::C('ai-ps.matting.token') . $imgUrl); + $postData = [ + 'img_url' => $imgUrl, + 'sign' => $sign + ]; + + $aiOcrAutoDomain = self::getOneRandomAiOcrAutoDomain(); + $ocrUrl = $aiOcrAutoDomain . '/ocr'; + $curl = self::getCurl(30); + for ($i = 0; $i <= 0; $i++) { + $orcRetJson = $curl->post($ocrUrl, $postData); + $log->info('-------orcRetJson------' . $orcRetJson); + + $orcRet = json_decode($orcRetJson, true); + if ((json_last_error() != JSON_ERROR_NONE) || empty($orcRet)) { + continue; + } + if (CommonTool::isFailRet($orcRet)) { + continue; + } + + return $orcRet; + } + + return CommonTool::failResult('调用OCR接口失败'); + } + + public static function decompressZipToFile($fileName){ + $fileNameArr = explode('/', $fileName); + unset($fileNameArr[count($fileNameArr) - 1]); + $folder = implode('/', $fileNameArr); + $zipFile = new \PhpZip\ZipFile(); + try { + $zipFile + ->openFile($fileName) // open archive from file + ->extractTo($folder); + $zipFile->close(); + unlink($fileName); + return CommonTool::successResult(['folder' => $folder]); + } catch (\PhpZip\Exception\ZipException $e) { + return self::failResult($e->getMessage()); + } + } + + public static function getFilesByFolder($folder, $formats){ + if(stripos($folder, Zc::C('temp.dir')) !== 0){ + return CommonTool::failResult('只能处理temp目录'); + } + + if(!file_exists($folder)){ + return CommonTool::failResult('文件夹不存在'); + } + + chmod($folder, 0755); + try { + $files = []; + $handle = opendir($folder); + if ($handle === false) { + return CommonTool::failResult('没有权限'); + } + while(($file = readdir($handle)) !== false) { + if($file != '.' && $file != '..'){ + $curPath = $folder . DIRECTORY_SEPARATOR . $file; + if(is_dir($curPath)){ + continue; + } + + $strArr = explode('.', $file); + $type = strtolower(end($strArr)); + if(!in_array($type, $formats)){ + continue; + } + + array_push($files, $curPath); + } + } + closedir($handle); + return CommonTool::successResult('files', $files); + } + catch (Exception $e) { + return CommonTool::failResult($e->getMessage()); + } + } + + private static function parseMultipleFile($filename){ + $files = array(); + foreach ($_FILES[$filename] as $parameterName => $parameterValues) { + $i = 0; + foreach ($parameterValues as $parameterValue) { + $files[$i][$parameterName] = $parameterValue; + $i++; + } + } + return $files; + } + + public static function buildSearchSameItemUrl($imgUrl) { + return sprintf('https://s.1688.com/selloffer/similar_search.html?offerIds=0&imageAddress=%s', urlencode($imgUrl)); + } + + public static function checkTipLimitToCWebsite($source) { + $limitToCWebsite = FetchClientTool::getLimitToCWebsite(); + return $limitToCWebsite[$source] ? true : false; + } + + public static function underScoreToCamelCaseArr($arr) { + if (!is_array($arr)) { + return $arr; + } + $newArr = []; + foreach ($arr as $key => $value) { + $newKey = self::underScoreToCamelCaseStr($key); + $newVal = self::underScoreToCamelCaseArr($value); + $newArr[$newKey] = is_null($newVal) ? '' : $newVal; + } + return $newArr; + } + + public static function underScoreToCamelCaseStr($str) { + $array = explode('_', $str); + $result = $array[0]; + $len = count($array); + if($len>1) + { + for($i=1;$i<$len;$i++) + { + $result.= ucfirst($array[$i]); + } + } + return $result; + } + + public static function camelCaseToUnderScoreArr($arr){ + if (!is_array($arr)) { + return $arr; + } + + $newArr = []; + $userDefindMap = [ + 'copy1688CidOnly' => 'copy_1688_cid_only', + 'supply7dayReturn' => 'supply_7day_return', + 'skip3cProduct' => 'skip_3c_product', + ]; + foreach ($arr as $key => $value) { + if ($userDefindMap[$key]) { + $key = $userDefindMap[$key]; + } else { + $key = self::camelCaseToUnderScoreStr($key); + } +// $value = self::camelCaseToUnderScoreArr($value); //因为这个只给保存搬家配置用,所以要隐藏,谁开启了谁注意下搬家配置 + $newArr[$key] = $value; + } + return $newArr; + } + + + public static function camelCaseToUnderScoreStr($str) { + $dstr = preg_replace_callback('/([A-Z]+)/',function($matchs) + { + return '_'.strtolower($matchs[0]); + },$str); + return trim(preg_replace('/_{2,}/','_',$dstr),'_'); + } + + public static function arrayChangeIntValueMoreThen13ToStr($data) { + foreach ($data as &$value) { + if(is_array($value)) { + $value = self::arrayChangeIntValueMoreThen13ToStr($value); + } else { + if(is_numeric($value) && strlen($value) > 13) { + $value = (string) $value; + } + } + } + + return $data; + } + + public static function uploadImageUrlToOss($imageUrl, $imageData = '') { + if(empty($imageData)) { + $getRet = CommonTool::getImageDataFromUrlUseProxy($imageUrl, 3); + if (CommonTool::isFailRet($getRet)) { + return $getRet; + } + + $imageData = $getRet['imageData']; + } + + $ext = CommonTool::getImageExtendByData($imageData); + if (!in_array($ext, array ('png','gif','jpg','jpeg'))) { + return CommonTool::failResult("只允许上传png, gif, jpg, jpeg格式的图片"); + } + + $ossPath = sprintf('temp/%s/%s.%s', date('Y-m-d'), CommonTool::getUuidName(), $ext); + $ret = OssTool::uploadImmutableObjectByContent($ossPath, $imageData); + if (CommonTool::isFailRet($ret)) { + return $ret; + } + + return CommonTool::successResult([ + 'src' => OssTool::getPubOssUrlByOssPath($ossPath), + 'srcThumb' => OssTool::getPubOssUrlByOssPath($ossPath), + 'pictureUrl' => OssTool::getPubOssUrlByOssPath($ossPath), + ]); + } + + public static function checkImageUrlArrHasNotDdUrl($imageArr) { + $hasOther = false; + foreach ($imageArr as $url) { + if(strpos($url,'ecombdimg.com') !== false) { + continue; + } + + $hasOther = true; + break; + } + + return $hasOther; + } + + public static function getImageUrlArrNotDdUrl($imageArr) { + $notDdUrl = []; + foreach ($imageArr as $url) { + if (strpos($url, 'ecombdimg.com') !== false && strpos($url, 'ecombdimg.com/img') === false) { + continue; + } + + $notDdUrl[] = $url; + } + + return $notDdUrl; + } + + public static function checkIsImageLink($link) { + $baseName = basename($link); + $ext = explode('.', $baseName); + $ext = $ext[1]; + if (in_array($ext, array('png', 'jpg', 'jpeg'))){ + return true; + } + + $curl = self::getCurl(); + $content = $curl->head($link); + preg_match('/Content-Type: image/isU', $content, $matches); + return $matches ? true : false; + } + + public static function hasBookProductCat($shopId = null) { + static $redis; + if (!is_object($redis)) { + $redis = RedisExt::factory('bizCache'); + } + $shopId = $shopId ?: $_SESSION[SessionConst::shopId]; + $cacheKey = RedisKeyConst::hasBookProductCat($shopId); + $hasBookProductCat = $redis->get($cacheKey); + if (is_numeric($hasBookProductCat)) { + return (bool)$hasBookProductCat; + } + /* @var $rsyncProductService RsyncProductService */ + $rsyncProductService = Zc::singleton('RsyncProductService'); + $allLeafProductCatList = $rsyncProductService->getAllLeafProductCatList($shopId); + $hasBookProductCat = 0; + foreach ($allLeafProductCatList as $catInfo) { + if (strpos($catInfo['path'], '书籍/杂志/报纸') !== false) { + $hasBookProductCat = 1; + break; + } + } + $redis->setex($cacheKey, 7*24*3600, $hasBookProductCat); + return (bool)$hasBookProductCat; + } + + public static function hasNamePrefixProductCat($shopId = null) { + static $redis; + if (!is_object($redis)) { + $redis = RedisExt::factory('bizCache'); + } + $shopId = $shopId ?: $_SESSION[SessionConst::shopId]; + $cacheKey = RedisKeyConst::hasNamePrefixProductCat($shopId); + $hasNamePrefixProductCat = $redis->get($cacheKey); + if (is_numeric($hasNamePrefixProductCat)) { + return (bool)$hasNamePrefixProductCat; + } + /* @var $rsyncProductService RsyncProductService */ + $rsyncProductService = Zc::singleton('RsyncProductService'); + $allLeafProductCatList = $rsyncProductService->getAllLeafProductCatList($shopId); + $hasNamePrefixProductCat = 0; + foreach ($allLeafProductCatList as $catInfo) { + $namePrefixCateNames = self::getNamePrefixCateNames(); + foreach ($namePrefixCateNames as $namePrefixCateName) { + if (strpos($catInfo['path'], $namePrefixCateName) !== false) { + $hasNamePrefixProductCat = 1; + break 2; + } + } + } + $redis->setex($cacheKey, 7*24*3600, $hasNamePrefixProductCat); + return (bool)$hasNamePrefixProductCat; + } + + public static function getNamePrefixCateNames() { + return ['时尚饰品']; + } + + public static function checkIsFrequencyLimitReason($reason) { + if (strpos($reason, '限流') !== false) { + return true; + } + + return false; + } + + public static function checkIsSystemBusyReason($reason) { + if (strpos($reason, '系统繁忙,请稍后再试') !== false) { + return true; + } + + return false; + } + + public static function checkIsDdImageUrl($imageUrl) { + $pattern = "/((?:http|https):\/\/)?p\d-aio.ecombdimg.com/isU"; + if(preg_match($pattern, $imageUrl, $match)) { + return true; + } + + return false; + } + + public static function removeDdImageUrlPrefix($imageUrl) { + $arr = parse_url($imageUrl); + return $arr['path']; + } + + public static function checkUploadFile($fileArray) { + if ($fileArray['error'] != 0) { + return CommonTool::failResult("上传文件出错,请稍后再试或联系客服咨询!"); + } + + if (!in_array($fileArray['type'], ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/octet-stream', 'application/kset'])) { + return CommonTool::failResult(sprintf("您当前的模板类型是:%s,如果是我们提供的模板,请把当前模板类型告知客服,谢谢!", $fileArray['type'])); + } + + return CommonTool::successResult(); + } + + public static function parseLTaoItemId($ltaoUrl) { + if (strpos($ltaoUrl, 'market.m.taobao.com') !== false) { + preg_match('/id=(\d+)/', $ltaoUrl, $match); + $sourceItemId = $match[1]; + } else { + $curl = new ProxyCenterCurl('taote', true); + $html = $curl->get($ltaoUrl); + preg_match('/id=(\d+)/', $html, $match); + if (empty($match[1])) { + return ''; + } + $sourceItemId = $match[1]; + } + + return $sourceItemId; + } + + public static function getProductEditImageTaskRedisKey($shopId) { + $selfShopIds = CommonTool::adminSelfShopIds(); + if (in_array($shopId, $selfShopIds)) { + $queueName = RedisKeyConst::productEditImageTaskSelf; + } else { + $queueName = RedisKeyConst::productEditImageTask; + } + + return $queueName; + } + + public static function exportCsv($fileName, $headerColumns, $exportData = [], $charset="gbk") { + header("Content-Type: application/csv;charset=".$charset); + header("Content-Disposition: attachment; filename=" . self::convertEncoding($fileName, $charset) . ".csv"); + $f = fopen('php://output', null); + fputcsv($f, $headerColumns); + if (!empty($exportData)) { + foreach ($exportData as $data) { + fputcsv($f, $data); + } + } + fclose($f); + } + + public static function saveCsv($fileName, $headerColumns, $exportData = [], $charset="gbk") { + $fileName = self::convertEncoding($fileName, $charset) . (strpos($fileName, '.csv') ? '' : '.csv'); + $f = fopen($fileName, 'w+'); + fputcsv($f, $headerColumns); + if (!empty($exportData)) { + foreach ($exportData as $data) { + fputcsv($f, $data); + } + } + fclose($f); + } + + public static function filterMenu($shopId, $menus, $unsetMenuUrls = []) { + /* @var $sidebarService SidebarService */ + $sidebarService = Zc::singleton('SidebarService'); + if (!$unsetMenuUrls) { + $isHideVideoCreate = $sidebarService->isHideVideoCreate($shopId); + if ($isHideVideoCreate) { + $unsetMenuUrls[] = WebRouteConst::buildWebUrl('video/system'); + } + } + if (!$unsetMenuUrls) { + return $menus; + } + $hasUnset = false; + foreach ($menus as $k => &$menu) { + if (in_array($menu['url'], $unsetMenuUrls)) { + unset($menus[$k]); + $hasUnset = true; + continue; + } + if (!empty($menu['childs'])) { + $menu['childs'] = self::filterMenu($shopId, $menu['childs'], $unsetMenuUrls); + } + if (!empty($menu['leftMenus'])) { + $menu['leftMenus'] = self::filterMenu($shopId, $menu['leftMenus'], $unsetMenuUrls); + } + } + return $hasUnset ? array_values($menus) : $menus; + } + + public static function isMultiDimensionalArray($arr) { + if (is_array($arr) && count($arr) > 0) { + foreach ($arr as $item) { + if (!is_array($item)) { + return false; + } + } + return true; + } + return false; + } + + public static function convertBmpToJpgByData($imageData){ + try { + $imagine = new Imagine\Imagick\Imagine(); + $im = $imagine->load($imageData); + if (!$im) { + return false; + } + + $imageData = $im->get('jpg', array('jpeg_quality' => 80)); + return $imageData; + } catch (Exception $e) { + return false; + } + } + + public static function checkNeedUploadOssImgUrl($imageUrl) { + $needles =[ + 'k3cdn', + 't.shuaishou.com' + ]; + $isNeedUploadOss = false; + foreach ($needles as $needle) { + if(strpos($imageUrl, $needle) !== false) { + $isNeedUploadOss = true; + break; + } + } + + return $isNeedUploadOss; + } + + public static function getNotHaveAppOrderShopIds() { + return array( + '4463798', // 开放平台测试专用店(主客商家) + ); + } + + public static function splitStrToArrNew($str, $isUseBlankSplit = true) { + if ($isUseBlankSplit) { + $pattern = '/,|,|;|;|\*|\\s|\\n/isU'; + } else { + $pattern = '/,|,|;|;\*|/isU'; + } + return array_unique(array_filter(array_map(function ($value) { + return trim($value); + }, preg_split($pattern, $str)))); + } + + public static function checkImgIsExist($imgUrl) { + $sourceImageUrl = self::ddImgPathToUrl($imgUrl); + $curl = CommonTool::getCurl(10); + $curl->head($sourceImageUrl); + $curlInfo = $curl->getInfo(); + if ($curlInfo['after']['http_code'] == 200) { + return true; + } + return false; + } + + public static function checkRepeatTimingTime($timingRangeList, $allowEqual = false) { + if (empty($timingRangeList)) { + return self::successResult(); + } + + $filledTimingRangeList = self::fillEmptyTimingTime($timingRangeList); + $gmtTimingStartList = ZcArrayHelper::getSub($filledTimingRangeList, 'gmtTimingStart'); + array_multisort($filledTimingRangeList, SORT_ASC, SORT_NUMERIC, $gmtTimingStartList, SORT_ASC, SORT_NUMERIC); + + $preTimingRange = array_shift($filledTimingRangeList); + + $preGmtTimingStart = $preTimingRange['gmtTimingStart']; + $preGmtTimingEnd = $preTimingRange['gmtTimingEnd']; + if ($preGmtTimingStart >= $preGmtTimingEnd) { + return self::failResult("开始时间不能大于等于结束时间"); + } + + foreach ($filledTimingRangeList as $index => $timingRange) { + $gmtTimingStart = $timingRange['gmtTimingStart']; + $gmtTimingEnd = $timingRange['gmtTimingEnd']; + + if ($gmtTimingStart >= $gmtTimingEnd) { + return self::failResult("开始时间不能大于等于结束时间"); + } + if ($allowEqual) { + if ($gmtTimingStart < $preGmtTimingEnd) { + return self::failResult("任务时间不能重叠"); + } + } else { + if ($gmtTimingStart <= $preGmtTimingEnd) { + return self::failResult("任务时间不能重叠"); + } + } + $preGmtTimingEnd = $gmtTimingEnd; + } + + return self::successResult(); + } + + private static function fillEmptyTimingTime($timingTasks) { + $emptyTimingStart = date("Y-m-d H:i:s"); + $emptyTimingEnd = "8888-01-01 00:00:00"; + + $timingTasksFilled = []; + foreach ($timingTasks as $timingTask) { + if (empty($timingTask['gmtTimingStart'])) { + $timingTask['gmtTimingStart'] = $emptyTimingStart; + } + if (empty($timingTask['gmtTimingEnd'])) { + $timingTask['gmtTimingEnd'] = $emptyTimingEnd; + } + + $timingTasksFilled[] = [ + 'gmtTimingStart' => strtotime($timingTask['gmtTimingStart']), + 'gmtTimingEnd' => strtotime($timingTask['gmtTimingEnd']), + ]; + } + return $timingTasksFilled; + } + + public static function checkIsFeigeBrowser($userAgent) { + //Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) feige/0.11.6 Chrome/104.0.5112.102 Electron/20.1.0-tt.4.release.main.6 TTElectron/20.1.0-tt.4.release.main.6 Safari/537.36 + if(stripos($userAgent, 'feige')) { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/ms-api/src/main/java/com/ms/api/ItemDTO.java b/ms-api/src/main/java/com/ms/api/dto/ItemDTO.java similarity index 88% rename from ms-api/src/main/java/com/ms/api/ItemDTO.java rename to ms-api/src/main/java/com/ms/api/dto/ItemDTO.java index 80b45b96..15c87b13 100644 --- a/ms-api/src/main/java/com/ms/api/ItemDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/ItemDTO.java @@ -1,4 +1,4 @@ -package com.ms.api; +package com.ms.api.dto; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/BatchDeleteTaskDetailRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/BatchDeleteTaskDetailRequestDTO.java similarity index 86% rename from ms-api/src/main/java/com/ms/api/move/BatchDeleteTaskDetailRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/BatchDeleteTaskDetailRequestDTO.java index 33a9418c..99b7b916 100644 --- a/ms-api/src/main/java/com/ms/api/move/BatchDeleteTaskDetailRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/BatchDeleteTaskDetailRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/CancelCollectTaskRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/CancelCollectTaskRequestDTO.java similarity index 86% rename from ms-api/src/main/java/com/ms/api/move/CancelCollectTaskRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/CancelCollectTaskRequestDTO.java index edab2dd8..3b403062 100644 --- a/ms-api/src/main/java/com/ms/api/move/CancelCollectTaskRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/CancelCollectTaskRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/FailRetryMoveTasksRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/FailRetryMoveTasksRequestDTO.java similarity index 79% rename from ms-api/src/main/java/com/ms/api/move/FailRetryMoveTasksRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/FailRetryMoveTasksRequestDTO.java index e83df41c..f67c8a8a 100644 --- a/ms-api/src/main/java/com/ms/api/move/FailRetryMoveTasksRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/FailRetryMoveTasksRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/FindSimilarProductsRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/FindSimilarProductsRequestDTO.java similarity index 88% rename from ms-api/src/main/java/com/ms/api/move/FindSimilarProductsRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/FindSimilarProductsRequestDTO.java index d2d93874..6bc05555 100644 --- a/ms-api/src/main/java/com/ms/api/move/FindSimilarProductsRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/FindSimilarProductsRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/GetChoicenessSourceItemTagRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/GetChoicenessSourceItemTagRequestDTO.java similarity index 83% rename from ms-api/src/main/java/com/ms/api/move/GetChoicenessSourceItemTagRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/GetChoicenessSourceItemTagRequestDTO.java index 6daf941e..15431a16 100644 --- a/ms-api/src/main/java/com/ms/api/move/GetChoicenessSourceItemTagRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/GetChoicenessSourceItemTagRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/GetCurrentShopMoveSettingRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/GetCurrentShopMoveSettingRequestDTO.java similarity index 98% rename from ms-api/src/main/java/com/ms/api/move/GetCurrentShopMoveSettingRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/GetCurrentShopMoveSettingRequestDTO.java index ee1d1968..088c772e 100644 --- a/ms-api/src/main/java/com/ms/api/move/GetCurrentShopMoveSettingRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/GetCurrentShopMoveSettingRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/GetMoveHistoryProductListRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/GetMoveHistoryProductListRequestDTO.java similarity index 89% rename from ms-api/src/main/java/com/ms/api/move/GetMoveHistoryProductListRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/GetMoveHistoryProductListRequestDTO.java index 0d828a48..15d56886 100644 --- a/ms-api/src/main/java/com/ms/api/move/GetMoveHistoryProductListRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/GetMoveHistoryProductListRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/GetProductInfoRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/GetProductInfoRequestDTO.java similarity index 86% rename from ms-api/src/main/java/com/ms/api/move/GetProductInfoRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/GetProductInfoRequestDTO.java index d7aabbad..4e63df58 100644 --- a/ms-api/src/main/java/com/ms/api/move/GetProductInfoRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/GetProductInfoRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/GetShopCloudHotProductsRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/GetShopCloudHotProductsRequestDTO.java similarity index 93% rename from ms-api/src/main/java/com/ms/api/move/GetShopCloudHotProductsRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/GetShopCloudHotProductsRequestDTO.java index 2fba0629..e98e5498 100644 --- a/ms-api/src/main/java/com/ms/api/move/GetShopCloudHotProductsRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/GetShopCloudHotProductsRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/MoveAgainDetailRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/MoveAgainDetailRequestDTO.java similarity index 85% rename from ms-api/src/main/java/com/ms/api/move/MoveAgainDetailRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/MoveAgainDetailRequestDTO.java index 4e8d60c3..a923177b 100644 --- a/ms-api/src/main/java/com/ms/api/move/MoveAgainDetailRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/MoveAgainDetailRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/dto/move/SaveBatchMoveTaskRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/SaveBatchMoveTaskRequestDTO.java new file mode 100644 index 00000000..71f79ef1 --- /dev/null +++ b/ms-api/src/main/java/com/ms/api/dto/move/SaveBatchMoveTaskRequestDTO.java @@ -0,0 +1,55 @@ +package com.ms.api.dto.move; + +import lombok.Data; + +import java.util.List; + +/* + * 提交搬家任务 请求参数 + */ +@Data +public class SaveBatchMoveTaskRequestDTO { + + /** + * 商品信息 + */ + private List products; + + public static class Product{ + /** + * 来源商品图片 + */ + public String source_img_url; + + /** + * 来源商品标题 + */ + public String source_title; + + /** + * 来源商品id + */ + public int source_item_id; + + /** + * 抖店类目id + */ + public int cid; + + /** + * 搬家配置id + */ + public int move_shop_config_id; + + /** + * 是否极速模式 + */ + public int is_fast_mode; + + /** + * sku编辑价格之后的map信息 + * 例如:{'skuId' : 100} + */ + public String skus; + } +} diff --git a/ms-api/src/main/java/com/ms/api/move/SearchChoicenessSourceItemRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/SearchChoicenessSourceItemRequestDTO.java similarity index 95% rename from ms-api/src/main/java/com/ms/api/move/SearchChoicenessSourceItemRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/SearchChoicenessSourceItemRequestDTO.java index 8d0d8c67..52ac06c5 100644 --- a/ms-api/src/main/java/com/ms/api/move/SearchChoicenessSourceItemRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/SearchChoicenessSourceItemRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/move/SearchDSProductCatTreeRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/move/SearchDSProductCatTreeRequestDTO.java similarity index 88% rename from ms-api/src/main/java/com/ms/api/move/SearchDSProductCatTreeRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/move/SearchDSProductCatTreeRequestDTO.java index 672036f6..91e56e3b 100644 --- a/ms-api/src/main/java/com/ms/api/move/SearchDSProductCatTreeRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/move/SearchDSProductCatTreeRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.move; +package com.ms.api.dto.move; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/CheckDsAppAuthExpireRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/CheckDsAppAuthExpireRequestDTO.java similarity index 95% rename from ms-api/src/main/java/com/ms/api/order/CheckDsAppAuthExpireRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/CheckDsAppAuthExpireRequestDTO.java index 928090d5..1e9c5afd 100644 --- a/ms-api/src/main/java/com/ms/api/order/CheckDsAppAuthExpireRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/CheckDsAppAuthExpireRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/GetAuthShopMemberInfosRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/GetAuthShopMemberInfosRequestDTO.java similarity index 91% rename from ms-api/src/main/java/com/ms/api/order/GetAuthShopMemberInfosRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/GetAuthShopMemberInfosRequestDTO.java index 466f7b07..f04fadf5 100644 --- a/ms-api/src/main/java/com/ms/api/order/GetAuthShopMemberInfosRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/GetAuthShopMemberInfosRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/GetPlatformAuthUrlRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/GetPlatformAuthUrlRequestDTO.java similarity index 93% rename from ms-api/src/main/java/com/ms/api/order/GetPlatformAuthUrlRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/GetPlatformAuthUrlRequestDTO.java index cf745639..9e492d15 100644 --- a/ms-api/src/main/java/com/ms/api/order/GetPlatformAuthUrlRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/GetPlatformAuthUrlRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/OrderSearchListRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/OrderSearchListRequestDTO.java similarity index 95% rename from ms-api/src/main/java/com/ms/api/order/OrderSearchListRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/OrderSearchListRequestDTO.java index 399e40b5..e0eb1055 100644 --- a/ms-api/src/main/java/com/ms/api/order/OrderSearchListRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/OrderSearchListRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/OriginalAndCustomConsigneeInfoRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/OriginalAndCustomConsigneeInfoRequestDTO.java similarity index 93% rename from ms-api/src/main/java/com/ms/api/order/OriginalAndCustomConsigneeInfoRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/OriginalAndCustomConsigneeInfoRequestDTO.java index 318c3f35..2ae35f9f 100644 --- a/ms-api/src/main/java/com/ms/api/order/OriginalAndCustomConsigneeInfoRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/OriginalAndCustomConsigneeInfoRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/OriginalAndCustomConsigneeInfoResponseDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/OriginalAndCustomConsigneeInfoResponseDTO.java similarity index 96% rename from ms-api/src/main/java/com/ms/api/order/OriginalAndCustomConsigneeInfoResponseDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/OriginalAndCustomConsigneeInfoResponseDTO.java index 5eb01226..df70ebb2 100644 --- a/ms-api/src/main/java/com/ms/api/order/OriginalAndCustomConsigneeInfoResponseDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/OriginalAndCustomConsigneeInfoResponseDTO.java @@ -1,5 +1,5 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import lombok.Data; diff --git a/ms-api/src/main/java/com/ms/api/order/SearchDsOrderFilterDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/SearchDsOrderFilterDTO.java similarity index 97% rename from ms-api/src/main/java/com/ms/api/order/SearchDsOrderFilterDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/SearchDsOrderFilterDTO.java index 024ca73f..1ec1a408 100644 --- a/ms-api/src/main/java/com/ms/api/order/SearchDsOrderFilterDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/SearchDsOrderFilterDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import java.util.Date; import java.util.List; diff --git a/ms-api/src/main/java/com/ms/api/order/SearchDsOrderListRequestDTO.java b/ms-api/src/main/java/com/ms/api/dto/order/SearchDsOrderListRequestDTO.java similarity index 98% rename from ms-api/src/main/java/com/ms/api/order/SearchDsOrderListRequestDTO.java rename to ms-api/src/main/java/com/ms/api/dto/order/SearchDsOrderListRequestDTO.java index f5b17bc1..c9d1234d 100644 --- a/ms-api/src/main/java/com/ms/api/order/SearchDsOrderListRequestDTO.java +++ b/ms-api/src/main/java/com/ms/api/dto/order/SearchDsOrderListRequestDTO.java @@ -1,4 +1,4 @@ -package com.ms.api.order; +package com.ms.api.dto.order; import com.fasterxml.jackson.annotation.JsonIgnore; import com.ms.api.common.PageOption; diff --git a/ms-api/src/main/java/com/ms/api/move/SaveBatchMoveTaskRequestDTO.java b/ms-api/src/main/java/com/ms/api/move/SaveBatchMoveTaskRequestDTO.java deleted file mode 100644 index c94d905a..00000000 --- a/ms-api/src/main/java/com/ms/api/move/SaveBatchMoveTaskRequestDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.ms.api.move; - -import lombok.Data; - -/* - * 提交搬家任务 请求参数 - */ -@Data -public class SaveBatchMoveTaskRequestDTO { - -// products [] 商品信息 -// source_img_url String 来源商品图片 -// source_title String 来源商品标题 -// source_item_id int 来源商品id -// cid int 抖店类目id -// move_shop_config_id int 搬家配置id -// is_fast_mode int 是否极速模式 -// skus map sku编辑价格之后的map信息 -// 例如:{'skuId' : 100} - -} diff --git a/ms-biz/src/main/java/com/ms/api/DsRequestService.java b/ms-biz/src/main/java/com/ms/api/DsRequestService.java index 615fa4bc..cbdd2b0b 100644 --- a/ms-biz/src/main/java/com/ms/api/DsRequestService.java +++ b/ms-biz/src/main/java/com/ms/api/DsRequestService.java @@ -4,7 +4,8 @@ import com.jinritemai.cloud.base.api.BaseRequest; import com.jinritemai.cloud.base.api.BaseResponse; import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.ItemDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/DsTestJavaRequestService.java b/ms-biz/src/main/java/com/ms/api/DsTestJavaRequestService.java index bfd0cf1b..7d43a893 100644 --- a/ms-biz/src/main/java/com/ms/api/DsTestJavaRequestService.java +++ b/ms-biz/src/main/java/com/ms/api/DsTestJavaRequestService.java @@ -5,7 +5,8 @@ import com.jinritemai.cloud.base.api.BaseRequest; import com.jinritemai.cloud.base.api.BaseResponse; import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.ItemDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/HttpDemoService.java b/ms-biz/src/main/java/com/ms/api/HttpDemoService.java index 544d9a1b..c2bc92b4 100644 --- a/ms-biz/src/main/java/com/ms/api/HttpDemoService.java +++ b/ms-biz/src/main/java/com/ms/api/HttpDemoService.java @@ -4,7 +4,8 @@ import com.jinritemai.cloud.base.api.BaseRequest; import com.jinritemai.cloud.base.api.BaseResponse; import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; -import com.ms.api.util.CloudRequestTemplate; +import com.ms.api.dto.ItemDTO; +import com.ms.api.tool.CloudRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/TaskService.java b/ms-biz/src/main/java/com/ms/api/TaskService.java index babb8bf2..410caa21 100644 --- a/ms-biz/src/main/java/com/ms/api/TaskService.java +++ b/ms-biz/src/main/java/com/ms/api/TaskService.java @@ -4,6 +4,7 @@ import com.jinritemai.cloud.base.api.BaseRequest; import com.jinritemai.cloud.base.api.BaseResponse; import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; +import com.ms.api.dto.ItemDTO; import lombok.extern.slf4j.Slf4j; /** diff --git a/ms-biz/src/main/java/com/ms/api/TestDdService.java b/ms-biz/src/main/java/com/ms/api/TestDdService.java index 4f6b1a1e..6ddbdd5f 100644 --- a/ms-biz/src/main/java/com/ms/api/TestDdService.java +++ b/ms-biz/src/main/java/com/ms/api/TestDdService.java @@ -11,7 +11,7 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.util.DdRequestUtil; -import com.ms.api.order.OrderSearchListRequestDTO; +import com.ms.api.dto.order.OrderSearchListRequestDTO; import lombok.extern.slf4j.Slf4j; @ExtensionService("testDdService") diff --git a/ms-biz/src/main/java/com/ms/api/bo/ProductBO.java b/ms-biz/src/main/java/com/ms/api/bo/ProductBO.java new file mode 100644 index 00000000..967a6480 --- /dev/null +++ b/ms-biz/src/main/java/com/ms/api/bo/ProductBO.java @@ -0,0 +1,46 @@ +package com.ms.api.bo; + +import lombok.Data; + +@Data +public class ProductBO { + + private int isFastMode; + + /** + * source + */ + private String source; + + /** + * site + */ + private String site; + + /** + * third_cid + */ + private String cid; + + /** + * source_item_id + */ + private String sourceItemId; + + /** + * source_title + */ + private String sourceTitle; + + /** + * source_img_url + */ + private String sourceImgUrl; + + /** + * source_shop_name + */ + private String sourceShopName; + + +} diff --git a/ms-biz/src/main/java/com/ms/api/consts/StatusConst.java b/ms-biz/src/main/java/com/ms/api/consts/StatusConst.java new file mode 100644 index 00000000..5ea85339 --- /dev/null +++ b/ms-biz/src/main/java/com/ms/api/consts/StatusConst.java @@ -0,0 +1,101 @@ +package com.ms.api.consts; + +import java.util.HashMap; + +public class StatusConst { + + public static final String normal = "normal"; + public static final String pause = "pause"; + public static final String cancel = "cancel"; + public static final String recycle = "recycle"; + public static final String deny = "deny"; + public static final String none = "none"; + + public static final String delete = "delete"; + public static final String skip = "skip"; + public static final String finish = "finish"; + + public static final String wait = "wait"; + public static final String waitRetry = "wait_retry"; + public static final String waitRetryFixup = "wait_retry_fixup"; + public static final String waitFixup = "wait_fixup"; + public static final String waitRevert = "wait_revert"; + public static final String waitPlan = "wait_plan"; + public static final String waitAudit = "wait_audit"; + public static final String processing = "processing"; + public static final String processingRevert = "processing_revert"; + public static final String processChildTask = "process_child_task"; + public static final String processCompareImage = "process_compare_image"; + public static final String process = "process"; + + public static final String reject = "reject"; + public static final String manualAudit = "manual_audit"; + public static final String auditPass = "audit_pass"; + public static final String agree = "agree"; + + public static final String success = "success"; + public static final String updateSuccess = "update_success"; + public static final String revertSuccess = "revert_success"; + public static final String processingDelete = "processing_delete"; + public static final String fail = "fail"; + public static final String updateFail = "update_fail"; + public static final String revertFail = "revert_fail"; + public static final String processingCancel = "processing_cancel"; + public static final String processingUpdate = "processing_update"; + public static final String processingCheckEnd = "processing_check_end"; + public static final String partSuccess = "part_success"; + public static final String partProcessing = "part_processing"; + + public static final String waitProcessing = "wait_processing"; + + public static final String switchOn = "on"; + public static final String switchOff = "off"; + + public static final String waitDwsData = "wait_dws_data"; + + public static final String processParse = "process_parse"; + public static final String processJudgment = "process_judgment"; + public static final String processCollectData = "process_collect_data"; + + public static final String waitPlugin = "waitPlugin"; + + public static final String payWait = "pay_wait"; + public static final String paySuccess = "pay_success"; + public static final String payFail = "pay_fail"; + public static final String payManualCheck = "pay_manual_check"; + public static final String payManualRefund = "pay_manual_refund"; + + public static final String settingStatusAll = "all"; + public static final String settingStatusHasSet = "has_set"; + public static final String settingStatusNotSet = "not_set"; + + public static final String delay = "delay"; + + public static final String manual = "manual"; + + public static final String productImgProcessTypeNormal = "normal"; + public static final String productImgProcessTypeRevert = "revert"; + + /** + * 根据状态码获取状态名称 + * + * @param code + * @return + */ + public static String getStatusNameByStatusCode(String code) { + HashMap codeMap = new HashMap<>(); + codeMap.put(finish,"完成"); + codeMap.put(success,"'成功'"); + codeMap.put(fail,"'失败'"); + codeMap.put(cancel,"已取消"); + codeMap.put(wait,"等待"); + codeMap.put(processing,"处理中"); + codeMap.put(waitRevert,"等待恢复"); + codeMap.put(processingRevert,"恢复处理中"); + codeMap.put(revertSuccess,"已恢复"); + codeMap.put(revertFail,"恢复失败"); + + return codeMap.getOrDefault(code, ""); + + } +} diff --git a/ms-biz/src/main/java/com/ms/api/service/OpOrderService.java b/ms-biz/src/main/java/com/ms/api/service/OpOrderService.java index 719c95cc..6943de70 100644 --- a/ms-biz/src/main/java/com/ms/api/service/OpOrderService.java +++ b/ms-biz/src/main/java/com/ms/api/service/OpOrderService.java @@ -1,7 +1,7 @@ package com.ms.api.service; -import com.ms.api.order.OriginalAndCustomConsigneeInfoRequestDTO; -import com.ms.api.order.OriginalAndCustomConsigneeInfoResponseDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoRequestDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoResponseDTO; import com.ms.dal.entity.OpOrder; /** diff --git a/ms-biz/src/main/java/com/ms/api/service/ShopService.java b/ms-biz/src/main/java/com/ms/api/service/ShopService.java index 72dbda10..519343a9 100644 --- a/ms-biz/src/main/java/com/ms/api/service/ShopService.java +++ b/ms-biz/src/main/java/com/ms/api/service/ShopService.java @@ -7,6 +7,8 @@ import com.ms.dal.entity.Shop; */ public interface ShopService { + Shop getDetailById(Long id); + int deleteByPrimaryKey(Long id); int insert(Shop record); diff --git a/ms-biz/src/main/java/com/ms/api/service/impl/OpOrderServiceImpl.java b/ms-biz/src/main/java/com/ms/api/service/impl/OpOrderServiceImpl.java index bcc66752..5e34deeb 100644 --- a/ms-biz/src/main/java/com/ms/api/service/impl/OpOrderServiceImpl.java +++ b/ms-biz/src/main/java/com/ms/api/service/impl/OpOrderServiceImpl.java @@ -4,8 +4,8 @@ import cn.hutool.core.util.StrUtil; import com.doudian.open.api.order_searchList.OrderSearchListRequest; import com.doudian.open.api.order_searchList.OrderSearchListResponse; import com.doudian.open.api.order_searchList.param.OrderSearchListParam; -import com.ms.api.order.OriginalAndCustomConsigneeInfoRequestDTO; -import com.ms.api.order.OriginalAndCustomConsigneeInfoResponseDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoRequestDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoResponseDTO; import com.ms.api.service.OpOrderService; import com.ms.dal.entity.OpOrder; import com.ms.dal.mapper.OpOrderMapper; diff --git a/ms-biz/src/main/java/com/ms/api/service/impl/PurchaseOrderServiceImpl.java b/ms-biz/src/main/java/com/ms/api/service/impl/PurchaseOrderServiceImpl.java index d400e5ee..c06135a9 100644 --- a/ms-biz/src/main/java/com/ms/api/service/impl/PurchaseOrderServiceImpl.java +++ b/ms-biz/src/main/java/com/ms/api/service/impl/PurchaseOrderServiceImpl.java @@ -5,7 +5,7 @@ import java.util.HashMap; import cn.hutool.core.util.ObjectUtil; import com.ms.api.consts.DsOrderConst; import com.ms.api.consts.TblConst; -import com.ms.api.order.SearchDsOrderFilterDTO; +import com.ms.api.dto.order.SearchDsOrderFilterDTO; import com.ms.api.service.PurchaseOrderService; import com.ms.dal.entity.PurchaseOrder; import com.ms.dal.mapper.PurchaseOrderMapper; diff --git a/ms-biz/src/main/java/com/ms/api/service/impl/ShopServiceImpl.java b/ms-biz/src/main/java/com/ms/api/service/impl/ShopServiceImpl.java index a88ed1d0..f7efd8c8 100644 --- a/ms-biz/src/main/java/com/ms/api/service/impl/ShopServiceImpl.java +++ b/ms-biz/src/main/java/com/ms/api/service/impl/ShopServiceImpl.java @@ -16,6 +16,11 @@ public class ShopServiceImpl implements ShopService{ @Autowired private ShopMapper shopMapper; + @Override + public Shop getDetailById(Long id) { + return shopMapper.selectByPrimaryKey(id); + } + @Override public int deleteByPrimaryKey(Long id) { return shopMapper.deleteByPrimaryKey(id); diff --git a/ms-biz/src/main/java/com/ms/api/spi/auth/CheckDsAppAuthExpireService.java b/ms-biz/src/main/java/com/ms/api/spi/auth/CheckDsAppAuthExpireService.java index 8a8bb245..ca22fa96 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/auth/CheckDsAppAuthExpireService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/auth/CheckDsAppAuthExpireService.java @@ -7,8 +7,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.order.CheckDsAppAuthExpireRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.order.CheckDsAppAuthExpireRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/auth/GetAuthShopMemberInfosService.java b/ms-biz/src/main/java/com/ms/api/spi/auth/GetAuthShopMemberInfosService.java index e8fdaf5c..f1e9387c 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/auth/GetAuthShopMemberInfosService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/auth/GetAuthShopMemberInfosService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.order.GetAuthShopMemberInfosRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.order.GetAuthShopMemberInfosRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/auth/GetPlatformAuthUrlService.java b/ms-biz/src/main/java/com/ms/api/spi/auth/GetPlatformAuthUrlService.java index 7d38b5f0..6c74253d 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/auth/GetPlatformAuthUrlService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/auth/GetPlatformAuthUrlService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.order.GetPlatformAuthUrlRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.order.GetPlatformAuthUrlRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/BatchDeleteTaskDetailService.java b/ms-biz/src/main/java/com/ms/api/spi/move/BatchDeleteTaskDetailService.java index b77ab8f3..792e31dc 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/BatchDeleteTaskDetailService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/BatchDeleteTaskDetailService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.BatchDeleteTaskDetailRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.BatchDeleteTaskDetailRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/CancelCollectTaskService.java b/ms-biz/src/main/java/com/ms/api/spi/move/CancelCollectTaskService.java index f612e952..49fd1976 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/CancelCollectTaskService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/CancelCollectTaskService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.CancelCollectTaskRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.CancelCollectTaskRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/FailRetryMoveTasksService.java b/ms-biz/src/main/java/com/ms/api/spi/move/FailRetryMoveTasksService.java index 54a83132..b5c9b613 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/FailRetryMoveTasksService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/FailRetryMoveTasksService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.FailRetryMoveTasksRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.FailRetryMoveTasksRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/FindSimilarProductsService.java b/ms-biz/src/main/java/com/ms/api/spi/move/FindSimilarProductsService.java index 5540ec5c..98fe2b13 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/FindSimilarProductsService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/FindSimilarProductsService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.FindSimilarProductsRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.FindSimilarProductsRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/GetChoicenessSourceItemTagService.java b/ms-biz/src/main/java/com/ms/api/spi/move/GetChoicenessSourceItemTagService.java index 102fed3f..f6c01e74 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/GetChoicenessSourceItemTagService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/GetChoicenessSourceItemTagService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.GetChoicenessSourceItemTagRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.GetChoicenessSourceItemTagRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/GetCurrentShopMoveSettingService.java b/ms-biz/src/main/java/com/ms/api/spi/move/GetCurrentShopMoveSettingService.java index 965670ea..ddade628 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/GetCurrentShopMoveSettingService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/GetCurrentShopMoveSettingService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.GetCurrentShopMoveSettingRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.GetCurrentShopMoveSettingRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/GetMoveHistoryProductListService.java b/ms-biz/src/main/java/com/ms/api/spi/move/GetMoveHistoryProductListService.java index 8c656365..8618c903 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/GetMoveHistoryProductListService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/GetMoveHistoryProductListService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.GetMoveHistoryProductListRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.GetMoveHistoryProductListRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/GetProductInfoService.java b/ms-biz/src/main/java/com/ms/api/spi/move/GetProductInfoService.java index c3a950fd..1dd57b8b 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/GetProductInfoService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/GetProductInfoService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.GetProductInfoRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.GetProductInfoRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/GetShopCloudHotProductsService.java b/ms-biz/src/main/java/com/ms/api/spi/move/GetShopCloudHotProductsService.java index b2bc6a51..24854d34 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/GetShopCloudHotProductsService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/GetShopCloudHotProductsService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.GetShopCloudHotProductsRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.GetShopCloudHotProductsRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/MoveAgainDetailService.java b/ms-biz/src/main/java/com/ms/api/spi/move/MoveAgainDetailService.java index 471afb39..b4675dc3 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/MoveAgainDetailService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/MoveAgainDetailService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.MoveAgainDetailRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.MoveAgainDetailRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/SaveBatchMoveTaskService.java b/ms-biz/src/main/java/com/ms/api/spi/move/SaveBatchMoveTaskService.java index f8d836c3..9ef96cf8 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/SaveBatchMoveTaskService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/SaveBatchMoveTaskService.java @@ -4,13 +4,23 @@ import com.jinritemai.cloud.base.api.BaseRequest; import com.jinritemai.cloud.base.api.BaseResponse; import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; +import com.ms.api.bo.ProductBO; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.SaveBatchMoveTaskRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.consts.StatusConst; +import com.ms.api.dto.move.SaveBatchMoveTaskRequestDTO; +import com.ms.api.service.MoveCollectTaskDetailService; +import com.ms.api.service.MoveCollectTaskService; +import com.ms.api.service.ShopService; +import com.ms.api.tool.CommonTool; +import com.ms.dal.entity.MoveCollectTask; +import com.ms.dal.entity.MoveCollectTaskDetail; +import com.ms.dal.entity.Shop; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import java.util.*; + /** * 提交搬家任务 * 上一步获取到的商品信息,客户二次确认后,把组装好的商品数据,提交给后台,进行复制任务 @@ -20,7 +30,13 @@ import org.springframework.beans.factory.annotation.Autowired; public class SaveBatchMoveTaskService extends SPIBaseService implements ExtensionServiceHandler { @Autowired - private DsFormRequestTemplate dsFormRequestTemplate; + private MoveCollectTaskService moveCollectTaskService; + + @Autowired + private ShopService shopService; + + @Autowired + private MoveCollectTaskDetailService moveCollectTaskDetailService; @Override public BaseResponse handle(BaseRequest req) { @@ -30,8 +46,147 @@ public class SaveBatchMoveTaskService extends SPIBaseService implements Extensio // ----逻辑校验---- // ----业务处理---- + long shopId = 0L; //TODO 要从session中取 + log.info("shopId "+shopId+" start saveTask"); + + addCollectTask(shopId, "copyType", "name",null); // ----结果返回---- return R.ok(); } + + private void saveTaskByAuthShop(){ + + } + + private void addShopCollectTask(long shopId, List shopProductsList, String name, String copyType){ + // TODO 开启事务 + try { + for (ProductBO product: shopProductsList) { +// this.addCollectTask(shopId,shopProductsList,copyType,name,); + } + + }catch (Exception e){ + + } + + // TODO 关闭事务 + + } + + private Map addCollectTask(long shopId, long operatorShopId, String copyType, String name, List products){ + int productTotal = products.size(); // TODO 这边计算还有点内容 + Map checkAndGetConfigIdRet = this.checkAvailableCopyAndGetMoveConfigId(shopId,productTotal); + if(CommonTool.isFailRet(checkAndGetConfigIdRet)){ + R.fail(checkAndGetConfigIdRet.get("reason")); + } + int moveShopConfigId = Integer.parseInt(checkAndGetConfigIdRet.get("moveShopConfigId")); + + // TODO 商品复制次数扣减 + + MoveCollectTask moveCollectTask = new MoveCollectTask(); + moveCollectTask.setShopId(shopId); + moveCollectTask.setCopyType(copyType); + moveCollectTask.setName(name); + moveCollectTask.setStatus(StatusConst.wait); + moveCollectTask.setGmtCreate(new Date()); + moveCollectTask.setGmtModified(new Date()); + + long moveCollectTaskId = moveCollectTaskService.insert(moveCollectTask); + + // TODO previewCateAttrData相关 + + log.info("INSERT move_collect task SQL:" + moveCollectTask.toString()); + + for (ProductBO product: products) { + MoveCollectTaskDetail moveCollectTaskDetail = new MoveCollectTaskDetail(); + moveCollectTaskDetail.setShopId(shopId); +// moveCollectTaskDetail.setAuthShopId() +// moveCollectTaskDetail.setOperatorShopId(operatorShopId) + moveCollectTaskDetail.setMoveCollectTaskId(moveCollectTaskId); + moveCollectTaskDetail.setIsFastMode(product.getIsFastMode()); + moveCollectTaskDetail.setSource(product.getSource()); + moveCollectTaskDetail.setSite(product.getSite()); + moveCollectTaskDetail.setSourceItemId(product.getSourceItemId()); + moveCollectTaskDetail.setSourceTitle(product.getSourceTitle()); + moveCollectTaskDetail.setSourceImgUrl(product.getSourceImgUrl()); + moveCollectTaskDetail.setSourceShopName(product.getSourceShopName()); + moveCollectTaskDetail.setMoveShopConfigId(moveShopConfigId); + moveCollectTaskDetail.setCid(product.getCid()); + moveCollectTaskDetail.setStatus(StatusConst.processing); + moveCollectTaskDetail.setGmtCreate(CommonTool.curDate()); + moveCollectTaskDetail.setGmtModified(CommonTool.curDate()); + + int moveCollectTaskDetailId = moveCollectTaskDetailService.insert(moveCollectTaskDetail); + log.info("INSERT move_collect_task_detail SQL" + moveCollectTaskDetail.toString()); + log.info("moveCollectTaskDetailId:" + moveCollectTaskDetailId); + + // TODO ext相关 + + String limitSource = "all"; + // TODO source的判断 + + // TODO 添加到taskBuffer + log.info("INSERT move_product_publish_buffer SQL"); + } + + return CommonTool.successResult( + new HashMap() {{ + put("taskId", String.valueOf(moveCollectTaskId)); + put("cnaliDsDetailMap", ""); + }} + ); + } + + + /** + * 检查店铺是否过期 + * + * @param shopId + * @return + */ + private boolean checkShopIsExpire(long shopId) { + Shop shop = shopService.getDetailById(shopId); + return shop.getGmtExpire().before(new Date()); + } + + private void accountBalancedLastMonth(){ + // TODO + } + + private Map getCurrentMonthMoveConfig(long shopId){ + // TODO + return null; + } + + private Map getAvailableCopyCount(long shopId) { + Shop shop = shopService.getDetailById(shopId); + if(shop.getGmtExpire().before(new Date())){ + return null; + } + this.accountBalancedLastMonth(); + Map currentMonthMoveConfig = this.getCurrentMonthMoveConfig(shopId); + if(Objects.isNull(currentMonthMoveConfig)){ + return null; + } + return currentMonthMoveConfig; + } + + private Map checkAvailableCopyAndGetMoveConfigId(long shopId, int needAddCnt) { + boolean shopIsExpire = this.checkShopIsExpire(shopId); + if (shopIsExpire) { + return CommonTool.failResult("shopId:" + shopId + "店铺已过期,请先续费"); + } + Map moveConfig = this.getAvailableCopyCount(shopId); + if(Objects.isNull(moveConfig)){ + return CommonTool.failResult("shopId:" + shopId + "搬家额度信息查询错误,请联系客服"); + } + int moveShopConfigId = (Integer) moveConfig.get("move_shop_config_id"); + int availableCopy = (Integer) moveConfig.get("available_total"); + if (needAddCnt > 0 && needAddCnt > availableCopy) { + return CommonTool.failResult("搬家额度不足,请先充值"); + } + + return CommonTool.successResult("moveShopConfigId", String.valueOf(moveShopConfigId)); + } } diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/SearchChoicenessSourceItemService.java b/ms-biz/src/main/java/com/ms/api/spi/move/SearchChoicenessSourceItemService.java index 023525e3..3c1570c7 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/SearchChoicenessSourceItemService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/SearchChoicenessSourceItemService.java @@ -7,8 +7,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.SearchChoicenessSourceItemRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.SearchChoicenessSourceItemRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/move/SearchDSProductCatTreeService.java b/ms-biz/src/main/java/com/ms/api/spi/move/SearchDSProductCatTreeService.java index dfa3766b..655359ee 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/move/SearchDSProductCatTreeService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/move/SearchDSProductCatTreeService.java @@ -6,8 +6,8 @@ import com.jinritemai.cloud.base.api.ExtensionService; import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; -import com.ms.api.move.SearchDSProductCatTreeRequestDTO; -import com.ms.api.util.DsFormRequestTemplate; +import com.ms.api.dto.move.SearchDSProductCatTreeRequestDTO; +import com.ms.api.tool.DsFormRequestTemplate; import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/ms-biz/src/main/java/com/ms/api/spi/order/GetOriginalAndCustomConsigneeInfoService.java b/ms-biz/src/main/java/com/ms/api/spi/order/GetOriginalAndCustomConsigneeInfoService.java index 490b00aa..11eebf17 100644 --- a/ms-biz/src/main/java/com/ms/api/spi/order/GetOriginalAndCustomConsigneeInfoService.java +++ b/ms-biz/src/main/java/com/ms/api/spi/order/GetOriginalAndCustomConsigneeInfoService.java @@ -8,10 +8,10 @@ import com.jinritemai.cloud.base.api.ExtensionServiceHandler; import com.ms.api.common.R; import com.ms.api.common.SPIBaseService; import com.ms.api.consts.OrderConst; -import com.ms.api.order.OriginalAndCustomConsigneeInfoRequestDTO; -import com.ms.api.order.OriginalAndCustomConsigneeInfoResponseDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoRequestDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoResponseDTO; import com.ms.api.service.OpOrderService; -import com.ms.api.util.CommmonTool; +import com.ms.api.tool.CommonTool; import com.ms.dal.entity.OpOrder; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -26,7 +26,7 @@ public class GetOriginalAndCustomConsigneeInfoService extends SPIBaseService imp @Override public BaseResponse handle(BaseRequest req) { OriginalAndCustomConsigneeInfoRequestDTO requestDTO = req.getData(); - String orderId = CommmonTool.rebuildDdorderIdSuffix(requestDTO.getOrderId()); + String orderId = CommonTool.rebuildDdorderIdSuffix(requestDTO.getOrderId()); OpOrder opOrder = orderService.selectByOrderId(orderId); if (ObjectUtil.isNull(opOrder)) { diff --git a/ms-biz/src/main/java/com/ms/api/util/CloudRequestTemplate.java b/ms-biz/src/main/java/com/ms/api/tool/CloudRequestTemplate.java similarity index 99% rename from ms-biz/src/main/java/com/ms/api/util/CloudRequestTemplate.java rename to ms-biz/src/main/java/com/ms/api/tool/CloudRequestTemplate.java index 06d24620..9ce56a1e 100644 --- a/ms-biz/src/main/java/com/ms/api/util/CloudRequestTemplate.java +++ b/ms-biz/src/main/java/com/ms/api/tool/CloudRequestTemplate.java @@ -1,4 +1,4 @@ -package com.ms.api.util; +package com.ms.api.tool; import com.alibaba.fastjson.JSON; import com.doudian.open.utils.SignUtil; diff --git a/ms-biz/src/main/java/com/ms/api/util/CommmonTool.java b/ms-biz/src/main/java/com/ms/api/tool/CommonTool.java similarity index 59% rename from ms-biz/src/main/java/com/ms/api/util/CommmonTool.java rename to ms-biz/src/main/java/com/ms/api/tool/CommonTool.java index f61eb303..a34bb9fa 100644 --- a/ms-biz/src/main/java/com/ms/api/util/CommmonTool.java +++ b/ms-biz/src/main/java/com/ms/api/tool/CommonTool.java @@ -1,14 +1,13 @@ -package com.ms.api.util; +package com.ms.api.tool; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.doudian.open.core.DoudianOpResponse; -public class CommmonTool { +public class CommonTool { /* * 订单id有没有以A结尾 没有则拼接上去 @@ -66,4 +65,41 @@ public class CommmonTool { public static List toStrList(String split, String str) { return Arrays.asList(toStrArray(split, str)); } + + public static String getStrNow(){ + return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()); + } + + public static Map successResult(Map keyMap) { + Map base = new HashMap<>(); + base.put("result", "success"); + base.putAll(keyMap); + return base; + } + + public static Map successResult(String key, String value) { + Map base = new HashMap<>(); + base.put("result", "success"); + base.put(key, value); + return base; + } + + public static Map failResult(String reason) { + Map resultMap = new HashMap<>(); + resultMap.put("result", "fail"); + resultMap.put(reason, reason); + return resultMap; + } + + public static boolean isSuccessRet(Map ret) { + return ret.get("result").equals("success"); + } + + public static boolean isFailRet(Map ret) { + return ret.get("result").equals("fail"); + } + + public static Date curDate() { + return new Date(); + } } diff --git a/ms-biz/src/main/java/com/ms/api/util/DsFormRequestTemplate.java b/ms-biz/src/main/java/com/ms/api/tool/DsFormRequestTemplate.java similarity index 97% rename from ms-biz/src/main/java/com/ms/api/util/DsFormRequestTemplate.java rename to ms-biz/src/main/java/com/ms/api/tool/DsFormRequestTemplate.java index 0b632e75..b111e52c 100644 --- a/ms-biz/src/main/java/com/ms/api/util/DsFormRequestTemplate.java +++ b/ms-biz/src/main/java/com/ms/api/tool/DsFormRequestTemplate.java @@ -1,6 +1,7 @@ -package com.ms.api.util; +package com.ms.api.tool; import cn.hutool.crypto.SecureUtil; +import com.ms.api.util.UniqueKeyMultiValueMap; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; diff --git a/ms-biz/src/main/java/com/ms/api/util/DdRequestUtil.java b/ms-biz/src/main/java/com/ms/api/util/DdRequestUtil.java index b8e0a4d4..c4722bdd 100644 --- a/ms-biz/src/main/java/com/ms/api/util/DdRequestUtil.java +++ b/ms-biz/src/main/java/com/ms/api/util/DdRequestUtil.java @@ -5,6 +5,7 @@ import com.doudian.open.api.order_searchList.OrderSearchListRequest; import com.doudian.open.api.order_searchList.OrderSearchListResponse; import com.doudian.open.api.order_searchList.data.OrderSearchListData; import com.doudian.open.api.order_searchList.param.OrderSearchListParam; +import com.ms.api.tool.CommonTool; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -18,7 +19,7 @@ public class DdRequestUtil { OrderSearchListResponse response = request.execute(); log.info("=============Dd请求返回==================="); log.info(JSONObject.toJSONString(response)); - boolean success = CommmonTool.checkDdApiRequestIsSuccess(response); + boolean success = CommonTool.checkDdApiRequestIsSuccess(response); if (success) { return response.getData(); } diff --git a/ms-biz/src/main/java/com/ms/api/util/PurchaseOrderUtil.java b/ms-biz/src/main/java/com/ms/api/util/PurchaseOrderUtil.java index 23967695..9438169a 100644 --- a/ms-biz/src/main/java/com/ms/api/util/PurchaseOrderUtil.java +++ b/ms-biz/src/main/java/com/ms/api/util/PurchaseOrderUtil.java @@ -15,10 +15,11 @@ import com.ms.api.consts.DsOrderConst; import com.ms.api.consts.OrderConst; import com.ms.api.consts.PurchaseOrderConst; import com.ms.api.consts.SessionConst; -import com.ms.api.order.OriginalAndCustomConsigneeInfoRequestDTO; -import com.ms.api.order.OriginalAndCustomConsigneeInfoResponseDTO; -import com.ms.api.order.SearchDsOrderFilterDTO; -import com.ms.api.order.SearchDsOrderListRequestDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoRequestDTO; +import com.ms.api.dto.order.OriginalAndCustomConsigneeInfoResponseDTO; +import com.ms.api.dto.order.SearchDsOrderFilterDTO; +import com.ms.api.dto.order.SearchDsOrderListRequestDTO; +import com.ms.api.tool.CommonTool; public class PurchaseOrderUtil { @@ -115,13 +116,13 @@ public class PurchaseOrderUtil { params.setIsPriorirtyDelivery(dto.getIsPriorirtyDelivery() ? 1 : 0); } if (StrUtil.isNotBlank(dto.getOrderIds())) { - params.setOrderIds(CommmonTool.splitWithComma(dto.getOrderIds())); + params.setOrderIds(CommonTool.splitWithComma(dto.getOrderIds())); if (params.getOrderIds().size() > 200) { return R.fail("一次最多输入200个订单号查询"); } } if (StrUtil.isNotBlank(dto.getPurchaseOrderSn())) { - params.setOrderIds(CommmonTool.splitWithComma(dto.getPurchaseOrderSn())); + params.setOrderIds(CommonTool.splitWithComma(dto.getPurchaseOrderSn())); } if (ObjectUtil.isNotNull(dto.getOrderStartTime())) { params.setOrderStartTime(DateUtil.parseDate(dto.getOrderStartTime())); diff --git a/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTask.java b/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTask.java index 0264e2df..ab395158 100644 --- a/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTask.java +++ b/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTask.java @@ -1,6 +1,7 @@ package com.ms.dal.entity; import lombok.Data; +import lombok.ToString; import java.io.Serializable; import java.util.Date; @@ -11,6 +12,7 @@ import java.util.Date; * @Date: 2023/8/24 */ @Data +@ToString public class MoveCollectTask implements Serializable { /** diff --git a/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTaskDetail.java b/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTaskDetail.java index b12ec27e..850b6727 100644 --- a/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTaskDetail.java +++ b/ms-dal/src/main/java/com/ms/dal/entity/MoveCollectTaskDetail.java @@ -1,6 +1,7 @@ package com.ms.dal.entity; import lombok.Data; +import lombok.ToString; import java.io.Serializable; import java.util.Date; @@ -10,6 +11,7 @@ import java.util.Date; * @Date: 2023/8/24 */ @Data +@ToString public class MoveCollectTaskDetail implements Serializable { /**