yingzi 1 年之前
当前提交
f678fbbc95
共有 74 个文件被更改,包括 7277 次插入0 次删除
  1. 4 0
      .gitignore
  2. 1 0
      .htaccess
  3. 1 0
      .user.ini
  4. 7 0
      404.html
  5. 二进制
      Jobs/.DS_Store
  6. 181 0
      Jobs/.ENV.php
  7. 71 0
      Jobs/Cache/AllTableNameCache.Class.php
  8. 220 0
      Jobs/Cache/CustomerCache.Class.php
  9. 45 0
      Jobs/Cache/FinanceCache.Class.php
  10. 395 0
      Jobs/Cache/OverviewCache.Class.php
  11. 二进制
      Jobs/Config/.DS_Store
  12. 351 0
      Jobs/Config/Config.php
  13. 42 0
      Jobs/Controller/BaseController.Class.php
  14. 81 0
      Jobs/Controller/CAddJob.Class.php
  15. 14 0
      Jobs/Controller/CBase.Class.php
  16. 195 0
      Jobs/Controller/CESinit.Class.php
  17. 22 0
      Jobs/Controller/CJobObject.Class.php
  18. 38 0
      Jobs/Controller/CJobs.Class.php
  19. 647 0
      Jobs/Controller/Test.Class.php
  20. 309 0
      Jobs/Dao/BaseDao.Class.php
  21. 60 0
      Jobs/Dao/DCoupon.Class.php
  22. 49 0
      Jobs/Dao/DGoodsBasic.Class.php
  23. 35 0
      Jobs/Dao/DLog.Class.php
  24. 35 0
      Jobs/Dao/DLoginLog.Class.php
  25. 35 0
      Jobs/Dao/DPriceLog.Class.php
  26. 57 0
      Jobs/Dao/DShop.Class.php
  27. 58 0
      Jobs/Dao/DUserCoupon.Class.php
  28. 42 0
      Jobs/Dao/Finance/DPay.Class.php
  29. 42 0
      Jobs/Dao/Finance/DPayReceiptIndex.Class.php
  30. 42 0
      Jobs/Dao/Finance/DReceive.Class.php
  31. 41 0
      Jobs/Dao/Finance/DReceiveReceiptIndex.Class.php
  32. 40 0
      Jobs/Dao/Message/DMessage.Class.php
  33. 59 0
      Jobs/Dao/Order/DOrder.Class.php
  34. 41 0
      Jobs/Dao/Order/DOrderCoupon.Class.php
  35. 57 0
      Jobs/Dao/Order/DOrderGoods.Class.php
  36. 45 0
      Jobs/Dao/Order/DOrderIndex.Class.php
  37. 48 0
      Jobs/Dao/Order/DOrderReceive.Class.php
  38. 56 0
      Jobs/Dao/Purchase/DPurchase.Class.php
  39. 57 0
      Jobs/Dao/Purchase/DPurchaseOut.Class.php
  40. 50 0
      Jobs/Dao/Stock/DInventoryBatch.Class.php
  41. 53 0
      Jobs/Dao/Stock/DInventoryDetails.Class.php
  42. 58 0
      Jobs/Dao/Stock/DInventoryIn.Class.php
  43. 54 0
      Jobs/Dao/Stock/DInventoryInDetails.Class.php
  44. 60 0
      Jobs/Dao/Stock/DInventoryOut.Class.php
  45. 49 0
      Jobs/Dao/Stock/DWarehouse.Class.php
  46. 154 0
      Jobs/Model/MConsole.Class.php
  47. 114 0
      Jobs/Model/MJobs.Class.php
  48. 441 0
      Jobs/Model/MProcess.Class.php
  49. 25 0
      Jobs/Model/MQueue.Class.php
  50. 85 0
      Jobs/Model/MTopic/Enterprise/MEnterprise.Class.php
  51. 252 0
      Jobs/Model/MTopic/Finance/MPayable.Class.php
  52. 488 0
      Jobs/Model/MTopic/Finance/MReceivable.Class.php
  53. 46 0
      Jobs/Model/MTopic/MErp.Class.php
  54. 149 0
      Jobs/Model/MTopic/Market/MCoupon.Class.php
  55. 57 0
      Jobs/Model/MTopic/Market/MGrantCoupon.Class.php
  56. 55 0
      Jobs/Model/MTopic/Market/MOnlinePayCoupon.Class.php
  57. 52 0
      Jobs/Model/MTopic/Market/MRegisterCoupon.Class.php
  58. 95 0
      Jobs/Model/MTopic/Message/MMessage.Class.php
  59. 132 0
      Jobs/Model/MTopic/Order/MCommissionOrder.Class.php
  60. 33 0
      Jobs/Model/MTopic/Order/MDelayedCancelOrder.Class.php
  61. 125 0
      Jobs/Model/MTopic/Order/MOrder.Class.php
  62. 217 0
      Jobs/Model/MTopic/Order/MOrderStatistics.Class.php
  63. 246 0
      Jobs/Model/MTopic/Push/MPush.Class.php
  64. 107 0
      Jobs/Model/Middleware.Class.php
  65. 55 0
      Jobs/Model/Queue/MBaseTopicQueue.Class.php
  66. 114 0
      Jobs/Model/Queue/MRedisTopicQueue.Class.php
  67. 48 0
      Jobs/Model/Queue/MTopicQueueInterface.Class.php
  68. 33 0
      Jobs/Model/Test/K3Curl.Class.php
  69. 165 0
      Jobs/Model/Test/K3Handle.Class.php
  70. 54 0
      Jobs/Model/Test/K3login.Class.php
  71. 二进制
      Jobs/Public/.DS_Store
  72. 25 0
      Jobs/Public/www/index.php
  73. 23 0
      Jobs/start.php
  74. 40 0
      index.html

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+nbproject/
+log/
+Jobs/log/
+./Jobs/log/

+ 1 - 0
.htaccess

@@ -0,0 +1 @@
+ 

+ 1 - 0
.user.ini

@@ -0,0 +1 @@
+open_basedir=/www/wwwroot/queueqnys.liuniukj.com/:/tmp/

+ 7 - 0
404.html

@@ -0,0 +1,7 @@
+<html>
+<head><title>404 Not Found</title></head>
+<body>
+<center><h1>404 Not Found</h1></center>
+<hr><center>nginx</center>
+</body>
+</html>

二进制
Jobs/.DS_Store


+ 181 - 0
Jobs/.ENV.php

@@ -0,0 +1,181 @@
+<?php
+/**
+ * 基础常量
+ */
+// 项目根目录
+define('PROJECT_PATH', __DIR__);
+// 项目名称
+define('PROJECT_NAME', 'Jobs');
+// 项目域名
+define('PROJECT_DOMAIN', 'queueqnys');
+// 项目在权限系统编号
+define('PROJECT_ACL_NO', '3');
+// 默认控制器
+define('DEFAULT_CLASS_CONTROLLER_NAME', 'index');
+// 默认方法名
+define('DEFAULT_CLASS_ACTION_NAME', 'index');
+// 默认模块名
+define('DEFAULT_CLASS_MODULE_NAME', 'index');
+
+/**
+ * 域名
+ */
+// 根域名
+define('DOMAIN', 'mallguang.top');
+/* 域名后缀 */
+define('DOMAIN_SUFFIX', '.' . DOMAIN);
+// 项目域名
+define('DOMAIN_PROJECT', strtolower(PROJECT_NAME) . DOMAIN_SUFFIX);
+// 配置项目资源域名
+define('DOMAIN_PROJECT_IMG', strtolower(PROJECT_NAME). '.res' . DOMAIN_SUFFIX);
+// 上传附件资源域名
+define('DOMAIN_UPLOAD', 'upload' . DOMAIN_SUFFIX);
+
+/**
+ * URL
+ * 必须以 / 结尾
+ */
+// http协议
+define('AGREEMENT', 'http://');
+// https协议
+define('AGREEMENTSSL', 'https://');
+// 项目地址
+define('URL_PROJECT', AGREEMENT . DOMAIN_PROJECT . '/');
+// 项目资源地址
+define('URL_PROJECT_RES',  AGREEMENT . DOMAIN_PROJECT_IMG . '/');
+// 阿里云请求主域名
+define('URL_ALI_SERVICE', AGREEMENT . 'ali' . DOMAIN_SUFFIX);
+// 上传附件资源域名
+define('URL_UPLOAD', AGREEMENT . DOMAIN_UPLOAD . '/');
+// Mobile Web分享
+define('URL_SHARE_MOBILE', AGREEMENT . 'share' . DOMAIN_SUFFIX . '/');
+// android 下载地址
+define('URL_ANDROID_DOWNLOAD', 'http://a.app.qq.com/o/simple.jsp?pkgname=com.maoguang.catmall');
+// ios 下载地址
+define('URL_IOS_DOWNLOAD', 'http://www.mallguang.com');
+// 队列处理地址  dev队列 对应请求域名
+define('QIANNIAO_QUEUE', 'http://queueqnys.liuniukj.com');
+// 项目正式域名
+define('URL_API', 'https://apiqnys.liuniukj.com');
+// 项目开发环境域名
+define('DEV_URL_API', 'https://devapiqnys.liuniukj.com');
+
+/**
+ * Smarty
+ * 模板引擎配置
+ */
+// 模板存放目录
+define('SMARTY_TEMPLATE_DIR', PROJECT_PATH . DS . 'View' . DS . 'Templates');
+// 模板编译目录
+define('SMARTY_COMPILE_DIR', PROJECT_PATH . DS . 'Storage' . DS . 'Views');
+// 模板缓存目录
+define('SMARTY_CACHE_DIR', PROJECT_PATH . DS . 'Storage' . DS . 'Views');
+// 模板后缀
+define('SMARTY_TEMPLATE_TYPE', '.html');
+// 模板缓存是否开启
+define('SMARTY_IS_CACHE', FALSE);
+
+
+/**
+ * DB
+ * 数据库引擎配置
+ */
+// 数据库引擎名称,首字母大写
+define('DB_DIRVER', 'Pdo');
+// 数据库服务IP地址
+define('DB_HOST', '47.104.177.139');
+// 数据库服务端口号
+define('DB_PORT', '3306');
+// 数据库服务用户名
+define('DB_USERNAME', 'mallguang');
+// 数据库服务密码
+define('DB_PASSWORD', 'zxcvbnm');
+// 数据库名称
+define('DB_NAME', 'shop');
+// 数据库字符编码
+define('DB_CHARSET', 'utf-8');
+
+/**
+ * Cookie
+ */
+define('COOKIE_PREFIX', 'mallguang_');
+define('COOKIE_PATH', '/');
+define('COOKIE_DOMAIN', DOMAIN_SUFFIX);
+
+/**
+ * Mail
+ */
+/**
+ * 邮件发送方式
+ * 1.使用PHP的mail函数发送
+ * 2.通过 SOCKET 连接 SMTP 服务器发送(支持 ESMTP 验证, 推荐方法)
+ * 3.邮件发送方式1. 使用PHP的mail函数发送2.通过SOCKET 连接 SMTP 服务器发送(支持 ESMTP 验证, 推荐方法)
+ */
+define('MAIL_MAILER', 2);
+/**
+ * 分隔符
+ * 使用 CRLF 作为分隔符(常用, SMTP方式默认分割符)
+ * 使用 LF 作为分隔符(一些Unix主机使用mail函数时需用LF替代CRLF)
+ * 使用 CR 作为分隔符(通常为 Mac 主机, 不常用)
+ */
+define('MAIL_DELIMITER', 1);
+// 字符集
+define('MAIL_CHARSET', 'utf-8');
+// 发件人邮箱
+define('MAIL_FROM', 'qlxbaa@163.com');
+// 是否需要鉴权
+define('MAIL_SIGN', FALSE);
+// Smtp 服务地址
+define('MAIL_SMTP_HOST', 'smtp.163.com');
+// Smtp 服务端口
+define('MAIL_SMTP_PORT', 25);
+// Smtp 身份验证
+define('MAIL_SMTP_AUTH', 1);
+// Smtp 用户名
+define('MAIL_SMTP_USERNAME', 'qlxbaa@163.com');
+// Smtp 密码
+define('MAIL_SMTP_PASSWORD', '8879288aaa');
+// 内容是否Base64
+define('MAIL_CONTENT_BASE64', FALSE);
+
+/**
+ * Session
+ */
+// Session引擎
+define('SESSION_SAVE_HANDLER', 'redis');
+// 存放地址
+define('SESSION_SAVE_PATH',  'tcp://127.0.0.1:6379?auth=&databases=2&weight=1&timeout=1&prefix=BackendSession:');
+// 数据在服务器端储存有效期
+define('SESSION_GC_MAXLIFETIME', 3600);
+// 客户端的缓存方式,有nocache,private,private_no_expire,publice
+define('SESSION_CACHE_LIMITER', 'nocache');
+// cookie 值生存周期
+define('SESSION_CACHE_EXPIRE', 60);
+// cookie 域名
+define('SESSION_COOKIE_DOMAIN', DOMAIN_SUFFIX);
+// cookie 路径
+define('SESSION_COOKIE_PATH', '/');
+// cookie 数据存储有效期
+define('SESSION_COOKIE_LIFETIME', 0);
+
+/** 附加常量 **/
+
+/**
+ * 时间戳
+ */
+define('TIME', time());
+
+/**
+ * 站点加密SECRET
+ */
+define('SITE_SECRET', '884N7GpYjPM/}rmx,LCxGJP3si?D&4');
+
+/**
+ * Upload File Path
+ */
+define('UPLOAD_FILE_PATH',  PROJECT_PATH . DS.'Public/upload/file/');
+
+/**
+ * default member avatar path
+ */
+define('DEFAULT_MEMBER_AVATAR', URL_UPLOAD.'defaultavatar.png');

+ 71 - 0
Jobs/Cache/AllTableNameCache.Class.php

@@ -0,0 +1,71 @@
+<?php
+namespace Jobs\Cache;
+
+use Mall\Framework\Factory;
+
+class AllTableNameCache
+{
+    /**
+     * 所有表名缓存
+     *
+     * @var
+     */
+    static $allTableName = 'all_tablename';
+
+    /**
+     * 判断所有表名缓存是否存在
+     *
+     * @param string $databaseName 库名
+     *
+     * @return bool
+     */
+    static function allTableNameCacheIsExists($databaseName){
+        $result = Factory::cache('default')->has(self::$allTableName.'::'.$databaseName);
+        return $result;
+    }
+
+    /**
+     * 缓存制定库下的所有表名
+     *
+     * @param string $dataBaseName      当前数据库库名
+     * @param array  $allTableNameData  当前库中所有表名数据
+     */
+    static function allTableNameCache($databaseName, $allTableNameData)
+    {
+        if(empty($allTableNameData)){
+            return false;
+        }
+
+        $pipe =  Factory::cache('default')->multi();
+        foreach ($allTableNameData as $key => $value){
+            $writeCache = Factory::cache('default')->sadd(self::$allTableName.'::'.$databaseName, $value['TABLE_NAME']);
+        }
+        $pipe->exec();
+    }
+
+    /**
+     * 判断是否存在这张表
+     *
+     * @param string $dataBaseName    当前数据库库名
+     * @param string $tableName       表名
+     *
+     * @return bool
+     */
+    static function TableIsExists($databaseName, $tableName)
+    {
+        $result =  Factory::cache('default')->sismember(self::$allTableName.'::'.$databaseName, $tableName);
+        return $result;
+    }
+
+    /**
+     * 添加新表到表名缓存中
+     * @param string $dataBaseName    当前数据库库名
+     * @param string $tableName       表名
+     *
+     * @return bool
+     */
+    static function addNewTableName($databaseName, $tableName){
+        $writeCache = Factory::cache('default')->sadd(self::$allTableName.'::'.$databaseName, $tableName);
+        return $writeCache;
+    }
+}

+ 220 - 0
Jobs/Cache/CustomerCache.Class.php

@@ -0,0 +1,220 @@
+<?php
+/**
+ * 客户统计部分埋点
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/11/14
+ * Time: 11:58
+ */
+
+namespace Jobs\Cache;
+
+use Mall\Framework\Core\ResultWrapper;
+use Mall\Framework\Factory;
+
+class CustomerCache
+{
+    private $cache;
+    protected $key = '';
+    protected $registerSmsCountKey = 'todayCreateOrderCustomer::'; //今日下单用户key
+    protected $customerExpire = 10;//过期时间为一天
+    protected $allCustomerNumKey = 'allCustomerNum';//全部客户数量key
+    protected $lastMonthNewCustomerKey = 'lastMonthNewCustomer';//新增客户数量:最近30天新增,且没有成功付款的客户 key
+    protected $interestCustomerKey = 'interestCustomer';//兴趣人群数量:近7天有加购行为,但没有成功付款的客户
+
+    public function __construct()
+    {
+        $this->key = $this->registerSmsCountKey . date('Ymd', time());
+        $this->cache = Factory::cache('user');
+    }
+
+    /***************************** 今日下单用户相关 start **********************************/
+
+    /**
+     * 下单时调用此方法,添加一条客户下单信息  todayCreateOrderCustomer::20190101:0001:0002:0003
+     * @param $enterpriseId
+     * @param $provinceCode
+     * @param $cityCode
+     * @param $districtCode
+     * @param $customerId
+     * @param $shopId
+     * @return bool|ResultWrapper
+     */
+    public function cacheCustomerOrderInfo($enterpriseId, $provinceCode = null, $cityCode = null, $districtCode = null, $customerId, $shopId = null)
+    {
+        if (empty($enterpriseId) || empty($customerId)) {
+            return false;
+        }
+        $this->key = $this->key . '::enterprise_' . $enterpriseId;
+        $this->cache->zincrby($this->key, 1, $customerId);//存全国
+        $this->cache->expire($this->key, $this->customerExpire);
+
+        if (!empty($provinceCode)) {
+            $key = $this->key . '::areaCode_' . $provinceCode;
+            $this->cache->zincrby($key, 1, $customerId);//存省
+            $this->cache->expire($key, $this->customerExpire);
+        }
+
+        if (!empty($cityCode)) {
+            $key = $this->key . '::areaCode_' . $cityCode;
+            $this->cache->zincrby($key, 1, $customerId);//存市
+            $this->cache->expire($key, $this->customerExpire);
+        }
+
+        if (!empty($districtCode)) {
+            $key = $this->key . '::areaCode_' . $districtCode;
+            $this->cache->zincrby($key, 1, $customerId);//存区
+            $this->cache->expire($key, $this->customerExpire);
+        }
+
+        if (!empty($shopId)) {
+            $key = $this->key . '::shopId_' . $shopId;
+            $this->cache->zincrby($key, 1, $customerId);
+            $this->cache->expire($key, $this->customerExpire);
+        }
+        return true;
+    }
+
+    /**
+     * 今日下单用户统计,按地区搜索
+     * @param $enterpriseId 企业id
+     * code不传则查的是全国的客户下单信息
+     * @param $code
+     * @param $shopId
+     * @return array
+     */
+    public function getTodayCustomerOrderInfo($enterpriseId, $code = null, $shopId = null)
+    {
+        $key = $this->key . '::enterprise_' . $enterpriseId;
+        if (!empty($code)) {
+            $key .= '::areaCode_' . $code;
+        }
+        if (!empty($shopId)) {
+            $key .= '::shopId_' . $shopId;
+        }
+        $result = $this->cache->zrange($key, 0, -1);
+        return $result ? $result : [];
+    }
+
+    /***************************** 今日下单用户相关 end **********************************/
+
+    /***************************** 全部客户数量相关 start **********************************/
+
+    /**
+     * 增加客户数量:每次客户注册调用此方法
+     * @param $enterpriseId
+     * @return bool
+     */
+    public function incrCustomerNum($enterpriseId)
+    {
+        $result = $this->cache->incr($this->allCustomerNumKey . '::' . $enterpriseId);
+        return $result ? true : false;
+    }
+
+    /**
+     * 获取当前客户总数
+     * @param $enterpriseId
+     * @return bool
+     */
+    public function getAllCustomerNum($enterpriseId)
+    {
+        return $this->cache->get($this->allCustomerNumKey . '::' . $enterpriseId);
+    }
+
+    /***************************** 全部客户数量相关 end **********************************/
+
+
+    /***************************** 新增客户数量相关 start **********************************/
+
+    /**
+     * 新增客户 customerId  score存时间戳   注册用户时调用此方法
+     * @param $customerId
+     * @param $enterpriseId
+     * @return bool
+     */
+    public function incrCustomer($customerId, $enterpriseId)
+    {
+        $result = $this->cache->zadd($this->lastMonthNewCustomerKey . '::' . $enterpriseId, time(), $customerId);
+        return $result ? true : false;
+    }
+
+    /**
+     * 删除所有企业注册超过30天的用户
+     * @return bool   true代表有数据被删除  false相反
+     */
+    public function delCustomerOfOneMonthAgo()
+    {
+        //获取所有key  ['lastMonthNewCustomer::12','lastMonthNewCustomer::11']
+        $keysList = $this->cache->keys($this->lastMonthNewCustomerKey . '*');
+        $oneMonthAgoTimestamp = strtotime("-30 day");
+        foreach ($keysList as $value) {
+            $keyArr = explode('::', $value);
+            $result = $this->cache->zremrangebyscore($this->lastMonthNewCustomerKey . '::' . $keyArr[2], 0, $oneMonthAgoTimestamp);
+            if (!$result) {
+                return false;//没有数据可删除也返回false
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 客户下单后删除客户信息
+     * @param $customerId
+     * @param $enterpriseId
+     * @return bool
+     */
+    public function delCustomerAfterPlaceOrder($customerId, $enterpriseId)
+    {
+        $result = $this->cache->zrem($this->lastMonthNewCustomerKey . '::' . $enterpriseId, $customerId);
+        return $result ? true : false;
+    }
+    /***************************** 新增客户数量相关 end **********************************/
+
+    /***************************** 兴趣人群数量 : 近7天加购行为 start **********************************/
+    /**
+     * 加入购物车 customerId  score存时间戳   注册用户时调用此方法
+     * @param $customerId
+     * @param $enterpriseId
+     * @return bool
+     */
+    public function incrInterestCustomer($customerId, $enterpriseId)
+    {
+        $result = $this->cache->zadd($this->interestCustomerKey . '::' . $enterpriseId, time(), $customerId);
+        return $result ? true : false;
+    }
+
+    /**
+     * 删除所有企业加购超过7天的用户
+     * @return bool   true代表有数据被删除  false相反
+     */
+    public function delInterestCustomerOfSevenDaysAgo()
+    {
+        //获取所有key  ['lastMonthNewCustomer::12','lastMonthNewCustomer::11']
+        $keysList = $this->cache->keys($this->interestCustomerKey . '*');
+        $SeveralDaysAgoTimestamp = strtotime("-7 day");
+        foreach ($keysList as $value) {
+            $keyArr = explode('::', $value);
+            $result = $this->cache->zremrangebyscore($this->interestCustomerKey . '::' . $keyArr[2], 0, $SeveralDaysAgoTimestamp);
+            if (!$result) {
+                return false;//没有数据可删除也返回false
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 客户成功付款后删除信息
+     * @param $customerId
+     * @param $enterpriseId
+     * @return bool
+     */
+    public function delInterestCustomerAfterPay($customerId, $enterpriseId)
+    {
+        $result = $this->cache->zrem($this->interestCustomerKey . '::' . $enterpriseId, $customerId);
+        return $result ? true : false;
+    }
+
+    /***************************** 近7天加购行为 end **********************************/
+
+
+}

+ 45 - 0
Jobs/Cache/FinanceCache.Class.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Jobs\Cache;
+
+use http\Exception;
+use Mall\Framework\Factory;
+use Mall\Framework\Core\ResultWrapper;
+use Mall\Framework\Core\ErrorCode;
+
+class FinanceCache
+{
+    private $cache;
+    protected $salesOutReceiveKey = 'salesOutReceive';//销售出库生成应收,缓存应收单的id
+    private $existPayEnterpriseKey = 'existPayEnterprise'; // 存在应付单的企业标识
+
+    public function __construct()
+    {
+        $this->cache = Factory::cache('finance');
+    }
+
+    /**
+     * 销售出库生成应收单,应收单自动审核  缓存应收单id和时间
+     * @param $enterpriseId
+     * @param $id
+     * @param $createTime
+     * @return array|mixed
+     */
+    public function saveSalesOutReceive($enterpriseId, $id, $createTime)
+    {
+        $this->cache->zadd($this->salesOutReceiveKey.'::'.$enterpriseId, $createTime, $id);
+    }
+
+    public function delSalesOutReceive($enterpriseId, $id)
+    {
+        $this->cache->zrem($this->salesOutReceiveKey.'::'.$enterpriseId, $id);
+    }
+
+    /**
+     * 缓存一下那个企业有应付单生成,便于计划任务进行自动切换企业,做自动审核
+     */
+    public function cacheExistPayEnterprise($enterpriseId)
+    {
+        return $this->cache->sadd($this->existPayEnterpriseKey, $enterpriseId);
+    }
+}

+ 395 - 0
Jobs/Cache/OverviewCache.Class.php

@@ -0,0 +1,395 @@
+<?php
+/**
+ * 首页概况缓存
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/11/5
+ * Time: 10:14
+ */
+
+namespace Jobs\Cache;
+
+use http\Exception;
+use Mall\Framework\Factory;
+use Mall\Framework\Core\ResultWrapper;
+use Mall\Framework\Core\ErrorCode;
+
+class OverviewCache
+{
+    private $cache;
+    private $expireTime = 86400;
+    private $orderDay = 7;//近7天订单趋势
+    protected $aggregateStatisticsKey = 'aggregateStatistics';//总数统计 区分企业
+    protected $businessOverviewEnterpriseKey = 'businessOverviewEnterprise';//经营概况_日期_企业Id_(全店)
+    protected $businessOverviewEnterpriseShopKey = 'businessOverviewEnterpriseShop';//经营概况_日期_企业Id_商铺id
+    protected $rankingEnterpriseKey = 'rankingEnterprise';//销量排行榜_日期_企业Id_(全店)
+    protected $rankingEnterpriseShopKey = 'rankingEnterpriseShop';//销量排行榜_日期_企业Id_商铺id
+    protected $salesMoneyRankingEnterpriseKey = 'salesMoneyRankingEnterprise';//销额排行榜_日期_企业Id_(全店)
+    protected $salesMoneyRankingEnterpriseShopKey = 'salesMoneyRankingEnterpriseShop';//销额排行榜_日期_企业Id_商铺id
+    protected $orderTrendKey = 'orderTrend';//近7天订单趋势_企业Id
+
+    public function __construct()
+    {
+        $this->cache = Factory::cache('finance');
+    }
+
+    /**
+     * 总数统计
+     * @param $enterpriseId
+     * @param string $key
+     * @param $change_num
+     * @return ResultWrapper
+     */
+    public function saveAggregateStatistics($enterpriseId, $key = 'totalShouldReceive', $change_num)
+    {
+        if (empty($key)) {
+            return ResultWrapper::fail('要缓存的数据为空', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->aggregateStatisticsKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        $ttl = $this->cache->ttl($Key);
+
+        $old = self::getAggregateStatistics($enterpriseId,$key);
+        $this->cache->hset($Key , $key, $change_num + $old);
+        //如果键没有设置,那么设置过期时间
+        if ($ttl == -2) {
+            $this->cache->expire($Key, $this->expireTime);
+        }
+    }
+
+    /**
+     * 获取总数统计
+     * @param $enterpriseId
+     * @param $key
+     * @return array
+     */
+    public function getAggregateStatistics($enterpriseId, $key = 'totalShouldReceive')
+    {
+        $Key = $this->aggregateStatisticsKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        $result = $this->cache->hget($Key, $key);
+        return $result ? $result : 0;
+    }
+
+    /**
+     * 删除总数统计
+     * @param $enterpriseId
+     * @param $key
+     * @return array
+     */
+    public function delAggregateStatistics($enterpriseId, $key = 'totalShouldReceive')
+    {
+        $Key = $this->aggregateStatisticsKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        return $this->cache->hdel($Key, $key);
+    }
+
+    /**************************经营概况 start**********************************/
+    /**
+     * 经营概况
+     * @param $enterpriseId
+     * @param string $key
+     * @param $change_num
+     * @param null $shopId
+     * @return ResultWrapper
+     */
+    public function saveBusinessOverview($enterpriseId, $key = 'orderTotalMoney', $change_num, $shopId = null)
+    {
+        if (empty($key)) {
+            return ResultWrapper::fail('要缓存的数据为空', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->businessOverviewEnterpriseKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->businessOverviewEnterpriseShopKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId . '::ShopId_' . $shopId;
+        }
+
+        $ttl = $this->cache->ttl($Key);
+
+        $old = self::getBusinessOverview($enterpriseId, $key, $shopId);
+        $this->cache->hset($Key, $key, $old + $change_num);
+
+        //如果键没有设置,那么设置过期时间
+        if ($ttl == -2) {
+            $this->cache->expire($Key, $this->expireTime);
+        }
+    }
+
+    /**
+     * 获取经营概况数字
+     * @param $enterpriseId
+     * @param string $key
+     * @param null $shopId
+     * @return ResultWrapper
+     */
+    public function getBusinessOverview($enterpriseId, $key = 'totalShouldReceive', $shopId = null)
+    {
+        if (empty($key)) {
+            return ResultWrapper::fail('要获取的key不存在', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->businessOverviewEnterpriseKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->businessOverviewEnterpriseShopKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId . '::ShopId_' . $shopId;
+        }
+
+        $result = $this->cache->hget($Key, $key);
+        return $result ? $result : 0;
+    }
+
+    /**
+     * 删除经营概况统计
+     * @param $enterpriseId
+     * @param string $key
+     * @param null $shopId
+     * @return mixed
+     */
+    public function delBusinessOverview($enterpriseId, $key = 'totalShouldReceive', $shopId = null)
+    {
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->businessOverviewEnterpriseKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->businessOverviewEnterpriseShopKey . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId . '::ShopId_' . $shopId;
+        }
+        return $this->cache->hdel($Key, $key);
+    }
+    /**************************经营概况 end**********************************/
+
+    /**************************销量排行榜 start**********************************/
+
+    /**
+     * 销量排行榜
+     * @param $enterpriseId
+     * @param string $suffix
+     * @param string $id
+     * @param $change_num
+     * @param null $shopId
+     * @return ResultWrapper
+     */
+    public function saveRanking($enterpriseId, $suffix = 'categoryRanking', $id, $change_num, $shopId = null)
+    {
+        if (empty($suffix) || empty($id)) {
+            return ResultWrapper::fail('要缓存的数据为空', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->rankingEnterpriseKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->rankingEnterpriseShopKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId.'::ShopId_'. $shopId;
+        }
+
+        $ttl = $this->cache->ttl($Key);
+
+        $old = $this->cache->zscore($Key, $id);
+        $old = $old ? $old : 0;
+        $change_num = bcmul($change_num,100);
+        $this->cache->zAdd($Key, bcadd($old,$change_num), $id);
+
+        //如果键没有设置,那么设置过期时间
+        if ($ttl == -2) {
+            $this->cache->expire($Key, $this->expireTime);
+        }
+    }
+
+    /**
+     * 获取排行榜,按score从大到小排行
+     * @param $enterpriseId
+     * @param string $suffix
+     * @param $id
+     * @param $change_num
+     * @param null $shopId
+     * @return ResultWrapper
+     */
+    public function getRanking($enterpriseId, $suffix = 'categoryRanking', $shopId = null)
+    {
+        if (empty($suffix)) {
+            return ResultWrapper::fail('要缓存的数据为空', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->rankingEnterpriseKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->rankingEnterpriseShopKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId.'::ShopId_'. $shopId;
+        }
+
+        $result = $this->cache->zRevRange($Key, 0, -1, true);
+        if(!empty($result)) {
+            foreach ($result as $key=>$value) {
+                if ($value) {
+                    $result[$key] = bcdiv($value,100,2);
+                }
+            }
+        }
+        return $result ? $result : [];
+    }
+
+    /**
+     * 删除排行榜 key
+     * @param $enterpriseId
+     * @param string $suffix
+     * @param null $shopId
+     * @return mixed
+     */
+    public function delRanking($enterpriseId, $suffix = 'categoryRanking', $shopId = null)
+    {
+        $Key = $this->rankingEnterpriseKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->rankingEnterpriseShopKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId.'::ShopId_'. $shopId;
+        }
+        return $this->cache->del($Key);
+    }
+
+    /**************************销量排行榜 end**********************************/
+
+    /**************************销额排行榜 start**********************************/
+
+    /**
+     * 销额排行榜
+     * @param $enterpriseId
+     * @param string $suffix
+     * @param string $id
+     * @param $change_num
+     * @param null $shopId
+     * @return ResultWrapper
+     */
+    public function saveSalesMoneyRanking($enterpriseId, $suffix = 'categoryRanking', $id, $change_num, $shopId = null)
+    {
+        if (empty($suffix) || empty($id)) {
+            return ResultWrapper::fail('要缓存的数据为空', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->salesMoneyRankingEnterpriseKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->salesMoneyRankingEnterpriseShopKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId.'::ShopId_'. $shopId;
+        }
+
+        $ttl = $this->cache->ttl($Key);
+
+        $old = $this->cache->zscore($Key, $id);
+        $old = $old ? $old : 0;
+        $change_num = bcmul($change_num,100);
+        $this->cache->zAdd($Key, bcadd($old, $change_num), $id);
+
+        //如果键没有设置,那么设置过期时间
+        if ($ttl == -2) {
+            $this->cache->expire($Key, $this->expireTime);
+        }
+    }
+
+    /**
+     * 获取排行榜,按score从大到小排行
+     * @param $enterpriseId
+     * @param string $suffix
+     * @param $id
+     * @param $change_num
+     * @param null $shopId
+     * @return ResultWrapper
+     */
+    public function getSalesMoneyRanking($enterpriseId, $suffix = 'categoryRanking', $shopId = null)
+    {
+        if (empty($suffix)) {
+            return ResultWrapper::fail('要缓存的数据为空', ErrorCode::$paramError);
+        }
+
+        //获取Key的过期时间,大于0的话就不再设置了
+        $Key = $this->salesMoneyRankingEnterpriseKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->salesMoneyRankingEnterpriseShopKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId.'::ShopId_'. $shopId;
+        }
+
+        $result = $this->cache->zRevRange($Key, 0, -1, true);
+        if(!empty($result)) {
+            foreach ($result as $key=>$value) {
+                if ($value) {
+                    $result[$key] = bcdiv($value,100,2);
+                }
+            }
+        }
+        return $result ? $result : [];
+    }
+
+    /**
+     * 删除排行榜 key
+     * @param $enterpriseId
+     * @param string $suffix
+     * @param null $shopId
+     * @return mixed
+     */
+    public function delSalesMoneyRanking($enterpriseId, $suffix = 'categoryRanking', $shopId = null)
+    {
+        $Key = $this->salesMoneyRankingEnterpriseKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId;
+        if (!empty($shopId)) {
+            $Key = $this->salesMoneyRankingEnterpriseShopKey . '::' . $suffix . '::' . date('Y-m-d') . '::EnterpriseId_' . $enterpriseId.'::ShopId_'. $shopId;
+        }
+        return $this->cache->del($Key);
+    }
+
+    /**************************销额排行榜 end**********************************/
+
+
+    /**************************近7天订单趋势 start**********************************/
+    /**
+     * 近7天订单趋势   订单审核后调用此方法
+     * @param $enterpriseId
+     * @param $orderMoney
+     * @param $goodsNum 商品数量
+     * @return void
+     */
+    public function saveOrderTrend($enterpriseId, $orderMoney, $goodsNum)
+    {
+        $Key = $this->orderTrendKey. '::EnterpriseId_' . $enterpriseId;
+
+        //删除前30天的值
+        $keys = $this->cache->hkeys($Key);
+        if(!empty($keys)) {
+            foreach ($keys as $k) {
+                if(strtotime($k) <= strtotime('-30 days')) {
+                    $this->cache->hdel($Key, $k);
+                }
+            }
+        }
+
+        //获取今天的值
+        $oldValue = $this->cache->hget($Key, date('Y-m-d'));
+        if(!empty($oldValue)) {
+            $oldValue = json_decode($oldValue, true);
+        }
+        $newValue = [
+            'orderMoney'=> $orderMoney + (isset($oldValue['orderMoney']) ? $oldValue['orderMoney'] : 0),
+            'goodsNum'=> $goodsNum + (isset($oldValue['goodsNum']) ? $oldValue['goodsNum'] : 0),
+            'orderNum'=> 1 + (isset($oldValue['orderNum']) ? $oldValue['orderNum'] : 0),
+        ];
+        $this->cache->hset($Key, date('Y-m-d'), json_encode($newValue));
+    }
+
+    /**
+     * 获取近7天订单趋势
+     * @param $enterpriseId
+     * @return ResultWrapper
+     */
+    public function getOrderTrend($enterpriseId)
+    {
+        $Key = $this->orderTrendKey. '::EnterpriseId_' . $enterpriseId;
+        $result = [];
+        for($i=6; $i>=0; $i--) {
+            $date = date('Y-m-d',strtotime("-$i days"));
+            $value = $this->cache->hget($Key, $date);
+
+            $value = empty($value) ? [] : json_decode($value, true);
+
+            $result[] = [
+                'date'       => $date,
+                'orderMoney' => isset($value['orderMoney']) ? $value['orderMoney'] : 0,
+                'goodsNum'   => isset($value['goodsNum']) ? $value['goodsNum'] : 0,
+                'orderNum'   => isset($value['orderNum']) ? $value['orderNum'] : 0,
+            ];
+        }
+
+        return $result;
+    }
+
+    /**************************近7天订单趋势 end**********************************/
+
+}

二进制
Jobs/Config/.DS_Store


+ 351 - 0
Jobs/Config/Config.php

@@ -0,0 +1,351 @@
+<?php
+return [
+    // 内置项目配置
+    'app_name'          => PROJECT_NAME,
+    'app_path'          => PROJECT_PATH,
+
+    // 自定义项目配置
+    //'logPath'           => PROJECT_PATH . '/log', // 项目日志目录
+    'logPath'           => PROJECT_PATH . '/log/crontab/'.date("Ymd"), // 项目日志目录
+    'logSaveFileApp'    => 'application.log', // 默认日志文件名称
+    'logSaveFileWorker' => 'crontab.log', // 进程启动相关log存储名字
+    'pidPath'           => PROJECT_PATH . '/log',
+    'sleep'             => 2, // 队列没消息时,暂停秒数
+    'queueMaxNum'       => 10, // 队列达到一定长度,启动动态子进程个数发和送消息提醒
+    'excuteTime'        => 3600, // 子进程最长执行时间,防止内存泄漏
+    'queueTickTimer'    => 1000 * 10, //一定时间间隔(毫秒)检查队列长度;默认10秒钟
+    'messageTickTimer'  => 1000 * 180, //一定时间间隔(毫秒)发送消息提醒;默认3分钟
+    'processName'       => ':swooleTopicQueue', // 设置进程名, 方便管理, 默认值 swooleTopicQueue
+
+
+    //job任务相关
+    'job'               => [
+        'topics' => [
+            ['name' => 'MyJob', 'workerMinNum' => 1, 'workerMaxNum' => 5],
+            //['name'=> 'MyJob2', 'workerMinNum'=>1, 'workerMaxNum'=>5],
+            //['name'=> 'MyJob3', 'workerMinNum'=>1, 'workerMaxNum'=>5],
+        ],
+        // redis
+        'queue'  => [
+            'class'    => 'Jobs\Model\Queue\MRedisTopicQueue',
+            'host'     => '127.0.0.1',
+            'port'     => 6379,
+            'password' => '',
+            'database' => 3,
+        ],
+
+        // rabbitmq
+        // 'queue'   => [
+        //     'class'         => '\Kcloze\Jobs\Queue\RabbitmqTopicQueue',
+        //     'host'          => '192.168.9.24',
+        //     'user'          => 'phpadmin',
+        //     'pass'          => 'phpadmin',
+        //     'port'          => '5671',
+        //     'vhost'         => 'php',
+        //     'exchange'      => 'php.amqp.ext',
+        // ],
+    ],
+
+    //框架类型及装载类
+    'framework'         => [
+        //可以自定义,但是该类必须继承\Kcloze\Jobs\Action\BaseAction
+        'class' => 'Jobs\Controller\CJobs',
+    ],
+
+    'message' => [
+        'class' => '\Kcloze\Jobs\Message\DingMessage',
+        'token' => '***your-dingding-token***',
+    ],
+
+    'db' => [
+        'default' => [
+            'driver' => 'mysql',
+            'host' => '127.0.0.1',
+            'port' => '3306',
+            'username' => 'root',
+            'password' => '0d6047adbbae53c7',
+            'dbname' => 'qnys_devanfei',
+            'prefix' => 'qianniao',
+            'pconnect' => 0,
+            'charset' => 'utf8',
+        ],
+        'stock' => [
+            'driver' => 'mysql',
+            'host' => '127.0.0.1',
+            'port' => '3306',
+            'username' => 'root',
+            'password' => '0d6047adbbae53c7',
+            'dbname' => 'qnys_devstock',
+            'prefix' => 'qianniao',
+            'pconnect' => 0,
+            'charset' => 'utf8',
+        ],
+        'price'   => [
+            'driver'   => 'mysql',
+            'host'     => '127.0.0.1',
+            'port'     => '3306',
+             'username' => 'root',
+            'password' => '0d6047adbbae53c7',
+            'dbname'   => 'qnys_devprice',
+            'prefix'   => 'qianniao',
+            'pconnect' => 0,
+            'charset'  => 'utf8',
+        ],
+        'log' => [
+            'driver' => 'mysql',
+            'host' => '127.0.0.1',
+            'port' => '3306',
+             'username' => 'root',
+            'password' => '0d6047adbbae53c7',
+            'dbname' => 'qnys_devlog',
+            'prefix' => 'qianniao',
+            'pconnect' => 0,
+            'charset' => 'utf8',
+        ],
+        'finance' => [
+            'driver' => 'mysql',
+            'host' => '127.0.0.1',
+            'port' => '3306',
+            'username' => 'root',
+            'password' => '0d6047adbbae53c7',
+            'dbname' => 'qnys_devfinan',
+            'prefix' => 'qianniao',
+            'pconnect' => 0,
+            'charset' => 'utf8',
+        ],
+    ],
+    'cache' => [
+        'default' => [
+            'storage' => 'redis',
+            'host' => '127.0.0.1',
+            'port' => '6379',
+            'auth' => '',
+            'prefix' => 'new_',
+            'database' => '0',
+        ],
+        'mapping' => [
+            'storage' => 'redis',
+            'host' => '127.0.0.1',
+            'port' => '6379',
+            'auth' => '',
+            'prefix' => 'new_',
+            'database' => '1',//用于缓存地区
+        ],
+        'user' => [
+            'storage' => 'redis',
+            'host' => '127.0.0.1',
+            'port' => '6379',
+            'auth' => '',
+            'prefix' => 'new_',
+            'database' => '2',
+        ],
+        'finance'    => [
+            'storage'  => 'redis',
+            'host'     => '127.0.0.1',
+            'port'     => '6379',
+            'auth'     => '',
+            'prefix'   => 'new_',
+            'database' => '3',
+        ],
+        'activity'  => [
+            'storage'  => 'redis',
+            'host'     => '127.0.0.1',
+            'port'     => '6379',
+            'auth'     => '',
+            'prefix'   => 'new_',
+            'database' => '5',
+        ],//活动
+    ],
+
+
+    'dataResources' => [
+        'ThirdPartyService' => [
+            'host'     => '',
+            'port'     => '9508',
+            'time_out' => -1,
+        ],
+    ],
+
+    'search' => [
+        'goods_search' =>[
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_goods_search',
+            'type' => 'goods',
+        ],
+        'customer_search' =>[
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_customer_search',
+            'type' => 'customer',
+        ],
+        'goods_basic_search' =>[
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_goodsbasic_search',
+            'type' => 'goodsBasic',
+        ],
+        'shop_search' =>[
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_shop_search',
+            'type' => 'shop',
+        ],
+        'order_search' =>[
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_order_search',
+            'type' => 'order',
+        ],
+        'priceAdjustmentSheet_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'online_priceadjustmentsheet_search',
+            'type'     => 'priceAdjustmentSheet',
+        ],
+        'customerPriceAdjustmentSheet_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'online_customer_price_adjustment_sheet_search',
+            'type'     => 'customerPriceAdjustmentSheet',
+        ],
+        'inventory_details_search' => [
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_inventory_details_search',
+            'type' => 'inventory_details',
+        ],
+        'purchase_details_search' => [
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_purchase_details_search',
+            'type' => 'purchase_details',
+        ],
+        'order_out_search' => [
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_order_out_search',
+            'type' => 'order_out',
+        ],
+        'inventory_out_search' => [
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_inventory_out_search',
+            'type' => 'inventory_out',
+        ],
+        'inventory_in_search' => [
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_inventory_in_search',
+            'type' => 'inventory_in',
+        ],
+        'inventory_batch_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'online_inventory_batch_search',
+            'type'     => 'inventory_batch',
+        ],
+        'should_receive_receipt_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'dev_should_receive_receipt_search',
+            'type'     => 'should_receive_receipt',
+        ],
+        'should_pay_receipt_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'dev_should_pay_receipt_search',
+            'type'     => 'should_pay_receipt',
+        ],
+        'activity_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'online_activity_search',
+            'type'     => 'activity',
+        ],
+        'login_log' =>[
+            'protocol' => 'http',
+            'servers' => [
+                '127.0.0.1:80'
+            ],
+            'timeout' => null,
+            'index' => 'online_login_log',
+            'type' => 'login',
+        ],
+        'logs' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'dev_logs',
+            'type'     => 'logs',
+        ],
+        'received_receipt_search'  => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'online_received_receipt_search',
+            'type'     => 'received_receipt',
+        ],
+        'user_coupon_search' => [
+            'protocol' => 'http',
+            'servers'  => [
+                '127.0.0.1:80'
+            ],
+            'timeout'  => null,
+            'index'    => 'online_user_coupon_search',
+            'type'     => 'user_coupon',
+        ],
+    ]
+];

+ 42 - 0
Jobs/Controller/BaseController.Class.php

@@ -0,0 +1,42 @@
+<?php
+namespace Jobs\Controller;
+
+use Mall\Framework\Factory;
+
+class BaseController
+{
+
+    /** @var  \Mall\Framework\Core\Request $request */
+    protected $request;
+
+    /** @var  \Mall\Framework\Core\Cache $cache */
+    protected $cache;
+
+    public function __construct($isCheckAcl = true)
+    {
+        $this->request = Factory::request();
+        //$this->cache = Factory::cache();
+    }
+
+
+    public function sendOutput($data, $errorcode = 0)
+    {
+        $errorcode = intval($errorcode);
+
+        if ($errorcode) {
+            $sendMessage = [
+                'state' => false,
+                'data' => $data,
+                'errorcode' => $errorcode
+            ];
+        } else {
+            $sendMessage = [
+                'state' => true,
+                'data' => $data,
+                'errorcode' => $errorcode
+            ];
+        }
+        exit(json_encode($sendMessage, JSON_UNESCAPED_UNICODE));
+    }
+
+}

+ 81 - 0
Jobs/Controller/CAddJob.Class.php

@@ -0,0 +1,81 @@
+<?php
+namespace Jobs\Controller;
+
+use Mall\Framework\Factory;
+use Mall\Framework\Core\ErrorCode;
+
+use Jobs\Controller\CJobObject;
+use Jobs\Controller\BaseController;
+use Jobs\Model\MQueue;
+use think\Error;
+
+class CAddJob extends BaseController
+{
+    private $objMQueue;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $config = Factory::config()->all();
+        $this->config      = $config;
+        $this->logger      = Factory::logs($this->config['logPath'] ?:'', $this->config['logSaveFileApp'] ?:'', $this->config['app_name'] ?:'');
+
+        $this->objMQueue = MQueue::getQueue($this->config['job']['queue'], $this->logger);
+        if(!is_object($this->objMQueue)){
+            exit('初始化队列失败');
+        }
+        $this->objMQueue->setTopics($this->config['job']['topics']);
+    }
+
+    /**
+     * 统一的添加队列任务入口
+     */
+    public function add()
+    {
+
+        /*$params['topicName'] = 'MyJob';                       // 推送到那个队列主题中
+        $params['topicClass'] = 'Jobs\Model\MTopic\Log\MLog'; // 往队列中添加得任务脚本类文件
+        $params['topicMethon'] = 'push';                     // 需要触发的类文件中的入口函数
+        $params['topicMethonParams'] = [
+            'userCenterId' => 1,
+            'enterpriseId' => 15,
+            'createTime'   => time(),//操作时间
+            'no' => 'Y12455f4545', // 来源:
+            'actionType'=> '新增订单', // 操作类型:登录/注册
+            'operationData' => [
+                "goodsId"=>12,
+                "name"=>"商品名称"
+            ], //本次操作请求的数据(可空) json格式
+        ];    // 携带过去的参数*/
+
+        //接收参数
+        $params['topicName'] = $this->request->param('topicName');
+        $params['topicClass'] = $this->request->param('topicClass');
+        $params['topicMethon'] = $this->request->param('topicMethon');
+        $params['topicMethonParams'] = $this->request->param('topicMethonParams');
+
+        foreach ($params as $key => $value){
+            if(empty($value)){
+                parent::sendOutput('参数'.$key.'值为空', ErrorCode::$paramError);
+            }
+        }
+
+        $jobExtras = [                              // 指定在队列中的执行优先级(redis版本队列不支持,带上就行)
+            'delay' => mt_rand(0, 100) * 1000,
+            'priority' => 1,
+        ];
+
+        if(!is_array($params['topicMethonParams'])){
+            $params['topicMethonParams'] = json_decode(htmlspecialchars_decode($params['topicMethonParams'], ENT_QUOTES), true);
+        }
+
+        $job    = new CJobObject($params['topicName'], $params['topicClass'], $params['topicMethon'], $params['topicMethonParams'], $jobExtras);
+        $result = $this->objMQueue->push($params['topicName'], $job);
+        if($result) {
+            parent::sendOutput('添加队列成功');
+        }
+        parent::sendOutput('添加队列失败',ErrorCode::$redisWriteError);
+    }
+
+}

+ 14 - 0
Jobs/Controller/CBase.Class.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace Jobs\Controller;
+
+abstract class CBase
+{
+    public function init()
+    {
+    }
+
+    public function start($JobObject)
+    {
+    }
+}

+ 195 - 0
Jobs/Controller/CESinit.Class.php

@@ -0,0 +1,195 @@
+<?php
+/**
+ * ElasticSearch 初始化脚本
+ * Created by PhpStorm.
+ * User: phperstar
+ * Date: 2019/2/23
+ * Time: 2:04 PM
+ */
+
+namespace Jobs\Controller;
+
+use Mall\Framework\Factory;
+use Mall\Framework\Core\Request;
+
+class CESinit
+{
+    /**
+     * Search Demo
+     */
+    public function search()
+    {
+        $data = Request::params();
+        $c = $data['b'] ?: 1;
+
+        switch ($c) {
+            // 添加wms日志索引库
+            case 1 :
+                $mappings = array(
+                    'mappings' => array(
+                        "_default_" => [
+                            "properties" => [
+                                'userId' => ['type' => 'integer'],
+                                "userName" => [
+                                    "type" => "text",
+                                    "store" => false,
+                                    "analyzer" => "ik_max_word",
+                                    "search_analyzer" => "ik_max_word",
+                                    "boost" => 10
+                                ],
+                                'object' => ['type' => 'keyword'],
+                                'actionType' => ['type' => 'keyword'],
+                                "logContent" => [
+                                    "type" => "text",
+                                    "store" => false,
+                                    "analyzer" => "ik_max_word",
+                                    "search_analyzer" => "ik_max_word",
+                                    "boost" => 5
+                                ],
+                                'time' => ['type' => 'integer'],
+                            ]
+                        ]
+                    )
+                );
+
+                $searchServer = Factory::search('wms');
+                $result = $searchServer->createBase('dev_wms_operation_log', $mappings);
+                if ($result && !isset($result['error'])) {
+                    echo 'dev_wms_operation_log init done.';
+                    return true;
+                } else {
+                    print_r($result['error']);
+                    return false;
+                }
+
+                break;
+            // 删除wms索引库
+            case 2:
+                $searchServer = Factory::search('wms');
+                $searchServer->setIndex('dev_wms_operation_log');
+                $a = $searchServer->deleteBase('dev_wms_operation_log');
+                print_r($a);
+                break;
+            // 添加oms订单状态日志索引库
+            case 3 :
+                $mappings = array(
+                    'mappings' => array(
+                        "_default_" => [
+                            "properties" => [
+                                'orderNo' => ['type' => 'keyword'],
+                                'status' => ['type' => 'integer'],
+                                'operationUserName' => ['type' => 'keyword'],
+                                'time' => ['type' => 'integer'],
+                            ]
+                        ]
+                    )
+                );
+
+                $searchServer = Factory::search('wms');
+                $result = $searchServer->createBase('dev_oms_orderstatus_log', $mappings);
+                if ($result && !isset($result['error'])) {
+                    echo 'dev_oms_orderstatus_log init done.';
+                    return true;
+                } else {
+                    print_r($result['error']);
+                    return false;
+                }
+
+                break;
+            // 删除oms订单状态索引库
+            case 4:
+                $searchServer = Factory::search('wms');
+                $searchServer->setIndex('dev_oms_orderstatus_log');
+                $a = $searchServer->deleteBase('dev_oms_orderstatus_log');
+                print_r($a);
+                break;
+            // 添加capital日志索引库
+            case 5 :
+                $mappings = array(
+                    'mappings' => array(
+                        "_default_" => [
+                            "properties" => [
+                                'userId' => ['type' => 'integer'],
+                                "userName" => [
+                                    "type" => "text",
+                                ],
+                                'object' => ['type' => 'keyword'],
+                                'actionType' => ['type' => 'keyword'],
+                                "logContent" => [
+                                    "type" => "text",
+                                    "store" => false,
+                                    "analyzer" => "ik_max_word",
+                                    "search_analyzer" => "ik_max_word",
+                                    "boost" => 5
+                                ],
+                                'time' => ['type' => 'integer'],
+                            ]
+                        ]
+                    )
+                );
+
+                $searchServer = Factory::search('capital');
+                $result = $searchServer->createBase('dev_capital_operation_log', $mappings);
+                if ($result && !isset($result['error'])) {
+                    echo 'dev_capital_operation_log init done.';
+                    return true;
+                } else {
+                    print_r($result['error']);
+                    return false;
+                }
+
+                break;
+            // 删除wms索引库
+            case 6:
+                $searchServer = Factory::search('capital');
+                $searchServer->setIndex('dev_capital_operation_log');
+                $a = $searchServer->deleteBase('dev_capital_operation_log');
+                print_r($a);
+                break;
+            // 添加oms日志索引库
+            case 7 :
+                $mappings = array(
+                    'mappings' => array(
+                        "_default_" => [
+                            "properties" => [
+                                'userId' => ['type' => 'integer'],
+                                "userName" => [
+                                    "type" => "text",
+                                ],
+                                'object' => ['type' => 'keyword'],
+                                'actionType' => ['type' => 'keyword'],
+                                "logContent" => [
+                                    "type" => "text",
+                                    "store" => false,
+                                    "analyzer" => "ik_max_word",
+                                    "search_analyzer" => "ik_max_word",
+                                    "boost" => 5
+                                ],
+                                'time' => ['type' => 'integer'],
+                            ]
+                        ]
+                    )
+                );
+
+                $searchServer = Factory::search('oms');
+                $result = $searchServer->createBase('dev_oms_operation_log', $mappings);
+                if ($result && !isset($result['error'])) {
+                    echo 'dev_oms_operation_log init done.';
+                    return true;
+                } else {
+                    print_r($result['error']);
+                    return false;
+                }
+
+                break;
+            // 删除wms索引库
+            case 8:
+                $searchServer = Factory::search('oms');
+                $searchServer->setIndex('dev_oms_operation_log');
+                $a = $searchServer->deleteBase('dev_oms_operation_log');
+                print_r($a);
+                break;
+
+        }
+    }
+}

+ 22 - 0
Jobs/Controller/CJobObject.Class.php

@@ -0,0 +1,22 @@
+<?php
+namespace Jobs\Controller;
+
+class CJobObject
+{
+    public $uuid        =''; //job uuid
+    public $topic       =''; //job 队列名
+    public $jobClass    =''; //job 执行类
+    public $jobMethod   =''; //job 执行方法
+    public $jobParams   =[]; //job参数
+    public $jobExtras   =[]; //附件信息,delay/expiration/priority等
+
+    public function __construct( $topic, $jobClass, $jobMethod, array $jobParams=[], array $jobExtras=[])
+    {
+        $this->uuid       =uniqid($topic) . '.' . microtime(true);
+        $this->topic      =$topic;
+        $this->jobClass   =$jobClass;
+        $this->jobMethod  =$jobMethod;
+        $this->jobParams  =$jobParams;
+        $this->jobExtras  =$jobExtras;
+    }
+}

+ 38 - 0
Jobs/Controller/CJobs.Class.php

@@ -0,0 +1,38 @@
+<?php
+namespace Jobs\Controller;
+
+use Mall\Framework\Factory;
+use Jobs\Controller\CBase;
+
+class CJobs extends CBase
+{
+    private $logger=null;
+
+    public function __construct($config)
+    {
+        $this->config      = $config;
+        $this->logger      = Factory::logs($this->config['logPath'] ?:'', $this->config['logSaveFileApp'] ?:'', $this->config['app_name'] ?:'');
+    }
+
+    public function start($JobObject)
+    {
+        $jobClass =$JobObject->jobClass;
+        $jobMethod=$JobObject->jobMethod;
+        $jobParams=$JobObject->jobParams;
+        try {
+            $obj      =new $jobClass();
+            if (is_object($obj) && method_exists($obj, $jobMethod)) {
+                $result = call_user_func([$obj, $jobMethod], $jobParams);
+                $this->logger->log('topic run result: ' . $result, 'error');
+            } else {
+                $this->logger->log('Action obj not find: ' . json_encode($JobObject), 'error');
+            }
+        } catch (\Throwable $e) {
+            catchError($this->logger, $e);
+        } catch (\Exception $e) {
+            catchError($this->logger, $e);
+        }
+
+        $this->logger->log('Action has been done, action content: ' . json_encode($JobObject));
+    }
+}

+ 647 - 0
Jobs/Controller/Test.Class.php

@@ -0,0 +1,647 @@
+<?php
+/**
+ * 测试队列任务脚本入口文件
+ * Created by PhpStorm.
+ * User: phperstar
+ * Date: 2018/6/10
+ * Time: 下午4:49
+ */
+
+namespace Jobs\Controller;
+
+
+use Jobs\Dao\DCloudUsers;
+use Jobs\Dao\DUsersTestify;
+use Jobs\Model\MTopic\Push\MPush;
+use Jobs\Model\Middleware;
+
+use Jobs\Dao\DCloudUsersCategory;
+use Jobs\Dao\DUsersCategory;
+use Jobs\Dao\DGoodsSku;
+use Jobs\Dao\DGoods;
+use Jobs\Model\Test\K3Handle;
+use Jobs\Dao\DOrder;
+
+use Jobs\Model\MTopic\Finance\MReceivable;
+
+use Mall\Framework\Db\Db;
+
+class Test
+{
+    /**
+     * php ./Public/www/index.php --c=Test --a=Test
+     */
+    public function test()
+    {
+        $objMReceivable = new MReceivable();
+        $params = [
+            'userCenterId' => 35,
+            'enterpriseId' => 64,
+            'id'      => 9,
+            'type'         => 5,
+        ];
+        $objMReceivable->createReceivable($params);
+    }
+
+
+
+    public function testk3()
+    {
+        //K/3 Cloud 业务站点地址
+        $cloudUrl = "http://123.206.51.139/k3cloud/";
+
+        //登陆参数
+        $data = array(
+            '597be128163613',//帐套Id
+            '秦统业',//用户名
+            'Cwb20141222',//密码
+            2052//语言标识
+        );
+
+        //定义记录Cloud服务端返回的Session
+        $cookie_jar = tempnam('./tmp','CloudSession');
+        $post_content = self::create_postdata($data);
+
+        //$result = invoke_login($cloudUrl,$post_content,$cookie_jar);
+        $loginurl = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc';
+        $result = self::invoke_post($loginurl,$post_content,$cookie_jar,TRUE);
+
+        header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('登陆请求数据:');
+        //echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('登陆返回结果:');
+        //echo '<pre>';print_r($result);
+
+
+
+
+
+        unset($post_content);
+        unset($result);
+        unset($data);
+        /*$data = array(
+            'FormId'=>'STK_Inventory',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>10,
+            'StartRow'=>0,
+            'OrderString'=>'FID ASC',
+            'FieldKeys'=>'FMaterialId,FMaterialId.FNumber,FStockName,FMaterialName,FBaseQty,FStockStatusId,FStockOrgId.FNumber',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId=147946",//过滤(非必录)
+        );*/
+
+        /*$k3GoodsInfo = '{"FormId":"STK_Inventory","FieldKeys":"FMaterialId.FNumber,FMaterialName,FStockUnitId.FName,FBaseQty",
+                                    "FilterString":"FMaterialId=147946 and ( FStockName = \'菏泽G1库\' or FStockName = \'绿源冷库\' or FStockName = \'绿源冷库3号库\' )",
+                                    "OrderString":"","TopRowCount":"0","StartRow":"0","Limit":"100"}';*/
+
+        $data = array(
+            'FormId'=>'STK_Inventory',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>100,
+            'StartRow'=>0,
+            'OrderString'=>'',
+            'FieldKeys'=>'FMaterialId,FMaterialId.FNumber,FStockName,FMaterialName,FBaseQty,FStockStatusId,FStockOrgId.FNumber',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId.FNumber ='0602070004' and (FStockName = '菏泽G1库' or FStockName = '绿源冷库' or FStockName = '绿源冷库3号库') and FStockOrgId.FNumber='101' ",//过滤(非必录)
+        );
+
+
+        //定义记录Cloud服务端返回的Session
+        $post_content = self::create_postdata([$data]);
+
+        $url = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc';
+        $result = self::invoke_post($url,$post_content,$cookie_jar,false);
+
+        header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('及时库存请求数据:');
+        //echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('及时库存返回结果:');
+        echo '<pre>';var_dump(json_decode($result, true));
+
+        $k3Weight = 0.00;
+        $resultArray = json_decode($result, true);
+        if(!empty($resultArray)){
+            foreach ($resultArray as $key => $value){
+                $k3Weight += $value[4];
+            }
+        }
+        var_dump($k3Weight);
+        return $k3Weight;
+    }
+
+    public function testk4()
+    {
+        //K/3 Cloud 业务站点地址
+        $cloudUrl = "http://123.206.51.139/k3cloud/";
+
+        //登陆参数
+        $data = array(
+            '597be128163613',//帐套Id
+            '秦统业',//用户名
+            'Cwb20141222',//密码
+            2052//语言标识
+        );
+
+        //定义记录Cloud服务端返回的Session
+        $cookie_jar = tempnam('./tmp','CloudSession');
+        $post_content = self::create_postdata($data);
+
+        //$result = invoke_login($cloudUrl,$post_content,$cookie_jar);
+        $loginurl = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc';
+        $result = self::invoke_post($loginurl,$post_content,$cookie_jar,true);
+
+        header("Content-type: text/html; charset=gb2312");
+        echo '<pre>';print_r('登陆请求数据:');
+        echo '<pre>';print_r($post_content);
+
+        echo '<pre>';print_r('登陆返回结果:');
+        echo '<pre>';print_r($result);
+
+
+
+
+
+        unset($post_content);
+        unset($result);
+        unset($data);
+        /*$data = array(
+            'FormId'=>'STK_Inventory',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>10,
+            'StartRow'=>0,
+            'OrderString'=>'FID ASC',
+            'FieldKeys'=>'FMaterialId,FMaterialId.FNumber,FStockName,FMaterialName,FBaseQty,FStockStatusId,FStockOrgId.FNumber',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId=147946",//过滤(非必录)
+        );*/
+
+        /*$k3GoodsInfo = '{"FormId":"STK_Inventory","FieldKeys":"FMaterialId.FNumber,FMaterialName,FStockUnitId.FName,FBaseQty",
+                                    "FilterString":"FMaterialId=147946 and ( FStockName = \'菏泽G1库\' or FStockName = \'绿源冷库\' or FStockName = \'绿源冷库3号库\' )",
+                                    "OrderString":"","TopRowCount":"0","StartRow":"0","Limit":"100"}';*/
+
+
+        $data = '{"Model":{"FNumber":"xyc2218","FCreateOrgId":{"FNumber":"101"},"FUseOrgId":{"FNumber":"101"},"FName":"u5218u5e05uff08u4ebfu6210u98dfu54c1u5185u90e8u5458u5de5uff09","FTEL":"18114640037","FADDRESS":"u5c71u4e1cu7701u6d4eu5357u5e02u5386u4e0bu533au6d4bu8bd5u5730u5740","FSALDEPTID":{"FNumber":"0020"},"FSALGROUPID":{"FNumber":"16"},"FSELLER":{"FNumber":"0020"},"FCustTypeId":{"FNumber":"KHLB001_SYS"},"FTRADINGCURRID":{"FNumber":"PRE001"},"F_PAEZ_Assistant3":{"FNumber":"0101"},"F_PAEZ_Assistant5":{"FNumber":"01"}},"Creator":"u4ebfu6210u5546u57ce"}';
+
+        //定义记录Cloud服务端返回的Session
+        $post_content = self::create_postdata(["BD_Customer",$data]);
+
+        $url = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc';
+        $result = self::invoke_post($url,$post_content,$cookie_jar,false);
+
+        //header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('及时库存请求数据:');
+        echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('及时库存返回结果:');
+        //file_put_contents('/tmp/11.log',var_export($result,true),FILE_APPEND);
+        V($result);
+
+    }
+
+
+    // 采购入库单
+    public function testk5()
+    {
+        //K/3 Cloud 业务站点地址
+        $cloudUrl = "http://123.206.51.139/k3cloud/";
+
+        //登陆参数
+        $data = array(
+            '597be128163613',//帐套Id
+            '秦统业',//用户名
+            'Cwb20141222',//密码
+            2052//语言标识
+        );
+
+        //定义记录Cloud服务端返回的Session
+        $cookie_jar = tempnam('./tmp','CloudSession');
+        $post_content = self::create_postdata($data);
+
+        //$result = invoke_login($cloudUrl,$post_content,$cookie_jar);
+        $loginurl = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc';
+        $result = self::invoke_post($loginurl,$post_content,$cookie_jar,TRUE);
+
+        header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('登陆请求数据:');
+        //echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('登陆返回结果:');
+        //echo '<pre>';print_r($result);
+
+
+
+
+
+        unset($post_content);
+        unset($result);
+        unset($data);
+        /*$data = array(
+            'FormId'=>'STK_Inventory',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>10,
+            'StartRow'=>0,
+            'OrderString'=>'FID ASC',
+            'FieldKeys'=>'FMaterialId,FMaterialId.FNumber,FStockName,FMaterialName,FBaseQty,FStockStatusId,FStockOrgId.FNumber',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId=147946",//过滤(非必录)
+        );*/
+
+        /*$k3GoodsInfo = '{"FormId":"STK_Inventory","FieldKeys":"FMaterialId.FNumber,FMaterialName,FStockUnitId.FName,FBaseQty",
+                                    "FilterString":"FMaterialId=147946 and ( FStockName = \'菏泽G1库\' or FStockName = \'绿源冷库\' or FStockName = \'绿源冷库3号库\' )",
+                                    "OrderString":"","TopRowCount":"0","StartRow":"0","Limit":"100"}';*/
+
+        $data = array(
+            'FormId'=>'STK_InStock',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>1,
+            'StartRow'=>0,
+            'OrderString'=>'FBillNo desc',
+            'FieldKeys'=>'FMaterialId.FNumber,FID,FDate,FBillNo,FDocumentStatus,FMaterialId,FStockStatusid,FMaterialName',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId.FNumber ='01110101010001',FDocumentStatus = 'c'",//过滤(非必录)
+        );
+
+
+        //定义记录Cloud服务端返回的Session
+        $post_content = self::create_postdata([$data]);
+
+        $url = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc';
+        $result = self::invoke_post($url,$post_content,$cookie_jar,false);
+
+        header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('及时库存请求数据:');
+        //echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('及时库存返回结果:');
+        V(json_decode($result, true));
+    }
+
+
+    // 销售退货单
+    public function testk6()
+    {
+        //K/3 Cloud 业务站点地址
+        $cloudUrl = "http://123.206.51.139/k3cloud/";
+
+        //登陆参数
+        $data = array(
+            '597be128163613',//帐套Id
+            '秦统业',//用户名
+            'Cwb20141222',//密码
+            2052//语言标识
+        );
+
+        //定义记录Cloud服务端返回的Session
+        $cookie_jar = tempnam('./tmp','CloudSession');
+        $post_content = self::create_postdata($data);
+
+        //$result = invoke_login($cloudUrl,$post_content,$cookie_jar);
+        $loginurl = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc';
+        $result = self::invoke_post($loginurl,$post_content,$cookie_jar,TRUE);
+
+        header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('登陆请求数据:');
+        //echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('登陆返回结果:');
+        //echo '<pre>';print_r($result);
+
+
+
+
+
+        unset($post_content);
+        unset($result);
+        unset($data);
+        /*$data = array(
+            'FormId'=>'STK_Inventory',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>10,
+            'StartRow'=>0,
+            'OrderString'=>'FID ASC',
+            'FieldKeys'=>'FMaterialId,FMaterialId.FNumber,FStockName,FMaterialName,FBaseQty,FStockStatusId,FStockOrgId.FNumber',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId=147946",//过滤(非必录)
+        );*/
+
+        /*$k3GoodsInfo = '{"FormId":"STK_Inventory","FieldKeys":"FMaterialId.FNumber,FMaterialName,FStockUnitId.FName,FBaseQty",
+                                    "FilterString":"FMaterialId=147946 and ( FStockName = \'菏泽G1库\' or FStockName = \'绿源冷库\' or FStockName = \'绿源冷库3号库\' )",
+                                    "OrderString":"","TopRowCount":"0","StartRow":"0","Limit":"100"}';*/
+
+        $data = array(
+            'FormId'=>'STK_InStock',//业务对象表单Id(必录)
+            'TopRowCount'=>0, // 最多允许查询的数量,0或者不要此属性表示不限制
+            'Limit'=>1,
+            'StartRow'=>0,
+            'OrderString'=>'FBillNo desc',
+            'FieldKeys'=>'FMaterialId.FNumber,FID,FDate,FBillNo,FDocumentStatus,FMaterialId,FStockStatusid,FMaterialName',//字段keys,字符串类型用逗号分隔,比如"key1,key2..."(必录)
+            'FilterString'=>"FMaterialId.FNumber ='01110101010001',FDocumentStatus = 'c'",//过滤(非必录)
+        );
+
+
+        //定义记录Cloud服务端返回的Session
+        $post_content = self::create_postdata([$data]);
+
+        $url = $cloudUrl.'Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc';
+        $result = self::invoke_post($url,$post_content,$cookie_jar,false);
+
+        header("Content-type: text/html; charset=gb2312");
+        //echo '<pre>';print_r('及时库存请求数据:');
+        //echo '<pre>';print_r($post_content);
+
+        //echo '<pre>';print_r('及时库存返回结果:');
+        V(json_decode($result, true));
+    }
+
+
+
+
+
+
+
+
+
+    //构造Web API请求格式
+    public function create_postdata($args) {
+        $postdata = array(
+            'format'=>1,
+            'useragent'=>'ApiClient',
+            'rid'=>self::create_guid(),
+            'parameters'=>$args,
+            'timestamp'=>date('Y-m-d'),
+            'v'=>'1.0'
+        );
+        return json_encode($postdata);
+    }
+
+    public function create_guid() {
+        $charid = strtoupper(md5(uniqid(mt_rand(), true)));
+        $hyphen = chr(45);// "-"
+        $uuid = chr(123)// "{"
+            .substr($charid, 0, 8).$hyphen
+            .substr($charid, 8, 4).$hyphen
+            .substr($charid,12, 4).$hyphen
+            .substr($charid,16, 4).$hyphen
+            .substr($charid,20,12)
+            .chr(125);// "}"
+        return $uuid;
+    }
+
+    public function invoke_post($url,$post_content,$cookie_jar,$isLogin)
+    {
+        $ch = curl_init($url);
+
+        $this_header = array(
+            'Content-Type: application/json',
+            'Content-Length: '.strlen($post_content)
+        );
+
+        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $this_header);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_content);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        if($isLogin){
+            curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar);
+        }
+        else{
+            curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_jar);
+        }
+        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+
+        $result = curl_exec($ch);
+        curl_close($ch);
+
+        return $result;
+    }
+
+
+    public static function s_put_txt()
+    {
+
+        $objDOrder = new DOrder('pifabbc');
+        $orderData = $objDOrder->query('SELECT order_id,buyer_id,order_no,order_status,created_at,pay_money,payment_type from ns_order');
+        foreach ($orderData as $key => $value){
+            $buyerids[] = $value['buyer_id'];
+            $orderData[$value['order_id']] = $value;
+        }
+
+
+        $objDusersCategory = new DUsersCategory('pifabbc');
+        $infos = $objDusersCategory ->query('SELECT
+                     t.id,
+                     t.user_id as user_id,
+                    t.contact_phone,
+                    t.legal_person,
+                    r.referee_name,
+                    g.group_name,
+                    c.id as category_id,
+                    c.category_name,
+                    c.pid,
+                    t.check_status,
+                    t.company_address,
+                    t.detail_address,
+                    t.erp_no
+                FROM
+                    cloud_users_testify AS t,
+                    cloud_referee AS r,
+                    cloud_referee_group AS g,
+                    cloud_users_category AS c
+                WHERE
+                    t.referrer_no = r.referee_no
+                    AND t.referrer_group_no = g.group_no
+                    AND t.category_id = c.id and t.user_id in ('.implode(',', $buyerids).')');
+
+        if (!empty($infos)){
+            foreach ($infos as $key => $value) {
+                if ($value['pid'] != 0) {
+                    $data = self::s_handle($value);
+                }
+                $info = array_merge($value, $data);
+                $data_file = implode(',', $info);
+
+                $userData[$value['user_id']] = $data_file;
+            }
+        }
+
+        foreach ($orderData as $key => $value){
+            $content = $userData[$value['user_id']].','.implode(',', $value);
+            file_put_contents('order.txt',$content . PHP_EOL,FILE_APPEND) ;
+            unset($content);
+        }
+
+
+//        $data_file = implode(',', $file);
+//
+//        file_put_contents('cat.txt', $data_file);
+    }
+
+    public static function s_handle(&$info_value)
+    {
+        $objDusersCategory = new DUsersCategory();
+        $id = $info_value['pid'];
+        $detail = $objDusersCategory->get($id);
+        if (!empty($detail)) {
+            $info_value[] = $detail['category_name'];
+            $info_value['pid'] = $detail['pid'];
+            self::s_handle($info_value);
+        }
+        return $info_value;
+    }
+
+    //php ./Jobs/Public/www/index.php --c=Test --a=userErpReset
+    public static function userErpReset(){
+        $objectDCloudUsers = new DCloudUsers();
+        $objectDUsersTestify = new DUsersTestify();
+        $fileName = 'k3id.txt';
+        /*
+ * 逐行读取TXT文件
+ */
+            $file = fopen($fileName,'r');
+
+            $content = array();
+            if(!$file){
+                return 'file open fail';
+            }else{
+                $i = 0;
+                while (!feof($file)){
+                    $content = mb_convert_encoding(fgets($file),"UTF-8","GBK,ASCII,ANSI,UTF-8");
+//print_r($content);
+
+                    $data = explode(',',$content);
+
+                    $info = $objectDUsersTestify -> get(['erp_no' => $data[1]]);
+
+                    if (empty($info)){
+                        echo 0;
+                        continue;
+                    }else{
+                        $res = $objectDUsersTestify ->update(['k3_id'=>$data[0]],['erp_no' => $data[1]]);
+
+                        echo $res;
+
+                    }
+
+
+
+                }
+//                fclose($file);
+//                $content = array_filter($content); //数组去空
+            }
+
+//            return $content;
+
+
+
+
+    }
+
+    //php ./Jobs/Public/www/index.php --c=Test --a=resetErpNo
+    public static function resetErpNo(){
+        $log ='';
+        $objectDCloudUsers = new DCloudUsers();
+        $objectDUsersTestify = new DUsersTestify();
+        $sql = "select *from cloud_users_testify WHERE  SUBSTR(erp_no,1,3) !='xyc'";
+        $data = $objectDUsersTestify ->query($sql);
+
+        $log .= 'ID,客户新编号,客户旧编号,客户推荐人编码,客户推荐人组织编码,客户推荐人电话'.PHP_EOL;
+        $K3Handle = new K3Handle();
+        foreach($data as $value){
+
+            $id = $value['id'];
+//V($value);
+
+            if(!$value['erp_no']){
+                continue;
+            }
+            $erp_no = 'xyc'.$value['user_id'];
+            $res = $objectDUsersTestify -> update(['erp_no'=>$erp_no],['id'=>$id]);
+            $res = $K3Handle ->store($value,$erp_no);
+            if ($res['code'] !=200){
+continue;
+            }
+            $log .= $id.','.$erp_no.','.$value['erp_no']?:'空'.','.$value['referrer_no'].','.$value['referrer_group_no'].','.$value['referrer_phone'].PHP_EOL;
+        }
+        file_put_contents('update_erp_no.txt',$log,FILE_APPEND);
+    }
+
+
+
+
+//php ./Jobs/Public/www/index.php --c=Test --a=export
+    public static function export(){
+
+       $objDOrder = new DOrder('pifabbc');
+         $orderData = $objDOrder->query('SELECT sum(pay_money) as order_money ,count(order_id) as total_count,buyer_id  from ns_order where order_status <>5 group by buyer_id');
+         $a =[];
+        foreach ($orderData as $key => $value){
+        //$buyerids[] = $value['buyer_id'];
+        $a[$value['buyer_id']] = $value;
+        }
+        $objDusersCategory = new DUsersCategory('pifabbc');
+        $infos = $objDusersCategory ->query('SELECT
+                             t.id,
+                             t.user_id as user_id,
+                            t.contact_phone,
+                            t.legal_person,
+                            r.referee_name,
+                            g.group_name,
+                            c.id as category_id,
+                            c.category_name,
+                            c.pid,
+                            t.check_status,
+                            t.company_address,
+                            t.detail_address,
+                            t.erp_no
+                        FROM
+                            cloud_users_testify AS t,
+                            cloud_referee AS r,
+                            cloud_referee_group AS g,
+                            cloud_users_category AS c
+                        WHERE
+                            t.referrer_no = r.referee_no
+                            AND t.referrer_group_no = g.group_no
+                            AND t.category_id = c.id and t.user_id ');
+        $user =[];
+
+
+        if (!empty($infos)){
+            foreach ($infos as $key => $value) {
+                if ($value['pid'] != 0) {
+                    $data = self::s_handle($value);
+                }
+                $user[$value['user_id']] = $data;
+            }
+        }
+
+        foreach ($user as $key => $value){
+            echo 1 .'//';
+            echo ($key);
+//            $orderMoney = $objDOrder->query("SELECT sum('pay_money') as order_money ,count('order_id') as total_count from ns_order where order_status <>5 and buyer_id = $key");
+            $lastTime = $objDOrder->query("SELECT created_at from ns_order where order_status <>5 and buyer_id = $key ORDER by  order_id DESC limit 0,1");
+
+            if (isset($a[$key])){
+                $content = implode(',', $value).','.'总金额:'.$a[$key]['order_money']?:0;
+                $content .= ',订单数:'.$a[$key]['total_count']?:0 ;
+                $content .= ',最后下单时间:'.$lastTime[0]['created_at']?:0 ;
+            }else{
+                $content = implode(',', $value);
+            }
+    file_put_contents('export.txt',$content . PHP_EOL,FILE_APPEND) ;
+    unset($content);
+
+        }
+    }
+
+    public function ce(){
+        $objDOrder = new DOrder('pifabbc');
+
+        $lastTime = $objDOrder->query("SELECT created_at from ns_order where order_status <>5 and buyer_id = 4739 ORDER by  order_id DESC limit 0,1");
+        V($lastTime);
+    }
+
+    public function jpush()
+    {
+        $swResult = Middleware::getInstance('ThirdPartyService')->sendSwoole('Jpush', 'broadcastPush', ['alias'=>['7581'],'content'=>'优鲜供应链新版即将发布']);
+        if( !$swResult['state'] ){
+            V( $swResult['data']);
+        }else{
+            V($swResult['data']);
+        }
+    }
+}

+ 309 - 0
Jobs/Dao/BaseDao.Class.php

@@ -0,0 +1,309 @@
+<?php
+
+namespace Jobs\Dao;
+
+use Mall\Framework\Core\SqlHelper;
+use Mall\Framework\Factory;
+
+use Jobs\Cache\AllTableNameCache;
+
+class BaseDao extends SqlHelper
+{
+    /**
+     * @var \Mall\Framework\SearchClient\Client
+     */
+    private $search;
+
+    /**
+     * 当前操作的数据库配置标识
+     * @var $serviceDB
+     */
+    private $serviceDB;
+
+    /**
+     * 参考文章: https://www.php.cn/php-weizijiaocheng-403412.html
+     * 开启事务数量统计
+     * BaseDao constructor.
+     * @param string $serviceDB
+     */
+    private $transactions;
+
+    public function __construct($serviceDB = 'default')
+    {
+        $this->serviceDB = $serviceDB;
+
+        parent::__construct($serviceDB);
+
+        //$this->setSearchIndex($serviceDB);
+    }
+
+
+    /**
+     * 设置搜索引擎配置项
+     *
+     * @param string $serviceDB
+     *
+     * @throws \Exception
+     * @return \Mall\Framework\SearchClient\Client
+     */
+    public function setSearchIndex($serviceDB)
+    {
+        $this->search = Factory::search($serviceDB);
+
+        return $this->search;
+    }
+
+    /**
+     * 计算分表表名
+     *
+     * @param string $prefix 表名前缀
+     * @param int $id 索引表id
+     * @param int $pNumber 分割数量
+     *
+     * @return string
+     */
+    public function getTableName($prefix, $id, $pNumber = 500000)
+    {
+        $prefix = trim($prefix, '_') . '_';
+        $tableName = strtolower($prefix . ceil($id / $pNumber));
+
+        return $tableName;
+    }
+
+    /**
+     * 切换Dao层操作的表
+     * 主要用作切换分表使用
+     *
+     * @param $tableName
+     *
+     * @throws \Exception
+     */
+    public function setTable($tableName)
+    {
+        $this->_table = $tableName;
+
+        $databaseName = Factory::config()->get('db')[$this->serviceDB]['dbname'];
+
+        // 当前使用库所有表名缓存如果不存在自动更新
+        if (!AllTableNameCache::allTableNameCacheIsExists($databaseName)) {
+            $tables = $this->db->select("SELECT TABLE_NAME FROM INFORMATION_SCHEMA. TABLES WHERE TABLE_SCHEMA = '{$databaseName}';") ?: [];
+            if (!empty($tables)) {
+                AllTableNameCache::allTableNameCache($databaseName, $tables);
+            }
+        }
+        var_dump("xxxxaaaa");
+var_dump($databaseName);
+var_dump($tableName);
+
+        // 判断切换的表是否存在,不存在自动创建
+        if (!AllTableNameCache::TableIsExists($databaseName, $tableName)) {
+            $result = explode('_', $tableName);
+            if ($result && !empty($result)) {
+                $tablePrefix = '';
+                for ($i = 0, $c = count($result); $i < ($c - 1); $i++) {
+                    if(!is_numeric($result[$i])){
+                        $tablePrefix .= $result[$i] . '_';
+                    }
+                }
+
+                $dbresult = $this->db->query("CREATE TABLE {$tableName} LIKE {$tablePrefix}1");
+                if ($dbresult === false) {
+                    throw new \Exception($tableName . '分表创建错误. ErrorInfo: ' . var_export($this->db->error(), true));
+                }
+            } else {
+                throw new \Exception($tableName . '不是一个正确得表名');
+            }
+            AllTableNameCache::addNewTableName($databaseName, $tableName);
+        }
+    }
+
+    /**
+     * 添加数据
+     *
+     * @param array $params
+     *
+     * @return bool|int
+     */
+    public function insert($params = array(), $multiple = false)
+    {
+        return parent::insert($params, $multiple);
+    }
+
+    /**
+     * replace方式添加数据
+     *
+     * @param array $params
+     *
+     * @return bool|int
+     */
+    public function replace($params = array(), $multiple = false)
+    {
+        return parent::replace($params, $multiple);
+    }
+
+    /**
+     * 更新数据
+     *
+     * @param array $data
+     * @param null $where
+     * @param null $limit
+     * @param null $order
+     *
+     * @return int
+     */
+    public function update($data = array(), $where = null, $limit = null, $order = null)
+    {
+
+        return parent::update($data, $where, $limit, $order);
+    }
+
+    /**
+     * 删除数据
+     *
+     * @param null $where
+     * @param null $limit
+     * @param null $order
+     * @param array $data
+     *
+     * @return int
+     */
+    public function delete($where = null, $limit = null, $order = null, $data = array())
+    {
+        return parent::delete($where, $limit, $order, $data);
+    }
+
+    /**
+     * 执行sql
+     */
+    public function query($sql)
+    {
+        return parent::query($sql);
+    }
+
+    /**
+     * 获取Sql操作错误
+     *
+     * @return string
+     */
+    public function error()
+    {
+        return parent::error();
+    }
+
+    /**
+     * 过虑字段
+     *
+     * @param array $params 要筛选的数据
+     *
+     * @return array
+     */
+    public function getTablesFields($params)
+    {
+        $fields = [];
+
+        foreach ($this->_fields as $field) {
+            if (array_key_exists($field, $params)) {
+                $fields[$field] = $params[$field];
+            }
+        }
+
+        return $fields;
+    }
+
+    /**
+     * 根据DSL查询文档
+     *
+     * @param $query
+     *
+     * @return array
+     */
+    public function getSearchQueryDsl($query)
+    {
+        return $this->search->search($query);
+    }
+
+    /**
+     * 根据索引的主ID查询文档
+     *
+     * @param int $id 索引的DocumentId
+     *
+     * @return array
+     */
+    public function getSearchIndexDocument($id)
+    {
+        $id = intval($id);
+        return $this->search->get($id);
+    }
+
+    /**
+     * 添加或更新ES索引
+     *
+     * @param array $data 创建索引数据
+     * @param int $id 创建索引的DocumentId
+     *
+     * @return array
+     */
+    public function addUpSearchIndexDocument($data, $id)
+    {
+        return $this->search->index($data, $id);
+    }
+
+    /**
+     * 局部更新索引内容
+     * @param array $data 要更新的数据
+     * @param int $id 要更新的文档下的数据id
+     * @return array
+     */
+    public function esupdateTypeFieldVaule($data, $id)
+    {
+        return $this->search->updateFieldVaule($data, $id);
+    }
+
+    /**
+     * 删除索引下面的指定文档
+     */
+    public function esdeleteTypeDocument($id)
+    {
+        return $this->search->delete($id);
+    }
+
+
+    /**
+     * 开启事务
+     * @param bool $foreign_key_checks
+     * @return mixed
+     */
+    public function beginTransaction($foreign_key_checks = false)
+    {
+        ++$this->transactions;
+        if ($this->transactions == 1){
+            return parent::beginTransaction($foreign_key_checks = false);
+        }
+    }
+
+    /**
+     * 提交事务
+     * @return mixed
+     */
+    public function commit()
+    {
+        if($this->transactions == 1){
+            return parent::commit();
+        }
+        --$this->transactions;
+    }
+
+    /**
+     * 回滚事务
+     * @return mixed
+     */
+    public function rollBack()
+    {
+        if($this->transactions == 1){
+            $this->transactions = 0;
+            return parent::rollBack();
+        }else{
+            --$this->transactions;
+        }
+    }
+}

+ 60 - 0
Jobs/Dao/DCoupon.Class.php

@@ -0,0 +1,60 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/12/16
+ * Time: 15:55
+ */
+
+namespace Jobs\Dao;
+
+
+class DCoupon extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'coupon';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '优惠券id',
+            "startTime", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '固定时间-开始时间',
+            "endTime", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '固定时间-结束时间',
+            "name", //varchar(255) NOT NULL DEFAULT '' COMMENT '优惠券名称',
+            "couponType", //tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '优惠券类型(10满减券)',
+            "reducePrice", //decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '满减券-减免金额(面值)',
+            "minPrice", //decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '最低消费金额 0.00不限金额',
+            "remark", //varchar(255) NOT NULL DEFAULT '' COMMENT '使用说明',
+            "grantType", //tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '发放方式(10主动领取 20定向发放 30注册领取 40在线支付赠送)',
+            "totalNum", //int(11) NOT NULL DEFAULT '0' COMMENT '发放总数量(-1为不限制)',
+            "allowNum", //int(11) NOT NULL DEFAULT '0' COMMENT '每人限制领取数量(-1为不限制)',
+            "customerSourceId", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '领取范围',
+            "mustCondition", //decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '(40在线支付赠送)-满X金额发放 0.00所有在线支付不限金额可领取这个优惠券',
+            "grantStartTime", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '发放开始时间',
+            "grantEndTime", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '发放结束时间',
+            "useShop", //varchar(255) NOT NULL DEFAULT '' COMMENT '使用店铺 为空时所有店铺都能使用',
+            "applyRange", //tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '适用范围(10全部商品 20指定分类 30指定品牌)',
+            "categoryCollect", //varchar(255) NOT NULL DEFAULT '' COMMENT '(20指定分类)-分类集合',
+            "brandCollect", //varchar(255) NOT NULL DEFAULT '' COMMENT '(30指定品牌)-品牌集合',
+            "goodsCollect",
+            "receiveNum", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '已领取数量',
+            "sort", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '排序方式(数字越大越靠前)',
+            "deleteStatus", //tinyint(3) unsigned NOT NULL DEFAULT '5' COMMENT '软删除(5未删除 4已删除)',
+            "auditStatus", //tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '审核状态(1待审 2审核通过 3未通过 4审核中)',
+            "createTime", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "grantStatus",//tinyint(3) unsigned NOT NULL DEFAULT '5' COMMENT 'grantType==20发放状态(4未发放 5已发放)',
+            "customerIds",//varchar(255) NOT NULL DEFAULT '' COMMENT '领取客户 为空时所有客户都能领取',
+            "isMutex",//tinyint(3) unsigned NOT NULL DEFAULT '5' COMMENT '是否互斥(5是 4否)',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 49 - 0
Jobs/Dao/DGoodsBasic.Class.php

@@ -0,0 +1,49 @@
+<?php
+/**
+ * 商品基础数据Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/10/30
+ * Time: 14:27
+ */
+
+namespace Jobs\Dao;
+
+class DGoodsBasic extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'goods_basic';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT,
+            "images", //json DEFAULT NULL COMMENT '商品相册',
+            "title", //varchar(255) NOT NULL DEFAULT '' COMMENT '商品名称',
+            "code", //varchar(255) NOT NULL DEFAULT '' COMMENT '商品编码',
+            "barCode", //varchar(255) NOT NULL DEFAULT '' COMMENT '商品条码',
+            "categoryId", //int(10) NOT NULL default '0' COMMENT '商品分类id',
+            "categoryPath", //varchar(50) NOT NULL default '' COMMENT '商品分类路径',
+            "expireTime", //int(10) NOT NULL default '0' COMMENT '过期时间',
+            "brandId", //int(10) NOT NULL default '0' COMMENT '品牌id',
+            'describe', // 商品描述
+            "tag", //varchar(255) NOT NULL DEFAULT '' COMMENT '关键词',
+            "link", //varchar(255) NOT NULL DEFAULT '' COMMENT 'link',
+            "description", //text NOT NULL COMMENT '商品详情',
+            "noSalesShop", //json DEFAULT NULL COMMENT '禁止销售店铺',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "enableStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '商品状态  默认5 上线 6下线',
+            "deleteStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除 4 删除 5正常',
+            "createTime", //int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 35 - 0
Jobs/Dao/DLog.Class.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/11/28
+ * Time: 10:20
+ */
+namespace Jobs\Dao;
+
+use Jobs\Dao\BaseDao;
+
+class DLog extends BaseDao
+{
+    public function __construct($serviceDB = 'log')
+    {
+        $this->_table = 'log_2019_1';
+        $this->_primary = 'id';
+        $this->_fields = [
+          'id',//int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
+          'enterpriseId',//int(11) NOT NULL COMMENT '企业id',
+          'userCenterId',//int(11) DEFAULT NULL COMMENT 'userCenterId',
+          'createTime',//int(11) DEFAULT NULL COMMENT '创建时间',
+          'no',//varchar(225) DEFAULT NULL COMMENT '编码或id',
+          'actionType',//varchar(225) DEFAULT NULL COMMENT '操作类型',
+          'operationData',//json DEFAULT NULL COMMENT '操作数据',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+        ];
+        $this->_update_autofill = [
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 35 - 0
Jobs/Dao/DLoginLog.Class.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/11/28
+ * Time: 10:20
+ */
+namespace Jobs\Dao;
+
+use Jobs\Dao\BaseDao;
+
+class DLoginLog extends BaseDao
+{
+    public function __construct($serviceDB = 'log')
+    {
+        $this->_table = 'login_log_2019_12';
+        $this->_primary = 'id';
+        $this->_fields = [
+              'userCenterId',//int(11) DEFAULT NULL COMMENT '会员id',
+              'enterpriseId',//int(11) DEFAULT NULL COMMENT '企业id',
+              'mobile',//varchar(255) DEFAULT NULL COMMENT '注册手机号码',
+              'createTime',//varchar(20) DEFAULT NULL COMMENT '操作时间',
+              'source',//varchar(50) DEFAULT NULL COMMENT '来源'
+              'actionType',//varchar(255) DEFAULT NULL COMMENT '操作类型',
+              'operationData',//json DEFAULT NULL COMMENT '提交数据',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+        ];
+        $this->_update_autofill = [
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 35 - 0
Jobs/Dao/DPriceLog.Class.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2020/1/3
+ * Time: 16:10
+ */
+
+namespace Jobs\Dao;
+
+class DPriceLog extends BaseDao
+{
+    public function __construct($serviceDB = 'log')
+    {
+        $this->_table = 'price_log';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id",//int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
+            "enterpriseId",//int(11) NOT NULL COMMENT '企业id',
+            "userCenterId",//int(11) DEFAULT NULL COMMENT 'userCenterId',
+            "createTime",//int(11) DEFAULT NULL COMMENT '创建时间',
+            "no",//varchar(225) DEFAULT NULL COMMENT '编码或id',
+            "actionType",//varchar(225) DEFAULT NULL COMMENT '操作类型',
+            "operationData",//json DEFAULT NULL COMMENT '操作数据',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+
+        ];
+        $this->_update_autofill = [
+
+        ];
+        parent::__construct($serviceDB);
+    }
+}

+ 57 - 0
Jobs/Dao/DShop.Class.php

@@ -0,0 +1,57 @@
+<?php
+/**
+ * 商铺管理模块
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/10/31
+ * Time: 15:02
+ */
+
+namespace Jobs\Dao;
+
+/**
+ * Class DShop
+ * @package JinDouYun\Dao\Shop
+ */
+class DShop extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'shop';
+        $this->_primary = 'id';
+        $this->_fields = [
+            'id',//int(11) NOT NULL AUTO_INCREMENT COMMENT '商铺id',
+            'enterpriseId',// int(11) NOT NULL COMMENT '企业实体id',
+            'costType',
+            'name',// varchar(255) DEFAULT NULL COMMENT '商铺名称',
+            'logo',//varchar(255) NOT NULL COMMENT '商铺logo',
+            'shopCode',//varchar(255) NOT NULL COMMENT '商铺仓库编码',
+            'shopType',//int(10) DEFAULT NULL COMMENT '商铺类型',
+            'openTime',// json DEFAULT NULL COMMENT '营业时间',
+            'contactName',// varchar(50) NOT NULL COMMENT '联系人',
+            'mobile',//char(11) NOT NULL COMMENT '联系电话',
+            'deleteStatus',//tinyint(4) DEFAULT '5' COMMENT '删除状态(5未删除 4已删除)',
+            'createTime',//int(10) DEFAULT NULL COMMENT '创建时间',
+            'updateTime',//int(10) DEFAULT NULL COMMENT '修改时间',
+            'enableStatus',//tinyint(4) DEFAULT '5' COMMENT '启用状态(4未启用 5已启用)',
+            'provinceCode',//varchar(20) DEFAULT NULL COMMENT '省编码',
+            'cityCode',//varchar(20) DEFAULT NULL COMMENT '市编码',
+            'districtCode',//varchar(20) DEFAULT NULL COMMENT '区编码',
+            'address',//varchar(100) DEFAULT NULL COMMENT '详细地址',
+            'latitude',// varchar(255) DEFAULT NULL COMMENT '纬度',
+            'longitude',// varchar(255) DEFAULT NULL COMMENT '经度',
+            'salesArea',// json DEFAULT NULL COMMENT '销售区域',
+            'shopPartnerId',// int(11) DEFAULT NULL COMMENT '合伙人id',
+            'warehouseId',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 58 - 0
Jobs/Dao/DUserCoupon.Class.php

@@ -0,0 +1,58 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/12/16
+ * Time: 15:41
+ */
+
+namespace Jobs\Dao;
+
+
+class DUserCoupon extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'user_coupon';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id",//int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
+            "couponId",//int(11) unsigned NOT NULL COMMENT '优惠券id',
+            "name",//varchar(255) NOT NULL DEFAULT '' COMMENT '优惠券名称',
+            "remark",//varchar(255) NOT NULL DEFAULT '' COMMENT '使用说明',
+            "couponType",//tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '优惠券类型(10满减券)',
+            "reducePrice",//decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '满减券-减免金额(面值)',
+            "minPrice",//decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '最低消费金额 0.00不限金额',
+            "startTime",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '有效期开始时间',
+            "endTime",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '有效期结束时间',
+            "applyRange",//tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '适用范围(10全部商品 20指定分类 30指定品牌)',
+            "categoryCollect",//varchar(255) NOT NULL DEFAULT '' COMMENT '(20指定分类)-分类集合',
+            "brandCollect",//varchar(255) NOT NULL DEFAULT '' COMMENT '(30指定品牌)-品牌集合',
+            "goodsCollect",
+            "isExpire",//tinyint(3) unsigned NOT NULL DEFAULT '4' COMMENT '是否过期(4未过期 5已过期)',
+            "isUse",//tinyint(3) unsigned NOT NULL DEFAULT '4' COMMENT '是否已使用(4未使用 5已使用)',
+            "useTime",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '使用时间',
+            "userId",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
+            "customerId",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '客户id',
+            "shopId",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '领取的店铺id',
+            "useShop",//varchar(255) NOT NULL DEFAULT '' COMMENT '使用范围 为空时所有店铺都能使用',
+            "source",//tinyint(3) unsigned NOT NULL DEFAULT '10' COMMENT '优惠券来源(10主动领取 20定向发放 30注册领取 40在线支付赠送)',
+            "createTime",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
+            "orderNo",//char(21) NOT NULL DEFAULT '' COMMENT '使用单号',
+            "orderId",//int(11) unsigned NOT NULL DEFAULT '0' COMMENT '订单id',
+            "extends",//json DEFAULT NULL COMMENT '拓展字段',
+            "customerIds",//varchar(255) NOT NULL DEFAULT '' COMMENT '领取客户 为空时所有客户都能领取',
+            "isMutex",//tinyint(3) unsigned NOT NULL DEFAULT '5' COMMENT '是否互斥(5是 4否)',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 42 - 0
Jobs/Dao/Finance/DPay.Class.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace Jobs\Dao\Finance;
+
+use Jobs\Dao\BaseDao;
+
+class DPay extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'qianniao_pay_receipt_1_201901';
+        $this->_primary = 'id';
+        $this->_fields = [
+            'id',//int(11) NOT NULL AUTO_INCREMENT COMMENT '应付单据id',
+            'customerId',//int(11) DEFAULT NULL COMMENT '客户Id',
+            'customerName',//varchar(50) DEFAULT NULL COMMENT '客户名称',
+            'no',//char(25) DEFAULT NULL COMMENT '应付单据编号',
+            'sourceNo',//char(25) DEFAULT NULL COMMENT '源订单号',
+            'purchaseId',
+            'createTime',//int(11) DEFAULT NULL COMMENT '创建时间',
+            'updateTime',//int(11) DEFAULT NULL COMMENT '修改时间',
+            'financeTypeId',//int(10) DEFAULT NULL COMMENT '财务类型id',
+            'financeType',//varchar(50) DEFAULT NULL COMMENT '财务类型名称',
+            'discountMoney',//float(10,2) DEFAULT NULL COMMENT '优惠金额',
+            'payMoney',//float(10,2) DEFAULT NULL COMMENT '实际应付金额',
+            'shopId',//int(11) DEFAULT NULL COMMENT '商铺Id',
+            'shopName',//varchar(50) DEFAULT NULL COMMENT '商铺名称',
+            'deleteStatus',//tinyint(1) DEFAULT NULL COMMENT '删除状态',
+            'auditStatus',//tinyint(1) NOT NULL COMMENT '审核状态(1未审核  2已审核)',
+            'receiptTypeId',//tinyint(2) DEFAULT NULL COMMENT '应付单据类型',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 42 - 0
Jobs/Dao/Finance/DPayReceiptIndex.Class.php

@@ -0,0 +1,42 @@
+<?php
+/**
+ * 应付单索引Dao类
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/10/30
+ * Time: 14:17
+ */
+
+namespace Jobs\Dao\Finance;
+
+use Jobs\Dao\BaseDao;
+
+class DPayReceiptIndex extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'qianniao_pay_receipt_index_1';
+        $this->_primary = 'id';
+        $this->_fields = [
+            'id',//int(11) NOT NULL AUTO_INCREMENT COMMENT '应收索引表id',
+            'payReceiptId',//int(11) NOT NULL COMMENT '应付单据id',
+            'createTime',//int(11) NOT NULL COMMENT '创建时间',
+            'updateTime',//int(11) NOT NULL COMMENT '修改时间',
+            'shopId',//int(11) DEFAULT NULL COMMENT '商铺id',
+            'financeTypeId',//tinyint(2) DEFAULT NULL COMMENT '财务类型id',
+            'financeType',//varchar(50) DEFAULT NULL COMMENT '财务类型名称',
+            'auditStatus',//tinyint(1) DEFAULT '1' COMMENT '应付单据状态(1未审核 2已审核)',
+            'customerId',//int(11) DEFAULT NULL COMMENT '客户id',
+            'sourceNo',//char(25) DEFAULT NULL COMMENT '源订单号',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 42 - 0
Jobs/Dao/Finance/DReceive.Class.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace Jobs\Dao\Finance;
+
+use Jobs\Dao\BaseDao;
+
+class DReceive extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'receive_receipt_1_201901';
+        $this->_primary = 'id';
+        $this->_fields = [
+            'id',//int(11) NOT NULL AUTO_INCREMENT COMMENT '应收单据id',
+            'customerId',//int(11) DEFAULT NULL COMMENT '客户Id',
+            'customerName',//varchar(50) DEFAULT NULL COMMENT '客户名称',
+            'no',//varchar(50) DEFAULT NULL COMMENT '单据编号',
+            'orderId',//int(11) DEFAULT NULL COMMENT '订单id',
+            'sourceNo',//varchar(50) DEFAULT NULL COMMENT '订单号',
+            'createTime',//int(11) DEFAULT NULL COMMENT '创建时间',
+            'updateTime',//int(11) DEFAULT NULL COMMENT '修改时间',
+            'financeTypeId',//int(10) DEFAULT NULL COMMENT '财务类型id',
+            'financeType',//varchar(255) DEFAULT NULL COMMENT '财务类型名称',
+            'discountMoney',//float(10,2) DEFAULT NULL COMMENT '优惠金额',
+            'receiveMoney',//float(10,2) DEFAULT NULL COMMENT '实际应收金额',
+            'shopId',//int(11) DEFAULT NULL COMMENT '商铺Id',
+            'shopName',//varchar(50) DEFAULT NULL COMMENT '商铺名称',
+            'deleteStatus',//tinyint(1) DEFAULT NULL COMMENT '删除状态',
+            'auditStatus',//tinyint(2) DEFAULT NULL COMMENT '单据状态',
+            'receiptType',//tinyint(2) DEFAULT NULL COMMENT '单据类型',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 41 - 0
Jobs/Dao/Finance/DReceiveReceiptIndex.Class.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: wxj
+ * Date: 2019/10/30
+ * Time: 14:17
+ */
+
+namespace Jobs\Dao\Finance;
+
+use Jobs\Dao\BaseDao;
+
+class DReceiveReceiptIndex extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'receive_receipt_index_1';
+        $this->_primary = 'id';
+        $this->_fields = [
+            'id',//int(11) NOT NULL AUTO_INCREMENT COMMENT '应收索引表id',
+            'receiveReceiptId',//int(11) NOT NULL COMMENT '应收单据id',
+            'createTime',//int(11) NOT NULL COMMENT '创建时间',
+            'updateTime',//int(11) NOT NULL COMMENT '修改时间',
+            'shopId',//int(11) DEFAULT NULL COMMENT '商铺id',
+            'financeTypeId',//tinyint(2) DEFAULT NULL COMMENT '财务类型id',
+            'financeType',//varchar(50) DEFAULT NULL COMMENT '财务类型名称',
+            'auditStatus',//tinyint(1) DEFAULT NULL COMMENT '单据状态',
+            'customerId',//int(11) DEFAULT NULL COMMENT '客户id',
+            'sourceNo',//varchar(50) DEFAULT NULL COMMENT '订单编号',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 40 - 0
Jobs/Dao/Message/DMessage.Class.php

@@ -0,0 +1,40 @@
+<?php
+/**
+ * 消息Dao
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2019/04/03
+ * Time: 12:20
+ */
+
+namespace Jobs\Dao\Message;
+
+use Jobs\Dao\BaseDao;
+
+class DMessage extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'message';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
+            "sendId", //int(10) NOT NULL DEFAULT '0' COMMENT '发送人id 0为系统发送',
+            "receiveId", //int(10) NOT NULL COMMENT '接收人id',
+            "title", //varchar(255) NOT NULL COMMENT '标题',
+            "content", //text NOT NULL COMMENT '内容',
+            "receiveStatus", //tinyint(3) NOT NULL COMMENT '已读状态 4:未读 5:已读',
+            "type", //tinyint(3) NOT NULL COMMENT '类型 1:库存不足消息',
+            "deleteStatus",
+            "sendTime", //int(10) NOT NULL COMMENT '发送时间',
+            "receiveTime", //int(10) DEFAULT NULL COMMENT '接收时间',
+            "createTime", //int(10) NOT NULL COMMENT '创建时间',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 59 - 0
Jobs/Dao/Order/DOrder.Class.php

@@ -0,0 +1,59 @@
+<?php
+/**
+ * 订单Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/10/31
+ * Time: 15:49
+ */
+
+namespace Jobs\Dao\Order;
+
+use Jobs\Dao\BaseDao;
+
+class DOrder extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'order';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT,
+            "no", //char(20) NOT NULL COMMENT '订单编号',
+            "shopId", //int(10) NOT NULL DEFAULT '0' COMMENT '店铺id',
+            "shopName",
+            "outerTradeNo", //varchar(255) NOT NULL DEFAULT '' COMMENT '外部流水号(支付宝/微信返回的流水号)',
+            "totalMoney", //decimal(12,2) DEFAULT '0.00' COMMENT '总金额',
+            "payAmount", //decimal(12,2) DEFAULT '0.00' COMMENT '实付金额',
+            "buyTotal", //int(10) NOT NULL DEFAULT '0' COMMENT '购买总数',
+            "customerName", //varchar(50) NOT NULL COMMENT '客户姓名',
+            "customerId", //int(10) NOT NULL COMMENT '客户id',
+            "payStatus", //tinyint(3) NOT NULL DEFAULT '1' COMMENT '支付状态  默认1 未支付 2已支付',
+            "orderStatus", //tinyint(3) NOT NULL DEFAULT '2' COMMENT '订单状态 默认 2待支付 3代发货 4待收货 5已完成 6已关闭',
+            "payType", //tinyint(3) DEFAULT NULL COMMENT '支付方式 1微信 2支付宝 3货到付款 4上门自提',
+            "deliveryType", //tinyint(3) DEFAULT NULL COMMENT '配送方式 1商品配送 2上门自提',
+            "source", //tinyint(3) DEFAULT NULL COMMENT '订单来源 默认1 ios 2android 3小程序 4后台创建',
+            "remark", //varchar(255) NOT NULL DEFAULT '' COMMENT '订单备注',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "deleteStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除  默认5 正常 4删除',
+            "auditStatus", //tinyint(3) NOT NULL DEFAULT '1' COMMENT '审核状态 默认1 待审 2审核通过 3 审核未通过 4 审核中',
+            "payTime", //int(10) NOT NULL DEFAULT '0' COMMENT '付款时间',
+            "createTime", //int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+            "preferentialActivityId", //int(10) DEFAULT '0' COMMENT '店铺优惠活动id',
+            "salesManId", //int(10) DEFAULT '0' COMMENT '业务员id',
+            "salesManName", //varchar(255) DEFAULT NULL COMMENT '业务员名称',
+            "customerType", //tinyint(3) DEFAULT NULL COMMENT '客户类型',
+            "userCenterId", //int(10) DEFAULT NULL COMMENT 'userCenterId',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 41 - 0
Jobs/Dao/Order/DOrderCoupon.Class.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * 订单优惠表Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/10/31
+ * Time: 15:58
+ */
+
+namespace JJobs\Dao\Order;
+
+use Jobs\Dao\BaseDao;
+
+class DOrderCoupon extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'order_coupon';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id",//int(10) NOT NULL AUTO_INCREMENT,
+            "orderId",//int(10) NOT NULL DEFAULT '0' COMMENT '订单Id',
+            "goodsId",//int(10) NOT NULL DEFAULT '0' COMMENT '商品id',
+            "shopId",// int(10) NOT NULL DEFAULT '0' COMMENT '店铺id',
+            "couponAmount",//decimal(12,2) default '0.00' COMMENT '商品优惠金额',
+            "couponInfo",//json DEFAULT NULL COMMENT '优惠信息',
+            "extends",//json DEFAULT NULL COMMENT '拓展字段',
+            "createTime",//int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime",//int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 57 - 0
Jobs/Dao/Order/DOrderGoods.Class.php

@@ -0,0 +1,57 @@
+<?php
+/**
+ * 订单商品详情Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/10/31
+ * Time: 16:04
+ */
+
+namespace Jobs\Dao\Order;
+
+use Jobs\Dao\BaseDao;
+
+class DOrderGoods extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'order_goods';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT,
+            "no", //char(20) NOT NULL COMMENT '订单编号',
+            "orderId", //int(10) NOT NULL DEFAULT '0' COMMENT '订单Id',
+            "goodsCode", //varchar(255) NOT NULL DEFAULT '' COMMENT '商品编号',
+            "goodsId", //int(10) NOT NULL DEFAULT '0' COMMENT '商品Id',
+            "goodsName", //varchar(50) NOT NULL DEFAULT '' COMMENT '商品名称',
+            "shopId", //int(10) NOT NULL DEFAULT '0' COMMENT '商铺Id',
+            "shopName", //varchar(50) NOT NULL DEFAULT '' COMMENT '商铺名称',
+            "originPrice", //decimal(12,2) DEFAULT '0.00' COMMENT '原始单价',
+            "price", //decimal(12,2) DEFAULT '0.00' COMMENT '商品单价',
+            "buyNum", //int(10) NOT NULL DEFAULT '0' COMMENT '购买数量',
+            "preferential", //decimal(12,2) DEFAULT '0.00' COMMENT '每/优惠',
+            "totalMoney", //decimal(12,2) DEFAULT '0.00' COMMENT '小计金额',
+            "deliverNum", //int(10) NOT NULL DEFAULT '0' COMMENT '发货数量',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "deleteStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除  默认5 正常 4删除',
+            "returnStatus", //tinyint(3) DEFAULT '0' COMMENT '退货状态 0:未退货 1:已退货',
+            "createTime", //int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+            "preferentialActivityId", //int(10) DEFAULT '0' COMMENT '店铺优惠活动id',
+            "skuId", //int(10) DEFAULT NULL COMMENT 'skuid',
+            "goodsBasicId", //int(10) DEFAULT NULL COMMENT 'goodsBasicId',
+            "unitName", //varchar(50) DEFAULT NULL COMMENT '单位名称',
+            "conversion", //decimal(10,2) DEFAULT NULL COMMENT '换算比率',
+            "outCostPrice", //decimal(10,2) DEFAULT NULL COMMENT '成本',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 45 - 0
Jobs/Dao/Order/DOrderIndex.Class.php

@@ -0,0 +1,45 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/11/23
+ * Time: 9:22
+ */
+
+namespace Jobs\Dao\Order;
+
+use Jobs\Dao\BaseDao;
+
+class DOrderIndex extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'order_index';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
+            "orderId", //int(11) NOT NULL COMMENT '订单id',
+            "userCenterId", //int(11) NOT NULL COMMENT 'userCenterId',
+            "shopId", //int(11) NOT NULL COMMENT 'shopId',
+            "createTime", //int(10) DEFAULT NULL COMMENT '创建时间',
+            "updateTime", //int(10) DEFAULT NULL COMMENT '更新时间',
+            "deleteStatus", //tinyint(3) DEFAULT '5' COMMENT '删除状态',
+            "auditStatus", //tinyint(3) DEFAULT NULL COMMENT '审核状态',
+            "salesManId", //int(10) DEFAULT NULL COMMENT '业务员id',
+            "payStatus", //tinyint(3) DEFAULT '4' COMMENT '支付状态  默认4 未支付 5已支付',
+            "orderStatus", //tinyint(3) DEFAULT NULL COMMENT '订单状态 默认 2待支付 3代发货 4待收货 5已完成 6已关闭',
+            "outStatus",
+            "returnStatus",
+            "deliveryType", //tinyint(3) DEFAULT NULL COMMENT '配送方式 1商品配送 2上门自提',
+            "payType",//支付方式
+            "customerId",//客户id
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+        ];
+        $this->_update_autofill = [
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 48 - 0
Jobs/Dao/Order/DOrderReceive.Class.php

@@ -0,0 +1,48 @@
+<?php
+/**
+ * 订单收货信息Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/10/31
+ * Time: 16:01
+ */
+
+namespace Jobs\Dao\Order;
+
+use Jobs\Dao\BaseDao;
+
+class DOrderReceive extends BaseDao
+{
+    public function __construct($serviceDB = 'default')
+    {
+        $this->_table = 'order_receive';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT,
+            "no", //bigint(20) NOT NULL COMMENT '订单编号',
+            "orderId", //int(10) NOT NULL DEFAULT '0' COMMENT '订单Id',
+            "customerId", //int(10) NOT NULL DEFAULT '0' COMMENT '客户Id',
+            "customerCode", //varchar(255) NOT NULL DEFAULT '' COMMENT '客户编码',
+            "realName", //varchar(255) NOT NULL DEFAULT '' COMMENT '收货人姓名',
+            "mobile", //char(11) NOT NULL DEFAULT '' COMMENT '收货人电话',
+            "address", //varchar(255) NOT NULL DEFAULT '' COMMENT '收货详细地址',
+            "provinceCode", //int(10) NOT NULL DEFAULT '0' COMMENT '省份编码',
+            "cityCode", //int(10) NOT NULL DEFAULT '0' COMMENT '城市编码',
+            "districtCode", //int(10) NOT NULL DEFAULT '0' COMMENT '区编码',
+            "remark", //varchar(255) NOT NULL DEFAULT '' COMMENT '收货备注',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "deleteStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除  默认5 正常 4删除',
+            "createTime", //int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 56 - 0
Jobs/Dao/Purchase/DPurchase.Class.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * 采购Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/11/11
+ * Time: 17:46
+ */
+
+namespace Jobs\Dao\Purchase;
+
+use Jobs\Dao\BaseDao;
+
+class DPurchase extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'purchase';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT,
+            "no", //char(20) NOT NULL COMMENT '采购单号',
+            "shopId", //int(10) NOT NULL DEFAULT '0' COMMENT '采购门店id',
+            "shopName", //varchar(255) NOT NULL DEFAULT '' COMMENT '门店名称',
+            "supplierId", //int(10) NOT NULL DEFAULT '0' COMMENT '供应商Id',
+            "supplierName", //varchar(255) NOT NULL DEFAULT '' COMMENT '供应商名称',
+            "buyerId", //int(10) NOT NULL DEFAULT '0' COMMENT '采购人员Id',
+            "buyerName", //varchar(255) NOT NULL DEFAULT '' COMMENT '采购人员名称',
+            "remark", //varchar(255) DEFAULT '' COMMENT '备注',
+            "operatorId", //int(10) NOT NULL DEFAULT '0' COMMENT '制单人员Id',
+            "operatorName", //varchar(255) NOT NULL DEFAULT '' COMMENT '制单人名',
+            "purchaseAmount", //decimal(15,4) DEFAULT '0.0000' COMMENT '采购金额',
+            "couponAmount", //decimal(15,4) DEFAULT '0.0000' COMMENT '优惠金额',
+            "otherAmount", //decimal(15,4) DEFAULT '0.0000' COMMENT '其他金额',
+            "goodsNum", //decimal(20,8) NOT NULL COMMENT '采购商品数量',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "orderStatus", //tinyint(3) DEFAULT '4' COMMENT '单据入库状态 4:未入库 5:已入库',
+            "auditStatus", //tinyint(3) NOT NULL DEFAULT '1' COMMENT '审核状态  默认1 待审 2审核通过 3审核未通过 4审核中',
+            "deleteStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除 默认5 正常 4删除',
+            "auditId", //int(10) NOT NULL DEFAULT '0' COMMENT '审核人员Id',
+            "auditName", //varchar(255) NOT NULL DEFAULT '' COMMENT '审核人员名册',
+            "auditTime", //int(10) NOT NULL DEFAULT '0' COMMENT '审核时间',
+            "createTime", //int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 57 - 0
Jobs/Dao/Purchase/DPurchaseOut.Class.php

@@ -0,0 +1,57 @@
+<?php
+/**
+ * 采购退货单Dao
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/11/11
+ * Time: 17:46
+ */
+
+namespace Jobs\Dao\Purchase;
+
+use Jobs\Dao\BaseDao;
+
+class DPurchaseOut extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'purchase_out';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT,
+            "purchaseId", //int(10) NOT NULL DEFAULT '0' COMMENT '采购单id',
+            "purchaseNo", //bigint(20) NOT NULL COMMENT '采购订单号',
+            "no", //bigint(20) NOT NULL COMMENT '采购退货单号',
+            "shopId", //int(10) NOT NULL DEFAULT '0' COMMENT '门店id',
+            "shopName", //varchar(255) NOT NULL DEFAULT '' COMMENT '门店名称',
+            "supplierId", //int(10) NOT NULL DEFAULT '0' COMMENT '供应商Id',
+            "supplierName", //varchar(255) NOT NULL DEFAULT '' COMMENT '供应商名称',
+            "buyerId", //int(10) NOT NULL DEFAULT '0' COMMENT '采购人员Id',
+            "buyerName", //varchar(255) NOT NULL DEFAULT '' COMMENT '采购人员名称',
+            "remark", //varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
+            "operatorId", //int(10) NOT NULL DEFAULT '0' COMMENT '制单人员Id',
+            "operatorName", //varchar(255) NOT NULL DEFAULT '' COMMENT '制单人名',
+            "purchaseAmount", //decimal(12,4) default '0.0000' COMMENT '采购退货金额',
+            "couponAmount", //decimal(12,4) default '0.0000' COMMENT '优惠金额',
+            "otherAmount", //decimal(12,4) default '0.0000' COMMENT '其他金额',
+            "extends", //json DEFAULT NULL COMMENT '拓展字段',
+            "orderStatus",
+            "auditStatus", //tinyint(3) NOT NULL DEFAULT '1' COMMENT '审核状态  默认1 待审 2审核通过 3审核未通过 4审核中',
+            "deleteStatus", //tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除 默认5 正常 4删除',
+            "auditId", //int(10) NOT NULL DEFAULT '0' COMMENT '审核人员Id',
+            "auditName", //varchar(255) NOT NULL DEFAULT '' COMMENT '审核人员名册',
+            "auditTime", //int(10) NOT NULL DEFAULT '0' COMMENT '审核时间',
+            "createTime", //int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 50 - 0
Jobs/Dao/Stock/DInventoryBatch.Class.php

@@ -0,0 +1,50 @@
+<?php
+/**
+ * 库存批次管理Dao
+ * Created by PhpStorm.
+ * User: phperstar
+ * Date: 2019/12/10
+ * Time: 10:00
+ */
+
+namespace Jobs\Dao\Stock;
+
+
+use Jobs\Dao\BaseDao;
+
+class DInventoryBatch extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'inventory_batch';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT COMMENT '自增id',
+            "originId",
+            "originNo",
+            "warehouseId", //int(10) NOT NULL COMMENT '仓库id',
+            "materielId", //int(10) NOT NULL COMMENT '物料ID',
+            "materielIdCode", //varchar(255) DEFAULT NULL COMMENT '物料编码',
+            "sourceNo", // 来源单号
+            "skuId", //单位id
+            'batchNo', // 批次编号
+            'num', // 批次可用数量
+            "averageCost", //成本均价
+            'batchCost',//批次成本
+            'productionData',//生产日期
+            'batchStatus',
+            "updateTime", //int(10) DEFAULT NULL COMMENT '修改时间',
+            "createTime", //int(10) DEFAULT NULL COMMENT '创建时间',
+            "extend", //json DEFAULT NULL COMMENT '扩展字段',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time(),
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 53 - 0
Jobs/Dao/Stock/DInventoryDetails.Class.php

@@ -0,0 +1,53 @@
+<?php
+/**
+ * 库存流水管理Dao
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2019/11/12
+ * Time: 10:00
+ */
+
+namespace Jobs\Dao\Stock;
+
+use Jobs\Dao\BaseDao;
+
+class DInventoryDetails extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'inventory_details';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT COMMENT '自增id',
+            "warehouseId", //int(10) NOT NULL COMMENT '仓库id',
+            "originId", //int(10) NOT NULL COMMENT '业务来源id',
+            "originNo", //char(22) NOT NULL COMMENT '业务来源no',
+            "materielId", //int(10) NOT NULL COMMENT '物料id',
+            "materielCode", //varchar(255) NOT NULL COMMENT '物料编码',
+            "materielName", //varchar(255) NOT NULL COMMENT '物料名称',
+            "sourceNo", //char(20) NOT NULL COMMENT '来源单号',
+            "source", //tinyint(3) NOT NULL COMMENT '单据来源标识',
+            "operatorId", //int(10) NOT NULL COMMENT '操作人id',
+            "operatorName", //varchar(50) NOT NULL COMMENT '操作人姓名',
+            "skuId", //int(10) NOT NULL COMMENT '单位id',
+            "inventoryNum", //decimal(20,8) NOT NULL COMMENT '库存数',
+            "inventoryChangeNum", //decimal(20,8) NOT NULL COMMENT '变动后库存数量',
+            "batch", //json NOT NULL COMMENT '批次信息',
+            "costType", //tinyint(3) NOT NULL DEFAULT '1' COMMENT '计算成本方式 1:移动加权 2:个别计价',
+            "averageCost", //decimal(15,4) NOT NULL COMMENT '均价成本',
+            "actionType", //tinyint(3) NOT NULL COMMENT '出入库操作标识 5:入库 4:出库',
+            "createTime", //int(10) NOT NULL COMMENT '创建时间',
+            "updateTime", //int(10) NOT NULL COMMENT '更新时间',
+            "extend", //json DEFAULT NULL COMMENT '扩展字段',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 58 - 0
Jobs/Dao/Stock/DInventoryIn.Class.php

@@ -0,0 +1,58 @@
+<?php
+/**
+ * 入库管理Dao
+ * Created by PhpStorm.
+ * Date: 2019/11/11
+ * Time: 18:30
+ */
+
+namespace Jobs\Dao\Stock;
+
+use Jobs\Dao\BaseDao;
+
+class DInventoryIn extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'inventory_in';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT COMMENT '主键自增',
+            "no", //char(25) NOT NULL COMMENT '入库单号',
+            "sourceId", //int(10) NOT NULL COMMENT '来源id',
+            "sourceNo", //char(25) NOT NULL COMMENT '来源单号',
+            "originNo", //char(25) NOT NULL COMMENT '源头单号',
+            "merchantId", // int(10) NOT NULL DEFAULT '0' COMMENT '商户id',
+            "originId", //int(10) DEFAULT NULL COMMENT '源头id',
+            "materielNum", //int(10) DEFAULT NULL COMMENT '入库商品数量',
+            "amount", //decimal(15,4) DEFAULT NULL COMMENT '入库总金额',
+            "costAllocationType", //tinyint(1) DEFAULT NULL COMMENT '成本分摊类型',
+            "costAllocation", //decimal(15,4) DEFAULT '0.0000' COMMENT '成本分摊费用',
+            "shopId", //int(10) DEFAULT '0' COMMENT '商铺id',
+            "warehouseId", //int(10) DEFAULT NULL COMMENT '仓库id',
+            "warehouseName", //varchar(255) DEFAULT NULL COMMENT '仓库名称',
+            "operatorId", //int(10) DEFAULT NULL COMMENT '操作人id',
+            "operatorName", //varchar(255) DEFAULT NULL COMMENT '操作人姓名',
+            "auditId", //int(10) DEFAULT NULL COMMENT '审核人id',
+            "auditName", //varchar(20) DEFAULT NULL COMMENT '审核人姓名',
+            "remark", //varchar(255) DEFAULT NULL COMMENT '备注',
+            "deleteStatus", //tinyint(3) DEFAULT NULL COMMENT '删除状态 5:正常 4:删除',
+            "source", //tinyint(3) DEFAULT NULL COMMENT '订单来源(入库类型)',
+            "type", //tinyint(3) DEFAULT NULL COMMENT '单据类型',
+            "auditStatus", //tinyint(3) DEFAULT NULL COMMENT '审核状态 1:未审核 2:已审核',
+            "auditTime", //int(10) DEFAULT NULL COMMENT '审核日期',
+            "createTime", //int(10) DEFAULT NULL COMMENT '创建时间/制单时间',
+            "updateTime", //int(10) DEFAULT NULL COMMENT '修改时间',
+            "extend", //json DEFAULT NULL COMMENT '拓展字段',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 54 - 0
Jobs/Dao/Stock/DInventoryInDetails.Class.php

@@ -0,0 +1,54 @@
+<?php
+/**
+ * 入库详情管理Dao
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2019/11/11
+ * Time: 14:00
+ */
+
+namespace Jobs\Dao\Stock;
+
+use Jobs\Dao\BaseDao;
+
+class DInventoryInDetails extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'inventory_in_details';
+        $this->_primary = 'id';
+        $this->_fields = [
+            'id',//int(10) NOT NULL AUTO_INCREMENT COMMENT '自增id',
+            'linkId',//int(10) DEFAULT NULL COMMENT '入库id',
+            'linkNo',//char(25) DEFAULT NULL COMMENT '入库单号',
+            'InWarehouse',//json DEFAULT NULL COMMENT '入库仓库',
+            'materielId',//int(10) DEFAULT NULL COMMENT '物料id',
+            'materielName',//varchar(255) DEFAULT NULL COMMENT '物料名称',
+            'materielCode',//varchar(20) DEFAULT NULL COMMENT '物料编号',
+            'skuId',//int(10) DEFAULT NULL COMMENT '单位id',
+            'unitName',//varchar(255) NOT NULL COMMENT '单位名称',
+            'skuName',//varchar(255) NOT NULL COMMENT '属性名称',
+            'skuStorage',//varchar(255) DEFAULT NULL COMMENT '货架编码',
+            'num',//decimal(20,8) unsigned zerofill DEFAULT '000000000000.00000000' COMMENT '数量',
+            'inNum',//decimal(20,8) DEFAULT '0.00000000' COMMENT '入库数量',
+            'otherNum',//decimal(20,8) DEFAULT '0.00000000' COMMENT '其他单位数量',
+            'unitPrice',//decimal(15,4) DEFAULT NULL COMMENT '单价',
+            'totalPrice',//decimal(15,4) DEFAULT NULL COMMENT '总价',
+            'inCost',//decimal(15,4) DEFAULT '0.0000' COMMENT '入库成本',
+            'inCostTotal',//decimal(15,4) DEFAULT '0.0000' COMMENT '入库总成本',
+            'productionData',//int(10) DEFAULT '0' COMMENT '生产日期',
+            'createTime',//int(10) DEFAULT NULL COMMENT '创建时间',
+            'updateTime',//int(10) DEFAULT NULL COMMENT '修改时间',
+            'extend',//json DEFAULT NULL COMMENT '扩展字段',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 60 - 0
Jobs/Dao/Stock/DInventoryOut.Class.php

@@ -0,0 +1,60 @@
+<?php
+/**
+ * 出库管理Dao
+ * Created by PhpStorm.
+ * Date: 2019/11/11
+ * Time: 14:00
+ */
+namespace Jobs\Dao\Stock;
+
+use Jobs\Dao\BaseDao;
+
+class DInventoryOut extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'inventory_out';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT COMMENT '主键自增',
+            "no", //char(25) NOT NULL COMMENT '出库单号',
+            "sourceId", //int(10) NOT NULL COMMENT '来源Id',
+            "sourceNo", //char(25) NOT NULL COMMENT '来源单号',
+            "originNo", //char(25) NOT NULL COMMENT '源头单号',
+            "originId", //int(10) NOT NULL COMMENT '源头id',
+            "materielNum", //int(10) DEFAULT NULL COMMENT '出库商品数量',
+            "amount", //decimal(15,4) DEFAULT NULL COMMENT '出库总金额',
+            "shopId", //int(10) NOT NULL COMMENT '商铺ID',
+            "shopName", //varchar(50) NOT NULL COMMENT '商铺名称',
+            "operatorId", //int(10) DEFAULT NULL COMMENT '操作人id',
+            "operatorName", //varchar(255) DEFAULT NULL COMMENT '操作人姓名',
+            "auditId", //int(10) DEFAULT NULL COMMENT '审核人id',
+            "auditName", //varchar(30) DEFAULT NULL COMMENT '审核人姓名',
+            "customerId", //int(10) DEFAULT NULL COMMENT '客户id',
+            "customerName", //varchar(20) DEFAULT NULL COMMENT '客户姓名',
+            "customerCode", //varchar(255) DEFAULT NULL COMMENT '客户编码',
+            "customerMobile", //char(11) DEFAULT NULL COMMENT '客户电话',
+            "remark", //varchar(255) DEFAULT NULL COMMENT '备注',
+            "source", //tinyint(3) DEFAULT NULL COMMENT '订单来源(出库类型)',
+            "deliveryType", //tinyint(3) DEFAULT NULL COMMENT '配送方式',
+            "type", //tinyint(3) DEFAULT NULL COMMENT '单据类型',
+            "deleteStatus", //tinyint(3) DEFAULT NULL COMMENT '删除状态 5:正常 4:删除',
+            "outStatus", //tinyint(1) DEFAULT NULL COMMENT '出库状态 1:待出库 2:全部出库 3:部分出库',
+            "auditStatus", //tinyint(3) DEFAULT NULL COMMENT '审核状态1 :未审核 2:已审核',
+            "auditTime", //int(10) DEFAULT NULL COMMENT '审核日期',
+            "createTime", //int(10) DEFAULT NULL COMMENT '创建时间/制单时间',
+            "updateTime", //int(10) DEFAULT NULL COMMENT '修改时间',
+            "extend", //json DEFAULT NULL COMMENT '拓展字段',
+            "serialNum", //varchar(20) DEFAULT '0' COMMENT '序号',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 49 - 0
Jobs/Dao/Stock/DWarehouse.Class.php

@@ -0,0 +1,49 @@
+<?php
+/**
+ * 仓库管理Dao
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2019/11/08
+ * Time: 14:30
+ */
+
+namespace Jobs\Dao\Stock;
+
+use Jobs\Dao\BaseDao;
+
+class DWarehouse extends BaseDao
+{
+    public function __construct($serviceDB = 'stock')
+    {
+        $this->_table = 'warehouse';
+        $this->_primary = 'id';
+        $this->_fields = [
+            "id", //int(10) NOT NULL AUTO_INCREMENT COMMENT '自增id',
+            "shopId", //int(10) DEFAULT NULL COMMENT '商铺Id',
+            "warehouseCode", //varchar(50) DEFAULT NULL COMMENT '仓库编码',
+            "warehouseName", //varchar(255) DEFAULT NULL COMMENT '仓库名称',
+            "contactName", //varchar(255) DEFAULT NULL COMMENT '联系人姓名',
+            "contactMobile", //char(11) DEFAULT NULL COMMENT '联系方式/手机号',
+            "provinceCode", //int(10) DEFAULT NULL COMMENT '省份编码',
+            "cityCode", //int(10) DEFAULT NULL COMMENT '城市编码',
+            "districtCode", //int(10) DEFAULT NULL COMMENT '区县编码',
+            "contactAddress", //varchar(255) DEFAULT NULL COMMENT '仓库地址',
+            "remarks", //varchar(255) DEFAULT NULL COMMENT '备注',
+            "beginningStatus", // tinyint(3) NOT NULL DEFAULT '5' COMMENT '期初状态 5:正常 4:禁用',
+            "enableStatus", //tinyint(3) DEFAULT '5' COMMENT '启用状态 4:未启用 5:启用',
+            "deleteStatus", //tinyint(3) DEFAULT '5' COMMENT '删除状态 4:删除 5:正常',
+            "updateTime", //int(10) DEFAULT NULL COMMENT '更新时间',
+            "createTime", //int(10) DEFAULT NULL COMMENT '创建时间',
+            "extend", //json DEFAULT NULL COMMENT '扩展字段',
+        ];
+        $this->_readonly = ['id'];
+        $this->_create_autofill = [
+            'createTime' => time()
+        ];
+        $this->_update_autofill = [
+            'updateTime' => time()
+        ];
+
+        parent::__construct($serviceDB);
+    }
+}

+ 154 - 0
Jobs/Model/MConsole.Class.php

@@ -0,0 +1,154 @@
+<?php
+namespace Jobs\Model;
+
+use Mall\Framework\Factory;
+use Jobs\Model\MProcess;
+
+class MConsole
+{
+    public $logger    = null;
+    private $config   = [];
+
+    public function __construct($config)
+    {
+        $this->config = $config;
+        $this->logger  = Factory::logs($this->config['logPath'] ?:'', $this->config['logSaveFileApp'] ?:'', $this->config['app_name'] ?:'');
+    }
+
+    public function run()
+    {
+        $this->runOpt();
+    }
+
+    public function runOpt()
+    {
+        global $argv;
+        if (empty($argv[1])) {
+            $this->printHelpMessage();
+            exit();
+        }
+        $opt=$argv[1];
+        switch ($opt) {
+            case 'start':
+                $this->start($this->config);
+                break;
+            case 'stop':
+                $this->sendSignal();
+                break;
+            case 'status':
+                $this->sendSignal(SIGUSR2);
+                break;
+            case 'exit':
+                $this->kill();
+                break;
+            case 'restart':
+                $this->restart();
+                break;
+            case 'help':
+                $this->printHelpMessage();
+                break;
+
+            default:
+                $this->printHelpMessage();
+                break;
+        }
+    }
+
+    public function restart()
+    {
+        $this->logger->log('restarting...');
+        $this->kill();
+        sleep(3);
+        $this->start($this->config);
+    }
+
+    public function kill()
+    {
+        $this->sendSignal(SIGTERM);
+    }
+
+    /**
+     * 启动进程
+     */
+    public function start($config)
+    {
+        $process = new MProcess($config);
+        $process->start();
+    }
+
+    /**
+     *  给主进程发送信号:
+     *  SIGUSR1 自定义信号,让子进程平滑退出
+     *  SIGUSR2 自定义信号2,显示进程状态
+     *  SIGTERM 程序终止,让子进程强制退出.
+     *
+     * @param [type] $signal
+     */
+    public function sendSignal($signal=SIGUSR1)
+    {
+        $this->logger->log($signal . (SIGUSR1 == $signal) ? ' smooth to exit...' : ' force to exit...');
+
+        if (isset($this->config['pidPath']) && !empty($this->config['pidPath'])) {
+            $masterPidFile=$this->config['pidPath'] . '/master.pid';
+            $pidStatusFile=$this->config['pidPath'] . '/status.info';
+        } else {
+            die('config pidPath must be set!' . PHP_EOL);
+        }
+
+        if (file_exists($masterPidFile)) {
+            $pid   =file_get_contents($masterPidFile);
+            if ($pid && !@\Swoole\Process::kill($pid, 0)) {
+                exit('service is not running' . PHP_EOL);
+            }
+            if (@\Swoole\Process::kill($pid, $signal)) {
+                $this->logger->log('[master pid: ' . $pid . '] has been received  signal' . $signal);
+                sleep(1);
+                //如果是SIGUSR2信号,显示swoole-jobs状态信息
+                if (SIGUSR2 == $signal) {
+                    $statusStr=file_get_contents($pidStatusFile);
+
+                    echo $statusStr ? $statusStr : 'sorry,show status fail.';
+                    exit;
+                }
+            }
+            $this->logger->log('[master pid: ' . $pid . '] has been received signal fail');
+        } else {
+            exit('service is not running' . PHP_EOL);
+        }
+    }
+
+    /**
+     * 帮助手册
+     */
+    public function printHelpMessage()
+    {
+        $msg=<<<'EOF'
+NAME
+      php swoole-jobs - manage swoole-jobs
+
+SYNOPSIS
+      php swoole-jobs command [options]
+          Manage swoole-jobs daemons.
+
+WORKFLOWS
+
+      help [command]
+      Show this help, or workflow help for command.
+
+      restart
+      Stop, then start swoole-jobs master and workers.
+
+      start
+      Start swoole-jobs master and workers.
+
+      stop
+      Wait all running workers smooth exit, please check swoole-jobs status for a while.
+
+      exit
+      Kill all running workers and master PIDs.
+
+
+EOF;
+        echo $msg;
+    }
+}

+ 114 - 0
Jobs/Model/MJobs.Class.php

@@ -0,0 +1,114 @@
+<?php
+namespace Jobs\Model;
+
+use Mall\Framework\Factory;
+
+use Jobs\Model\MQueue;
+use Jobs\Model\MProcess;
+
+class MJobs
+{
+    public $logger              = null;
+    public $queue               = null;
+    public $sleep               = 2; //单个topic如果没有任务,该进程暂停秒数,不能低于1秒,数值太小无用进程会频繁拉起
+    public $config              = [];
+
+    private $pidInfoFile        = ''; // 主进程pid信息文件路径
+
+    public function __construct($pidInfoFile, $config)
+    {
+        $this->config      = $config;
+        $this->pidInfoFile = $pidInfoFile;
+        $this->sleep       = $this->config['sleep'] ?: $this->sleep;
+        $this->logger      = Factory::logs($this->config['logPath'] ?:'', $this->config['logSaveFileApp'] ?:'', $this->config['app_name'] ?:'');
+    }
+
+
+    public function run($topic='')
+    {
+        if ($topic) {
+            $this->queue = MQueue::getQueue($this->config['job']['queue'], $this->logger);
+            if (empty($this->queue)) {
+                sleep($this->sleep);
+
+                return;
+            }
+            $this->queue->setTopics($this->config['job']['topics'] ?: []);
+
+            $len = $this->queue->len($topic);
+            $this->logger->log($topic . ' pop len: ' . $len, 'info');
+            if ($len > 0) {
+                //循环拿出队列消息
+                while ($data = $this->queue->pop($topic)) {
+                    //主进程状态不是running状态,退出循环
+                    if (MProcess::STATUS_RUNNING != $this->getMasterData('status')) {
+                        break;
+                    }
+                    $this->logger->log('pop data: ' . print_r($data, true), 'info');
+                    if (!empty($data) && is_object($data)) {
+                        $beginTime=microtime(true);
+                        // 根据自己的业务需求改写此方法
+                        $jobObject               =  $this->loadObject($data);
+                        $baseAction              =  $this->loadFrameworkAction();
+                        $baseAction->start($jobObject);
+                        $endTime=microtime(true);
+                        $this->logger->log('job id ' . $jobObject->uuid . ' done, spend time: ' . ($endTime - $beginTime), 'info');
+                        unset($jobObject, $baseAction);
+                    } else {
+                        $this->logger->log('pop error data: ' . print_r($data, true), 'error');
+                    }
+                    // if ($this->queue->len($topic) <= 0) {
+                    //     break;
+                    // }
+                }
+            } else {
+                $this->logger->log($topic . ' no work to do!', 'info');
+                sleep($this->sleep);
+                //$this->logger->log('sleep ' . $this->sleep . ' second!', 'info');
+            }
+            $this->queue->close();
+        } else {
+            $this->logger->log('All topic no work to do!', 'info');
+        }
+    }
+
+    /**
+     * 获取主进程状态
+     * @param string $key
+     * @return mixed|null
+     */
+    private function getMasterData($key='')
+    {
+        $data=unserialize(file_get_contents($this->pidInfoFile));
+        if ($key) {
+            return $data[$key] ?: null;
+        }
+
+        return $data;
+    }
+
+    //实例化job对象
+    private function loadObject($data)
+    {
+        if (is_object($data)) {
+            return $data;
+        }
+
+        return fasle;
+    }
+
+    //根据配置装入不同的框架
+    private function loadFrameworkAction()
+    {
+        $classFramework=$this->config['framework']['class'] ?: 'Jobs\Controller\CJobs';
+        try {
+            $action = new $classFramework($this->config);
+        } catch (\Throwable $e) {
+            Utils::catchError($this->logger, $e);
+        } catch (\Exception $e) {
+            Utils::catchError($this->logger, $e);
+        }
+
+        return $action;
+    }
+}

+ 441 - 0
Jobs/Model/MProcess.Class.php

@@ -0,0 +1,441 @@
+<?php
+namespace Jobs\Model;
+
+use Mall\Framework\Factory;
+
+use Jobs\Model\MJobs;
+
+class MProcess
+{
+    const CHILD_PROCESS_CAN_RESTART                    ='staticWorker'; //子进程可以重启,进程个数固定
+    const CHILD_PROCESS_CAN_NOT_RESTART                ='dynamicWorker'; //子进程不可以重启,进程个数根据队列堵塞情况动态分配
+    const STATUS_RUNNING                               ='runnning'; //主进程running状态
+    const STATUS_WAIT                                  ='wait'; //主进程wait状态
+    const STATUS_STOP                                  ='stop'; //主进程stop状态
+    const APP_NAME                                     ='jobs'; //app name
+    const STATUS_HSET_KEY_HASH                         ='status'; //status hash名
+
+    public $processName                   = ':swooleProcessTopicQueueJob'; // 进程重命名, 方便 shell 脚本管理
+    public $workers                       = [];
+
+    private $version                      = '2.5';
+    private $excuteTime                   =3600; //子进程最长执行时间,单位:秒
+    private $queueMaxNum                  =10; //队列达到一定长度,启动动态子进程个数发和送消息提醒
+    private $queueTickTimer               =1000 * 10; //一定时间间隔(毫秒)检查队列长度;默认10秒钟
+    private $messageTickTimer             =1000 * 180; //一定时间间隔(毫秒)发送消息提醒;默认3分钟
+    private $message                      =[]; //提醒消息内容
+    private $workerNum                    =0; //固定分配的子进程个数
+    private $dynamicWorkerNum             =[]; //动态(不能重启)子进程计数,最大数为每个topic配置workerMaxNum,它的个数是动态变化的
+    private $workersInfo                  =[];
+    private $ppid;
+    private $config                       = [];
+    private $pidFile                      = 'master.pid'; //pid存放文件
+    private $pidInfoFile                  = 'master.info'; //pid 序列化信息
+    private $pidStatusFile                = 'status.info'; //pid status信息
+    private $status                       = '';
+    private $logger                       = null;
+    private $queue                        = null;
+    private $topics                       = null;
+    private $beginTime                    = '';
+    private $logSaveFileWorker            = 'workers.log';
+
+    public function __construct($config)
+    {
+        $this->config                    = $config;
+        $this->logger                    = Factory::logs($this->config['logPath'] ?:'', $this->config['logSaveFileApp'] ?:'', $this->config['app_name'] ?:'');
+        $this->topics                    = $this->config['job']['topics'] ?: [];
+        $this->processName               = $this->config['processName'] ?: $this->processName;
+        $this->excuteTime                = $this->config['excuteTime'] ?: $this->excuteTime;
+        $this->queueMaxNum               = $this->config['queueMaxNum'] ?: $this->queueMaxNum;
+        $this->queueTickTimer            = $this->config['queueTickTimer'] ?: $this->queueTickTimer;
+        $this->messageTickTimer          = $this->config['messageTickTimer'] ?: $this->messageTickTimer;
+        $this->logSaveFileWorker         = $this->config['logSaveFileWorker'] ?: $this->logSaveFileWorker;
+
+        $this->beginTime=time();
+        //该变量需要在多进程共享
+        $this->status=self::STATUS_RUNNING;
+
+        if (isset($this->config['pidPath']) && !empty($this->config['pidPath'])) {
+            if (!is_dir($this->config['pidPath'])) {
+                mkdir($this->config['pidPath'], '0777', true);
+            }
+            $this->pidFile      =$this->config['pidPath'] . '/' . $this->pidFile;
+            $this->pidInfoFile  =$this->config['pidPath'] . '/' . $this->pidInfoFile;
+            $this->pidStatusFile=$this->config['pidPath'] . '/' . $this->pidStatusFile;
+        } else {
+            die('config pidPath must be set!' . PHP_EOL);
+        }
+
+        /*
+         * master.pid 文件记录 master 进程 pid, 方便之后进程管理
+         * 请管理好此文件位置, 使用 systemd 管理进程时会用到此文件
+         * 判断文件是否存在,并判断进程是否在运行
+         */
+        if (file_exists($this->pidFile)) {
+            $pid=$this->getMasterData('pid');
+
+            // $signo=0,可以检测进程是否存在,不会发送默认SIGTERM信号,终止进程
+            if ($pid && @\Swoole\Process::kill($pid, 0)) {
+                die('已有进程运行中,请先结束或重启' . PHP_EOL);
+            }
+        }
+
+        // 使当前进程蜕变为一个守护进程。
+        \Swoole\Process::daemon();
+        $this->ppid    = getmypid();
+        $data['pid']   =$this->ppid;
+        $data['status']=$this->status;
+        $this->saveMasterData($data);
+        $this->setProcessName(self::APP_NAME . ' master ' . $this->ppid . $this->processName);
+        //报错解决:must be forked outside the coroutine
+        swoole_async_set(['enable_coroutine' => false]);//关闭内置协程
+    }
+
+    /**
+     * 设置进程名
+     * @param mixed $name
+     */
+    private function setProcessName($name)
+    {
+        $updateName = 0;
+        // 低版本Linux内核和Mac OSX不支持进程重命名
+        if (function_exists('cli_set_process_title') && PHP_OS != 'Darwin'){
+            if(cli_set_process_title($name)){ // 按照官网文档优先使用内置函数,php >= 5.5
+                $updateName = 1;
+            }
+        }else if (function_exists('swoole_set_process_name') && PHP_OS != 'Darwin' && !$updateName) {
+            swoole_set_process_name($name); // swoole >= 1.6.3
+        }
+    }
+
+    /**
+     * 保存守护进程数据
+     * @param array $data
+     */
+    private function saveMasterData($data=[])
+    {
+        isset($data['pid']) && file_put_contents($this->pidFile, $data['pid']);
+        file_put_contents($this->pidInfoFile, serialize($data));
+    }
+
+    /**
+     * 读取守护进程数据
+     * @param string $key
+     * @return mixed|null
+     */
+    private function getMasterData($key='')
+    {
+        $data=unserialize(file_get_contents($this->pidInfoFile));
+        if ($key) {
+            return $data[$key] ?: null;
+        }
+
+        return $data;
+    }
+
+    /**
+     * 按照配置开启每个topic进程
+     */
+    public function start()
+    {
+        $topics = $this->topics;
+        $this->logger->log('topics: ' . json_encode($topics));
+
+        if ($topics) {
+            //遍历topic任务列表
+            foreach ((array) $topics as  $topic) {
+                if (isset($topic['workerMinNum']) && isset($topic['name'])) {
+                    //每个topic开启最少个进程消费队列
+                    for ($i = 0; $i < $topic['workerMinNum']; ++$i) {
+                        $this->reserveQueue($i, $topic['name'], self::CHILD_PROCESS_CAN_RESTART);
+                    }
+                }
+            }
+        }
+
+        $this->registSignal();
+        $this->registTimer();
+    }
+
+    //增加定时器,检查队列积压情况;
+    public function registTimer()
+    {
+        \Swoole\Timer::tick($this->queueTickTimer, function ($timerId) {
+            $topics = $this->topics;
+            $this->status  =$this->getMasterData('status');
+            if (empty($this->workers) && self::STATUS_WAIT == $this->status) {
+                $this->exitMaster();
+            }
+            $this->queue   = MQueue::getQueue($this->config['job']['queue'], $this->logger);
+            if (empty($this->queue)) {
+                $this->logger->log('queue connection is lost', 'info', $this->logSaveFileWorker);
+
+                return;
+            }
+            $this->queue->setTopics($topics);
+
+            if ($topics && self::STATUS_RUNNING == $this->status) {
+                //遍历topic任务列表
+                foreach ((array) $topics as  $topic) {
+                    if (empty($topic['name'])) {
+                        continue;
+                    }
+                    $this->dynamicWorkerNum[$topic['name']]=$this->dynamicWorkerNum[$topic['name']] ?? 0;
+                    $topic['workerMaxNum']                       =$topic['workerMaxNum'] ?? 0;
+                    try {
+                        $len=$this->queue->len($topic['name']);
+                        $this->logger->log('topic: ' . $topic['name'] . ' ' . $this->status . ' len: ' . $len, 'info', $this->logSaveFileWorker);
+                    } catch (\Throwable $e) {
+                        $this->logger->log('queueError' . $e->getMessage(), 'error', $this->logSaveFileWorker);
+                    } catch (\Exception $e) {
+                        $this->logger->log('queueError: ' . $e->getMessage(), 'error', $this->logSaveFileWorker);
+                    }
+                    $this->status=$this->getMasterData('status');
+                    //消息提醒:消息体收集
+                    if ($len > $this->queueMaxNum && count($this->message) <= count($topics)) {
+                        $this->message[]= strtr('Time:{time} Pid:{pid} ProName:{pname} Topic:{topic} Message:{message}', [
+                            '{time}'   => date('Y-m-d H:i:s'),
+                            '{pid}'    => $this->ppid,
+                            '{pname}'  => $this->processName,
+                            '{topic}'  => $topic['name'],
+                            '{message}'=> '积压消息个数:' . $len . PHP_EOL,
+                        ]);
+                    }
+
+                    if ($topic['workerMaxNum'] > $topic['workerMinNum'] && self::STATUS_RUNNING == $this->status && $len > $this->queueMaxNum && $this->dynamicWorkerNum[$topic['name']] < $topic['workerMaxNum']) {
+                        $max=$topic['workerMaxNum'] - $this->dynamicWorkerNum[$topic['name']];
+                        for ($i=0; $i < $max; ++$i) {
+                            //队列堆积达到一定数据,拉起一次性子进程,这类进程不会自动重启[没必要]
+                            $this->reserveQueue($this->dynamicWorkerNum[$topic['name']], $topic['name'], self::CHILD_PROCESS_CAN_NOT_RESTART);
+                            ++$this->dynamicWorkerNum[$topic['name']];
+                            $this->logger->log('topic: ' . $topic['name'] . ' ' . $this->status . ' len: ' . $len . ' for: ' . $i . ' ' . $max, 'info', $this->logSaveFileWorker);
+                        }
+                    }
+                }
+            }
+            $this->queue->close();
+        });
+        //积压队列提醒
+        \Swoole\Timer::tick($this->messageTickTimer, function ($timerId) {
+            !empty($this->message) && $this->logger->log('Warning Message: ' . implode('', $this->message), 'warning', $this->logSaveFileWorker);
+            if ($this->message && isset($this->config['message'])) {
+                //$message =Message::getMessage($this->config['message']);
+                //$message->send(implode('', $this->message), $this->config['message']['token']);
+            }
+            //重置message,防止message不断变长
+            $this->message=[];
+        });
+    }
+
+    //退出主进程
+    private function exitMaster()
+    {
+        @unlink($this->pidFile);
+        @unlink($this->pidInfoFile);
+        $this->logger->log('Time: ' . microtime(true) . '主进程' . $this->ppid . '退出', 'info', $this->logSaveFileWorker);
+
+        sleep(1);
+        exit();
+    }
+
+    /**
+     * 注册信号
+     */
+    public function registSignal()
+    {
+        //终止进程信号
+        \Swoole\Process::signal(SIGTERM, function ($signo) {
+            $this->killWorkersAndExitMaster();
+        });
+        //
+        \Swoole\Process::signal(SIGKILL, function ($signo) {
+            $this->killWorkersAndExitMaster();
+        });
+        //平滑退出
+        \Swoole\Process::signal(SIGUSR1, function ($signo) {
+            $this->waitWorkers();
+        });
+        //记录进程状态
+        \Swoole\Process::signal(SIGUSR2, function ($signo) {
+            $this->logger->log('[master pid: ' . $this->ppid . '] has been received  signal' . $signo);
+            $result=$this->showStatus();
+            $this->saveSwooleJobsStatus($result);
+            //echo $result;
+        });
+
+        // 在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程
+        \Swoole\Process::signal(SIGCHLD, function ($signo) {
+            while (true) {
+                try {
+                    $ret = \Swoole\Process::wait(false);
+                } catch (\Exception $e) {
+                    $this->logger->log('signoError: ' . $signo . $e->getMessage(), 'error', $this->logSaveFileWorker);
+                }
+                if ($ret) {
+                    $pid           = $ret['pid'];
+                    $childProcess = $this->workers[$pid];
+                    $topic = $this->workersInfo[$pid]['topic'] ?: '';
+                    $this->status=$this->getMasterData('status');
+                    if(empty($this->dynamicWorkerNum) || empty($this->dynamicWorkerNum[$topic])){
+                        $topicCanNotRestartNum = null;
+                    }else{
+                        $topicCanNotRestartNum =  $this->dynamicWorkerNum[$topic];
+                    }
+                    // $topicCanNotRestartNum =  $this->dynamicWorkerNum[$topic] ?: 'null';
+                    $this->logger->log(self::CHILD_PROCESS_CAN_RESTART . '---' . $topic . '***' . $topicCanNotRestartNum . '***' . $this->status . '***' . $this->workersInfo[$pid]['type'] . '***' . $pid, 'info', $this->logSaveFileWorker);
+                    $this->logger->log($pid . ',' . $this->status . ',' . self::STATUS_RUNNING . ',' . $this->workersInfo[$pid]['type'] . ',' . self::CHILD_PROCESS_CAN_RESTART, 'info', $this->logSaveFileWorker);
+
+                    //主进程状态为running并且该子进程是可以重启的
+                    if (self::STATUS_RUNNING == $this->status && $this->workersInfo[$pid]['type'] == self::CHILD_PROCESS_CAN_RESTART) {
+                        try {
+                            //子进程重启可能失败,必须启动成功之后,再往下执行;最多尝试30次
+                            for ($i=0; $i < 30; ++$i) {
+                                var_dump("aaaa");
+                                $newPid = $childProcess->start();
+                                var_dump("xxxxxx".$newPid);
+                                if ($newPid > 0) {
+                                    break;
+                                }
+                                sleep(1);
+                            }
+                            if (!$newPid) {
+                                $this->logger->log('静态子进程重启失败,问题有点严重,平滑退出子进程,主进程会跟着退出', 'error', $this->logSaveFileWorker);
+                                $this->waitWorkers();
+                                //$this->reserveQueue(0, $topic);
+                                continue;
+                            }
+
+                            $this->workers[$newPid] = $childProcess;
+                            $this->workersInfo[$newPid]['type'] = self::CHILD_PROCESS_CAN_RESTART;
+                            $this->workersInfo[$newPid]['topic'] = $topic;
+                            ++$this->workerNum;
+                            $this->logger->log("Worker Restart, kill_signal={$ret['signal']} PID=" . $newPid, 'info', $this->logSaveFileWorker);
+                        } catch (\Throwable $e) {
+                            $this->logger->log('restartErrorThrow' . $e->getMessage(), 'error', $this->logSaveFileWorker);
+                        } catch (\Exception $e) {
+                            $this->logger->log('restartError: ' . $e->getMessage(), 'error', $this->logSaveFileWorker);
+                        }
+                    }
+                    //某个topic动态变化的子进程,退出之后个数减少一个
+                    if ($this->workersInfo[$pid]['type'] == self::CHILD_PROCESS_CAN_NOT_RESTART) {
+                        --$this->dynamicWorkerNum[$topic];
+                    }
+                    $this->logger->log("Worker Exit, kill_signal={$ret['signal']} PID=" . $pid, 'info', $this->logSaveFileWorker);
+                    unset($this->workers[$pid], $this->workersInfo[$pid]);
+                    --$this->workerNum;
+
+                    $this->logger->log('Worker count: ' . count($this->workers) . '==' . $this->workerNum, 'info', $this->logSaveFileWorker);
+                    //如果$this->workers为空,且主进程状态为wait,说明所有子进程安全退出,这个时候主进程退出
+                    if (empty($this->workers) && self::STATUS_WAIT == $this->status) {
+                        $this->logger->log('主进程收到所有信号子进程的退出信号,子进程安全退出完成', 'info', $this->logSaveFileWorker);
+                        $this->exitMaster();
+                    }
+                } else {
+                    break;
+                }
+            }
+        });
+    }
+
+    private function saveSwooleJobsStatus($data)
+    {
+        file_put_contents($this->pidStatusFile, $data);
+    }
+
+    private function showStatus()
+    {
+        $statusStr  ='-------------------------------------' . $this->processName . ' status--------------------------------------------' . PHP_EOL;
+        $statusStr .= 'PHP version:' . PHP_VERSION . '      swoole-jobs version: ' . $this->version . PHP_EOL;
+        $statusStr .= 'start time : ' . date('Y-m-d H:i:s', $this->beginTime) . '   run ' . floor((time() - $this->beginTime) / (24 * 60 * 60)) . ' days ' . floor(((time() - $this->beginTime) % (24 * 60 * 60)) / (60 * 60)) . ' hours   ' . PHP_EOL;
+        //$statusStr .= Utils::getSysLoadAvg() . '   memory use:' . Utils::getServerMemoryUsage() . PHP_EOL;
+        $statusStr .= '|-- Master pid ' . $this->ppid . ' status: ' . $this->status . ' Worker num: ' . count($this->workers) . PHP_EOL;
+        if ($this->workers) {
+            foreach ($this->workers as $pid => $value) {
+                $type =$this->workersInfo[$pid]['type'];
+                $topic=$this->workersInfo[$pid]['topic'];
+
+                $statusStr .= '    |---- Worker pid:  ' . $pid . ' ' . $type . ' ' . $topic . PHP_EOL;
+            }
+        }
+
+        return $statusStr;
+    }
+
+    //平滑等待子进程退出之后,再退出主进程
+    private function waitWorkers()
+    {
+        $data['pid']   =$this->ppid;
+        $data['status']=self::STATUS_WAIT;
+        $this->saveMasterData($data);
+        $this->status = self::STATUS_WAIT;
+        $this->logger->log('master status: ' . $this->status, 'info', $this->logSaveFileWorker);
+    }
+
+    //强制杀死子进程并退出主进程
+    private function killWorkersAndExitMaster()
+    {
+        //修改主进程状态为stop
+        $this->status   =self::STATUS_STOP;
+        if ($this->workers) {
+            foreach ($this->workers as $pid => $worker) {
+                //强制杀workers子进程
+                \Swoole\Process::kill($pid);
+                unset($this->workers[$pid]);
+                $this->logger->log('主进程收到退出信号,[' . $pid . ']子进程跟着退出', 'info', $this->logSaveFileWorker);
+                $this->logger->log('Worker count: ' . count($this->workers), 'info', $this->logSaveFileWorker);
+            }
+        }
+        $this->exitMaster();
+    }
+
+    /**
+     * fork子进程消费队列.
+     *
+     * @param [type] $num   子进程编号
+     * @param [type] $topic topic名称
+     * @param string $type  是否会重启 canRestart|unRestart
+     */
+    public function reserveQueue($num, $topic, $type=self::CHILD_PROCESS_CAN_RESTART)
+    {
+        $reserveProcess = new \Swoole\Process(function ($worker) use ($num, $topic, $type) {
+            $this->checkMpid($worker);
+            $beginTime=microtime(true);
+            try {
+                //设置进程名字
+                $this->setProcessName($type . ' ' . $topic . ' job ' . $num . ' ' . $this->processName);
+                $jobs  = new MJobs($this->pidInfoFile, $this->config);
+                do {
+                    $jobs->run($topic);
+                    $this->status=$this->getMasterData('status');
+                    $where = (self::STATUS_RUNNING == $this->status) && (self::CHILD_PROCESS_CAN_RESTART == $type ? time() < ($beginTime + $this->excuteTime) : false);
+                } while ($where);
+            } catch (\Throwable $e) {
+                catchError($this->logger, $e);
+            } catch (\Exception $e) {
+                catchError($this->logger, $e);
+            }
+
+            $endTime=microtime(true);
+            $this->logger->log($topic . ' worker id: ' . $num . ' is done!!! Timing: ' . ($endTime - $beginTime), 'info', $this->logSaveFileWorker);
+            unset($num, $topic, $type);
+        });
+        $pid                                        = $reserveProcess->start();
+        $this->workers[$pid]                        = $reserveProcess;
+        $this->workersInfo[$pid]['type']            = $type;
+        $this->workersInfo[$pid]['topic']           = $topic;
+        $this->logger->log('topic: ' . $topic . ' ' . $type . ' worker id: ' . $num . ' pid: ' . $pid . ' is start...', 'info', $this->logSaveFileWorker);
+        ++$this->workerNum;
+    }
+
+    /**
+     * 主进程如果不存在了,子进程退出
+     **/
+    private function checkMpid(&$worker)
+    {
+        if (!@\Swoole\Process::kill($this->ppid, 0)) {
+            $worker->exit();
+            $this->logger->log("Master process exited, I [{$worker['pid']}] also quit", 'info', $this->logSaveFileWorker);
+        }
+    }
+
+}

+ 25 - 0
Jobs/Model/MQueue.Class.php

@@ -0,0 +1,25 @@
+<?php
+namespace Jobs\Model;
+
+class MQueue
+{
+    public static function getQueue(array $config, $logger)
+    {
+        $classQueue = $config['class'] ?: 'Jobs\Model\Queue\MRedisTopicQueue';
+        if (is_callable([$classQueue, 'getConnection'])) {
+            //最多尝试连接3次
+            for ($i=0; $i < 3; $i++) {
+                $connection = $classQueue::getConnection($config, $logger);
+                if ($connection && is_object($connection)) {
+                    break;
+                }else{
+                    $logger->log("connect...,retry=".($i+1), 'error');
+                }
+            }
+
+            return $connection;
+        }
+        echo 'you must add queue config' . PHP_EOL;
+        exit;
+    }
+}

+ 85 - 0
Jobs/Model/MTopic/Enterprise/MEnterprise.Class.php

@@ -0,0 +1,85 @@
+<?php
+/**
+ * 企业
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2020/06/30
+ * Time: 18:41
+ */
+
+namespace Jobs\Model\MTopic\Enterprise;
+
+
+use Mall\Framework\Core\ErrorCode;
+use Mall\Framework\Core\ResultWrapper;
+use Mall\Framework\Core\StatusCode;
+
+class MEnterprise
+{
+    private $enterpriseId;
+
+    private $userCenterId;
+
+    private $objDMessage;
+
+    /**
+     * MGrantCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        echo '企业创建自动创建数据:' . date('Y-d-d H:i:s') . ':' . PHP_EOL;
+    }
+
+    /**
+     * 自动创建
+     * @param $params
+     * @return bool
+     * @throws \Exception
+     */
+    public function autoCreate($params)
+    {
+        echo '开始执行自动创建队列方法**************************************************************************************************************************';
+        var_dump($params);
+        $project_domain = $params['data']['PROJECT_DOMAIN'];
+        unset($params['data']['PROJECT_DOMAIN']);
+        if(empty($params['data']['enterpriseId'])){
+            echo '企业id参数错误'.PHP_EOL;
+            return false;
+        }
+        if(empty($params['data']['userCenterId'])){
+            echo '用户id参数错误'.PHP_EOL;
+            return false;
+        }
+        if(empty($params['data']['Authorization'])){
+            echo 'Authorization参数错误'.PHP_EOL;
+            return false;
+        }
+
+        switch ($project_domain){
+            case 'api':
+                $ip = URL_API.'/Enterprise/UserEnterprise/autoCreateData';
+                break;
+            default:
+                $ip = DEV_URL_API.'/Enterprise/UserEnterprise/autoCreateData';
+        }
+
+        $postData = [
+            'enterpriseId' => $params['data']['enterpriseId'],
+            'userCenterId' => $params['data']['userCenterId']
+        ];
+        $post = json_encode($postData);
+        $curl_option = [
+            CURLOPT_HTTPHEADER => [
+                'Content-Type:text/plain',
+                'Authorization:'.$params['data']['Authorization'],
+            ],
+        ];
+        $result = request($ip, $post, 40, false,$curl_option);
+        print_r($result);
+        echo '成功' . PHP_EOL;
+        return true;
+    }
+
+
+}

+ 252 - 0
Jobs/Model/MTopic/Finance/MPayable.Class.php

@@ -0,0 +1,252 @@
+<?php
+/**
+ * 财务应付生成和检测脚本
+ * Created by PhpStorm.
+ * User: phperstar
+ * Date: 2019/12/19
+ * Time: 10:38 AM
+ */
+namespace Jobs\Model\MTopic\Finance;
+
+use Mall\Framework\Core\StatusCode;
+
+use Jobs\Cache\FinanceCache;
+
+use Jobs\Dao\Purchase\DPurchase;
+use Jobs\Dao\Purchase\DPurchaseOut;
+use Jobs\Dao\Stock\DInventoryOut;
+use Jobs\Dao\Stock\DInventoryInDetails;
+use Jobs\Dao\Finance\DPay;
+use Jobs\Dao\Finance\DPayReceiptIndex;
+
+
+class MPayable
+{
+    private $objDPurchase;
+    private $objDPurchaseOut;
+    private $objDInventoryOut;
+    private $objDPay;
+    private $objDPayReceiptIndex;
+
+    public function __construct()
+    {
+        $this->objDPurchase = new DPurchase('stock');
+        $this->objDPurchaseOut = new DPurchaseOut('stock');
+        $this->objDInventoryOut = new DInventoryOut('stock');
+        $this->objDPay = new DPay('finance');
+        $this->objDPayReceiptIndex = new DPayReceiptIndex('finance');
+        //$this->objDPay->setSearchIndex('should_pay_receipt_search')->setType('should_pay_receipt');
+    }
+
+    /**
+     * 检测销售出库单是否都生成应收单了
+     */
+    public function checkSaleOutCreateReceivable()
+    {
+
+    }
+
+    /**
+     * 采购入库单生成应付单
+     */
+    public function createPayable($params)
+    {
+        if (empty($params)) {
+            echo '请求创建应付单参数为空'.PHP_EOL;
+            return false;
+        }
+
+        if (empty($params['type'])) {
+            echo '生成应付单:type字段错误,请提供单据类型'.PHP_EOL;
+            return false;
+        }
+
+        $payableExtraData = [];
+        $purchaseData = [];
+        $payableData = [];
+        //采购入库生成应付
+        if($params['type'] == StatusCode::$orderType['purchaseIn']) {
+            // 查询采购单信息
+            $this->objDPurchase->setTable($this->objDPurchase->get_Table() . '_' . $params['enterpriseId']);
+            $purchaseData = $this->objDPurchase->get(['id'=>$params['id']]);
+            if($purchaseData === false){
+                echo 'sql错误'.$this->objDPurchase->error().PHP_EOL;
+                return false;
+            }
+
+            if (empty($purchaseData)) {
+                echo '采购订单id:' . $params['id'] . '的数据为空'.PHP_EOL;
+                return false;
+            }
+
+            // 获取入库金额生成应付
+            $objDInventoryInDetails = new DInventoryInDetails('stock');
+            $objDInventoryInDetails->setTable('qianniao_inventory_in_details_'.$params['enterpriseId']);
+            $inDetailsData = $objDInventoryInDetails->select(['linkId' => $params['inventoryInId']]);
+            if($inDetailsData === false){
+                echo '查询采购订单对应的入库单详情数据错误'.$objDInventoryInDetails->error().PHP_EOL;
+                return false;
+            }
+            if( empty($inDetailsData) ){
+                echo '采购订单'.$params['id'].'对应的入库单详情数据为空'.PHP_EOL;
+                return false;
+            }
+
+            $payMoney = 0;
+            foreach ($inDetailsData as $key => $value){
+                $payMoney = bcadd($payMoney, bcmul($value['inNum'], $value['unitPrice']), 2);
+            }
+
+            $payableExtraData = [
+                'supplierId' => $purchaseData['supplierId'],
+                'supplierName' => $purchaseData['supplierName'],
+                'sourceNo' => $purchaseData['no'],
+                //'payMoney' => $payMoney, // 应付 = 实际采购总成本-均摊费用
+                'payMoney' => bcadd(bcsub($purchaseData['purchaseAmount'],$purchaseData['couponAmount'],2),$purchaseData['otherAmount'],2),
+                'discountMoney' => $purchaseData['couponAmount'],
+                'receiptTypeId' => StatusCode::$orderType['purchaseOrder'],
+                'purchaseId' => $purchaseData['id'],
+                'notOffsetMoney' => $payMoney,
+            ];
+            // 创建应付单数据
+            $payableData = [
+                'warehouseId' => $purchaseData['warehouseId'],
+                'warehouseName' => $purchaseData['warehouseName'],
+                'financeTypeId' => StatusCode::$orderType['purchaseReturn'],
+                'financeType'   => '采购单',
+                'auditStatus' => StatusCode::$auditStatus['auditing'],
+                'createTime'  => time(),
+                'updateTime'  => time(),
+            ];
+        }
+
+        //采购退货出库生成应付
+        if($params['type'] == StatusCode::$orderType['purchaseReturnOut']) {
+            // 查询采购退货出库单信息
+            $this->objDInventoryOut->setTable($this->objDInventoryOut->get_Table() . '_' . $params['enterpriseId']);
+            $inventoryOutData = $this->objDInventoryOut->get(['id'=>$params['id']]);
+            if($inventoryOutData === false){
+                echo 'sql错误'.$this->objDInventoryOut->error().PHP_EOL;
+                return false;
+            }
+
+            if (empty($inventoryOutData)) {
+                echo '采购退货出库单id:' . $params['id'] . '的数据为空'.PHP_EOL;
+                return false;
+            }
+
+            //查出源采购退货单对应的供应商Id和名称
+            $this->objDPurchaseOut->setTable($this->objDPurchaseOut->get_Table() . '_' . $params['enterpriseId']);
+            $purchaseData = $this->objDPurchaseOut->get(['no'=>$inventoryOutData['sourceNo']]);
+            if($purchaseData === false){
+                echo 'sql错误'.$this->objDPurchase->error().PHP_EOL;
+                return false;
+            }
+
+            if (empty($purchaseData)) {
+                echo '采购退货单no:' . $inventoryOutData['originNo'] . '的数据为空'.PHP_EOL;
+                return false;
+            }
+
+            $payableExtraData = [
+                'supplierId' => $purchaseData['supplierId'],
+                'supplierName' => $purchaseData['supplierName'],
+                'sourceNo' => $purchaseData['originNo'],//采购订单编号
+                'payMoney' => '-'.bcadd($purchaseData['purchaseAmount'], $purchaseData['otherAmount'],4),//实际应付金额
+                'discountMoney' => 0,
+                'receiptTypeId' => StatusCode::$orderType['purchaseReturn'],
+                'purchaseId' => $purchaseData['originId'],
+                'notOffsetMoney'=>'-'.bcadd($purchaseData['purchaseAmount'], $purchaseData['otherAmount'],4),//实际应付金额
+            ];
+            // 创建应付单数据
+            $payableData = [
+                'warehouseId' => $purchaseData['warehouseId'],
+                'warehouseName' => $purchaseData['warehouseName'],
+                'financeTypeId' => StatusCode::$orderType['purchaseReturn'],
+                'financeType'   => '采购退款单',
+                'auditStatus' => StatusCode::$auditStatus['auditing'],
+                'createTime'  => time(),
+                'updateTime'  => time(),
+            ];
+        }
+
+        /*foreach ($payableData as $key => $value) {
+            if (empty($value) && $value !== 0) {
+                echo $key . '参数错误';
+                return false;
+            }
+        }*/
+        $payableData = array_merge($payableData, $payableExtraData);
+
+        // 添加应付单
+        $this->objDPay->beginTransaction();
+        $this->objDPay->setTable('qianniao_pay_receipt_' . $params['enterpriseId'] . '_' . date('Y') . '_' . ceil(date('m') / 3));
+
+        //添加应付单no编号
+        $dbResult =  $this->objDPay->get('createTime >='.strtotime(date('Ymd'.'0:0:0')), 'no', 'createTime desc');
+        if ($dbResult === false) {
+            echo '数据库查询失败'.$this->objDPay->error().PHP_EOL;
+            return false;
+        }
+        if(empty($dbResult)){
+            $payableData['no'] = createSerialNumberByDate('');
+        }else{
+            $payableData['no'] = createSerialNumberByDate($dbResult['no']);
+        }
+
+        //索引表数据
+        $indexData = [
+            'payReceiptId' => 0,
+            'supplierId'       => $payableData['supplierId'],
+            'sourceNo'         => $payableData['sourceNo'],
+            'auditStatus'      => $payableData['auditStatus'],
+            'financeTypeId'    => $payableData['financeTypeId'],
+            'financeType'      => $payableData['financeType'],
+            'warehouseId'      => $payableData['warehouseId'],
+            'createTime'       => $payableData['createTime'],
+            'updateTime'       => $payableData['updateTime'],
+
+        ];
+        $this->objDPayReceiptIndex->setTable('qianniao_pay_receipt_index_' . $params['enterpriseId']);
+        $payReceiptId = $this->objDPayReceiptIndex->insert($indexData);
+        if ($payReceiptId === false) {
+            $this->objDPay->rollBack();
+            echo 'sql错误'.$this->objDPayReceiptIndex->error().PHP_EOL;
+            return false;
+        }
+
+        $payableData['id'] = $payReceiptId;
+        $payableId = $this->objDPay->insert($payableData);
+        if ($payableId === false) {
+            $this->objDPay->rollBack();
+            echo 'sql错误'.$this->objDPay->error().PHP_EOL;
+            return false;
+        }
+
+
+        $this->objDPay->commit();
+
+        /*
+        $_id = self::createEsDocumentId($payableId, $params['enterpriseId']);
+        $esData = $payableData;
+        $esData['id'] = $payableId;
+        $esData['enterpriseId'] = $params['enterpriseId'];
+        $result = $this->objDPay->addUpSearchIndexDocument($esData, $_id);
+        if (isset($result['_shards']) && isset($result['_shards']['successful']) && $result['_shards']['successful'] == 1) {
+            //echo "es操作成功";die;
+        }*/
+
+        $objFinanceCache = new FinanceCache();
+        $objFinanceCache->cacheExistPayEnterprise($params['enterpriseId']);
+
+        echo '添加应付单成功'.PHP_EOL;
+        return true;
+    }
+
+    private function createEsDocumentId($payId, $enterpriseId)
+    {
+        $t = date('Y') . '_' . ceil(date('m') / 3);
+        return 'EnterpriseId_' . $enterpriseId . '_'. $t .'_payId_' . $payId;
+    }
+
+}

+ 488 - 0
Jobs/Model/MTopic/Finance/MReceivable.Class.php

@@ -0,0 +1,488 @@
+<?php
+/**
+ * 财务应收生成和检测脚本
+ * Created by PhpStorm.
+ * User: phperstar
+ * Date: 2019/12/19
+ * Time: 10:38 AM
+ */
+
+namespace Jobs\Model\MTopic\Finance;
+
+use Jobs\Dao\DShop;
+use Mall\Framework\Factory;
+use Jobs\Cache\OverviewCache;
+use Jobs\Dao\Purchase\DPurchase;
+use Jobs\Dao\Stock\DInventoryBatch;
+use Jobs\Dao\Stock\DWarehouse;
+use Mall\Framework\Core\StatusCode;
+use Jobs\Dao\Stock\DInventoryDetails;
+use Jobs\Dao\Order\DOrder;
+use Jobs\Dao\Stock\DInventoryIn;
+use Jobs\Dao\Stock\DInventoryOut;
+use Jobs\Dao\Finance\DReceiveReceiptIndex;
+use Jobs\Dao\Finance\DReceive;
+use Jobs\Cache\FinanceCache;
+
+
+class MReceivable
+{
+    private $objDOrder;
+    private $objDInventoryIn;
+    private $objDReceive;
+    private $objDReceiveReceiptIndex;
+    private $objFinanceCache;
+    private $objDInventoryDetails;
+    private $objDWarehouse;
+    private $enterpriseId;
+    private $objOverviewCache;
+    private $objDInventoryBatch;
+    private $objDPurchase;
+    private $objDShop;
+
+    private $cutTable = 200000; // 订单表切割基数
+
+    public function __construct()
+    {
+        $this->objDOrder = new DOrder('default');
+        $this->objDInventoryIn = new DInventoryIn('stock');
+        $this->objDReceive = new DReceive('finance');
+        $this->objDReceiveReceiptIndex = new DReceiveReceiptIndex('finance');
+        $this->objFinanceCache = new FinanceCache();
+        $this->objDInventoryDetails = new DInventoryDetails();
+        $this->objDWarehouse = new DWarehouse();
+        $this->objOverviewCache = new OverviewCache();
+        $this->objDInventoryBatch = new DInventoryBatch();
+        $this->objDPurchase = new DPurchase();
+        $this->objDShop = new DShop();
+
+        $this->objDReceive->setSearchIndex('should_receive_receipt_search')->setType('should_receive_receipt');
+
+    }
+
+    /**
+     * @param $params
+     */
+    public function checkExistCreate($params)
+    {
+        echo '检查应收单开始'.PHP_EOL;
+        print_r($params);
+        self::checkSaleOutCreateReceivable($params['enterpriseId']);
+        echo '检查成功'.PHP_EOL;
+    }
+
+    /**
+     * 检测销售出库单是否都生成应收单了
+     */
+    public function checkSaleOutCreateReceivable($enterpriseId)
+    {
+        $financeDbName = Factory::config()->get('db.finance.dbname');
+        $stockDbName = Factory::config()->get('db.stock.dbname');
+        $defaultDbName = Factory::config()->get('db.default.dbname');
+
+        if (!$financeDbName || !$stockDbName || !$defaultDbName) {
+            echo "dbname获取错误";
+            return false;
+        }
+
+        //查出该企业下 审核通过但未生成应收单的销售出库单
+        $sql = 'select a.originId,a.customerId,a.type,b.userCenterId,a.id from `'. $stockDbName .'`.`qianniao_inventory_out_'. $enterpriseId .'` as a JOIN `'. $defaultDbName .'`.qianniao_customer_'. $enterpriseId .' AS b ON a.customerId=b.id AND a.sourceNo NOT IN (select sourceNo from `'. $financeDbName .'`.`qianniao_receive_receipt_index_'. $enterpriseId .'`) and a.auditStatus = '. StatusCode::$auditStatus['auditPass'].' AND a.type ='.StatusCode::$orderType['saleOut'];
+        $salesOutData = $this->objDOrder->query($sql);
+        if (!empty($salesOutData)) {
+            foreach ($salesOutData as $salesOut) {
+                $result = self::createReceivable([
+                    'userCenterId' => $salesOut['userCenterId'],
+                    'enterpriseId' => $enterpriseId,
+                    'id'           => $salesOut['id'],//订单id
+                    'type'         => StatusCode::$orderType['saleOut'],
+                    'checkOldData'  => false
+                ]);
+                print_r('订单'.$salesOut['originId'].'生成应收'.$result);
+            }
+        }
+
+
+        //查出该企业下 审核通过但未生成应收单的销售出库单
+        $sql = 'select a.id,a.type,b.userCenterId from `'. $stockDbName .'`.`qianniao_inventory_in_'. $enterpriseId .'` as a JOIN `'. $defaultDbName .'`.qianniao_order_index_'. $enterpriseId .' AS b ON a.originId=b.id AND a.originNo NOT IN (select sourceNo from `'. $financeDbName .'`.`qianniao_receive_receipt_index_'. $enterpriseId .'`) and a.auditStatus = '. StatusCode::$auditStatus['auditPass'].' AND a.type ='.StatusCode::$orderType['saleReturnIn'];
+        $saleReturnInData = $this->objDOrder->query($sql);
+        if (!empty($saleReturnInData)) {
+            foreach ($saleReturnInData as $saleReturnIn) {
+                $result = self::createReceivable([
+                    'userCenterId' => $saleReturnIn['userCenterId'],
+                    'enterpriseId' => $enterpriseId,
+                    'id'           => $saleReturnIn['id'],//入库单Id
+                    'type'         => StatusCode::$orderType['saleReturnIn'],
+                    'checkOldData'  => false
+                ]);
+                print_r('入库单'.$saleReturnIn['id'].'生成应收'.$result);
+            }
+        }
+    }
+
+    /**
+     * 销售出库单生成应收单
+     * @param $params
+     * @return bool
+     * @throws \Exception
+     */
+    public function createReceivable($params)
+    {
+        // 参数校验
+        if (empty($params)) {
+            echo '请求创建应收单参数为空' . PHP_EOL;
+            return false;
+        }
+
+        foreach ($params as $key => $value){
+            if(empty($value)){
+                echo $key.'参数错误' . PHP_EOL;
+                return false;
+            }
+        }
+        $this->enterpriseId = $params['enterpriseId'];
+
+        $receiveExtraData = [];
+        $orderData = [];
+        $receiveData = [];
+        //销售出库生成应收
+        if ($params['type'] == StatusCode::$orderType['saleOut']) {
+            // 查询销售出库单数据
+            $objDInventoryOut  = new DInventoryOut('stock');
+            $objDInventoryOut->setTable('qianniao_inventory_out_'.$params['enterpriseId']);
+            $inventoryOutData = $objDInventoryOut->get(['id'=>$params['id']]);
+            if($inventoryOutData === false){
+                echo 'sql错误'.$objDInventoryOut->error().PHP_EOL;
+                return false;
+            }
+
+            if (empty($inventoryOutData)) {
+                echo '销售出库单id:' . $params['id'] . '的数据为空'.PHP_EOL;
+                return false;
+            }
+
+            // 查询订单信息
+            $tableName = $this->objDOrder->getTableName('qianniao_order_' . $params['enterpriseId'], $params['userCenterId'], $this->cutTable);
+            $this->objDOrder->setTable($tableName);
+            $orderData = $this->objDOrder->get(['id' => $inventoryOutData['originId']]);
+            if ($orderData === false) {
+                echo 'sql错误' . $this->objDOrder->error() . PHP_EOL;
+                return false;
+            }
+
+            if (empty($orderData)) {
+                echo '源销售订单id:' . $inventoryOutData['originId'] . '的数据为空' . PHP_EOL;
+                return false;
+            }
+
+            // 统计首页概况今日毛利
+            self::getInfo($orderData);
+
+            // 组装应收单数据
+            $receiveExtraData = [
+                'orderId'       => $orderData['id'], // 销售出库单对应的应收单订单id为销售订单id
+                'customerId'    => $orderData['customerId'],
+                'customerName'  => $orderData['customerName'],
+                'sourceNo'      => $orderData['no'],
+                'receiveMoney'  => $inventoryOutData['amount'],
+                'notOffsetMoney'=> $inventoryOutData['amount'],
+                'discountMoney' => 0,
+                'receiptTypeId' => StatusCode::$orderType['saleOrder'],
+
+            ];
+            // 创建应收单数据
+            $receiveData = [
+                'shopId'        => $orderData['shopId'],
+                'shopName'      => $orderData['shopName'],
+                'financeTypeId' => StatusCode::$orderType['saleOut'],
+                'financeType'   => '销售单',
+                'auditStatus'   => StatusCode::$auditStatus['auditing'],
+                'createTime'    => time(),
+                'updateTime'    => time(),
+            ];
+        }
+
+
+        //销售退货入库生成应收
+        if ($params['type'] == StatusCode::$orderType['saleReturnIn']) {
+            // 查询销售退货入库单信息
+            $this->objDInventoryIn->setTable('qianniao_inventory_in_' . $params['enterpriseId']);
+            $inventoryInData = $this->objDInventoryIn->get(['id' => $params['id']]);
+            if ($inventoryInData === false) {
+                echo 'sql错误' . $this->objDInventoryIn->error() . PHP_EOL;
+                return false;
+            }
+
+            if (empty($inventoryInData)) {
+                echo '销售退货-入库单id:' . $params['id'] . '的数据为空' . PHP_EOL;
+                return false;
+            }
+
+            //源销售订单的信息
+            $tableName = $this->objDOrder->getTableName('qianniao_order_' . $params['enterpriseId'], $params['userCenterId'], $this->cutTable);
+            $this->objDOrder->setTable($tableName);
+            $orderData = $this->objDOrder->get(['id' => $inventoryInData['originId']]);
+            if ($orderData === false) {
+                echo 'sql错误' . $this->objDOrder->error() . PHP_EOL;
+                return false;
+            }
+
+            if (empty($orderData)) {
+                echo '源销售订单id:' . $inventoryInData['originId'] . '的数据为空' . PHP_EOL;
+                return false;
+            }
+
+            $receiveExtraData = [
+                'orderId'       => $inventoryInData['sourceId'], // 销售退货应收订单id为销售退货单id
+                'sourceNo'      => $inventoryInData['sourceNo'],
+                'customerId'    => $orderData['customerId'],
+                'customerName'  => $orderData['customerName'],
+                'receiveMoney'  => '-' . $inventoryInData['amount'],
+                'discountMoney' => 0.00,
+                'receiptTypeId' => StatusCode::$orderType['saleReturn'],
+                'notOffsetMoney'=>'-' . $inventoryInData['amount'],
+            ];
+            // 创建应收单数据
+            $receiveData = [
+                'shopId'        => $orderData['shopId'],
+                'shopName'      => $orderData['shopName'],
+                'financeTypeId' => StatusCode::$orderType['saleOut'],
+                'financeType'   => '销售退款单',
+                'auditStatus'   => StatusCode::$auditStatus['auditing'],
+                'createTime'    => time(),
+                'updateTime'    => time(),
+            ];
+        }
+        
+
+        $receiveData = array_merge($receiveData, $receiveExtraData);
+        // 添加应收单
+        $beginTransactionStatus = $this->objDReceive->beginTransaction();
+        $this->objDReceive->setTable('qianniao_receive_receipt_' . $params['enterpriseId'] . '_' . date('Y') . '_' . ceil(date('m') / 3));
+        $dbResult =  $this->objDReceive->get('createTime >='.strtotime(date('Ymd'.'0:0:0')), 'no', 'createTime desc');
+        if ($dbResult === false) {
+            echo 'sql错误' . $this->objDReceive->error() . PHP_EOL;
+            return false;
+        }
+        if(empty($dbResult)){
+            $receiveData['no'] =  createSerialNumberByDate('');
+        }else{
+            $receiveData['no'] =  createSerialNumberByDate($dbResult['no']);
+        }
+
+        //索引表数据
+        $indexData = [
+            'receiveReceiptId' => 0,
+            'customerId'       => $receiveData['customerId'],
+            'sourceNo'         => $receiveData['sourceNo'],
+            'auditStatus'      => $receiveData['auditStatus'],
+            'financeTypeId'    => $receiveData['financeTypeId'],
+            'financeType'      => $receiveData['financeType'],
+            'shopId'           => $receiveData['shopId'],
+            'createTime'       => $receiveData['createTime'],
+            'updateTime'       => $receiveData['updateTime'],
+        ];
+        $this->objDReceiveReceiptIndex->setTable('qianniao_receive_receipt_index_' . $params['enterpriseId']);
+        $receiveReceiptId = $this->objDReceiveReceiptIndex->insert($indexData);
+        if ($receiveReceiptId === false) {
+            $this->objDReceive->rollBack();
+            echo 'sql错误' . $this->objDReceiveReceiptIndex->error() . PHP_EOL;
+            return false;
+        }
+
+        //判断收款金额是否为负数,核销状态直接给5
+        $receiveData['offsetStatus'] = ($receiveData['receiveMoney']<0) ? 5 : 4;
+        $receiveData['id'] = $receiveReceiptId;
+        $dbResult = $this->objDReceive->insert($receiveData);
+        if ($dbResult === false) {
+            $this->objDReceive->rollBack();
+            echo 'sql错误' . $this->objDReceive->error() . PHP_EOL;
+            return false;
+        }
+
+        if($beginTransactionStatus){
+            $this->objDReceive->commit();
+        }
+
+        echo '数据库添加应收单成功' . PHP_EOL;
+
+        /*
+        $_id = self::createEsDocumentId($ReceiveId, $params['enterpriseId']);
+        $esData = $receiveData;
+        $esData['id'] = $ReceiveId;
+        $esData['enterpriseId'] = $params['enterpriseId'];
+        $result = $this->objDReceive->addUpSearchIndexDocument($esData, $_id);
+        if (isset($result['_shards']) && isset($result['_shards']['successful']) && $result['_shards']['successful'] == 1) {
+            echo "es操作成功";//die;
+        }else{
+            echo "es操作失败";
+            file_put_contents('/apps/logs/elasticsearch.log',date('Y-m-d H:i:s').'生成应收es错误,错误原因'.var_export($result,true).PHP_EOL,FILE_APPEND);
+        }
+
+        echo 'es添加应收单成功' . PHP_EOL;*/
+
+        // 添加应收队列缓存,计划任务自动审核应收用
+        $this->objFinanceCache->saveSalesOutReceive($params['enterpriseId'], $receiveReceiptId, $receiveData['createTime']);
+
+
+        if(!isset($params['checkOldData'])) {
+            echo '检测销售出库单是否都生成应收单了';
+            self::checkSaleOutCreateReceivable($params['enterpriseId']);
+        }
+
+        return true;
+    }
+
+    private function createEsDocumentId($receiveId, $enterpriseId)
+    {
+        $t = date('Y') . '_' . ceil(date('m') / 3);
+        return 'EnterpriseId_' . $enterpriseId . '_' . $t . '_receiveId_' . $receiveId;
+    }
+
+    /**
+     * @param $orderData
+     * @throws \Exception
+     */
+    private function getInfo($orderData)
+    {
+        // 查询订单对应店铺绑定的仓库id
+        $this->objDShop->setTable('qianniao_shop_1');
+        $warehouseId = $this->objDShop->get_field('warehouseId',['id'=>$orderData['shopId']]);
+
+        // 获取当前订单的shopId对应的仓库id
+        $this->objDWarehouse->setTable('qianniao_warehouse_' . $this->enterpriseId);
+        if ($warehouseId === false || empty($warehouseId)) {
+            echo '商铺id'. $orderData['shopId'] .'获取仓库id时出错' . $this->objDWarehouse->error() . PHP_EOL;
+            return false;
+        }
+        $warehouseId = strpos($warehouseId,',') ? explode(',', $warehouseId) : [$warehouseId];
+        $orderData['warehouseId'] = $warehouseId;
+
+        // 查询当前订单的流水记录
+        $this->objDPurchase->setTable('qianniao_purchase_' . $this->enterpriseId);//切换分表
+        $inventoryDetails = [];
+        foreach($warehouseId as $wid){
+            self::setDetailsTable($this->enterpriseId, $wid, 'qianniao_inventory_details');//切换分表
+            self::setBatchTable($this->enterpriseId, $wid, 'qianniao_inventory_batch');//切换分表
+            $dbResult = $this->objDInventoryDetails->select(['actionType' => StatusCode::$delete, 'originId' => $orderData['id']]);
+            if ($dbResult === false) {
+                echo '库存流水查询出错' . $this->objDInventoryDetails->error() . PHP_EOL;
+                return false;
+            }
+            if(!empty($dbResult)){
+                $inventoryDetails = array_merge($inventoryDetails, $dbResult);
+            }
+        }
+        if (empty($inventoryDetails)) {
+            echo '库存流水数据为空' . PHP_EOL;
+            return false;
+        }
+
+
+        self::todayGrossProfit($inventoryDetails, $orderData);
+        //self::supplierRanking($inventoryDetails, $orderData);
+    }
+
+
+
+    /**
+     * 缓存订单毛利
+     * @param $inventoryDetails
+     * @param $orderData
+     */
+    private function todayGrossProfit($inventoryDetails, $orderData)
+    {
+        $averageCostTotal = 0;
+        $batchCostTotal = 0;
+        foreach ($inventoryDetails as $detail) {
+            switch ($detail['costType']) {
+                case StatusCode::$costType['mwa']://平均值
+                    $averageCostTotal += bcmul($detail['inventoryNum'], $detail['averageCost'], 2);
+                    break;
+                case StatusCode::$costType['sp']://批次成本
+                    $batch = json_decode($detail['batch'], true);
+                    foreach ($batch as $val) {
+                        $batchCostTotal += bcmul($val['num'], $val['batchCost'], 2);
+                    }
+                    break;
+            }
+        }
+
+        //TODO(这里暂时不回写订单商品的出库成本)
+        $costTotal = bcadd($averageCostTotal, $batchCostTotal, 2);//此订单的总成本
+        $grossProfit = bcsub($orderData['payAmount'], $costTotal, 2);
+        $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayGrossProfit', $grossProfit);//订单毛利
+        $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayGrossProfit', $grossProfit, $orderData['shopId']);
+        echo '订单' . $orderData['no'] . ':毛利缓存成功' . PHP_EOL;
+    }
+
+    /**
+     * @param $inventoryDetails
+     * @param $orderData
+     */
+    private function supplierRanking($inventoryDetails, $orderData)
+    {
+        $batchNo = [];
+        foreach ($inventoryDetails as $detail) {
+            $batch = json_decode($detail['batch'], true);
+            foreach ($batch as $val) {
+                $batchNo[] = $val['batch'];
+            }
+        }
+        $fields = 'p.supplierId,p.supplierName,p.warehouseId,b.materielId,b.skuId,b.batchNo';
+        $sql = 'SELECT ' . $fields . ' FROM ' . $this->objDInventoryBatch->get_Table() . ' AS b LEFT JOIN ' . $this->objDPurchase->get_Table() . ' AS p ON b.originId=p.id WHERE b.batchNo IN(' . implode(',', $batchNo) . ')';
+        $supplier = $this->objDInventoryBatch->query($sql);
+        if ($supplier === false) {
+            echo '查询订单商品所属供应商时出错' . $this->objDInventoryBatch->error() . PHP_EOL;
+            die;
+        }
+        if (empty($supplier)) {
+            echo '查询订单商品对应供应商数据为空' . PHP_EOL;
+            die;
+        }
+
+        $allSupplier = [];
+        foreach ($supplier as $val) {
+            $allSupplier[$val['batchNo']] = $val;
+        }
+        foreach ($inventoryDetails as &$detail) {
+            $batch = json_decode($detail['batch'], true);
+            foreach ($batch as &$val) {
+                $val['supplierId'] = isset($allSupplier[$val['batch']]['supplierId']) ? $allSupplier[$val['batch']]['supplierId'] : 0;
+                $this->objOverviewCache->saveRanking($this->enterpriseId, 'supplierRanking', $val['supplierId'], $val['num']);//销量
+                $this->objOverviewCache->saveRanking($this->enterpriseId, 'supplierRanking', $val['supplierId'], $val['num'], $orderData['shopId']);
+
+                $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'supplierRanking', $val['supplierId'], $orderData['payAmount']);//销额
+                $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'supplierRanking', $val['supplierId'], $orderData['payAmount'], $orderData['shopId']);
+            }
+
+        }
+        echo '出库供应商数据统计成功' . PHP_EOL;
+    }
+
+    /**
+     * 库存批次按照企业商铺分表
+     * @param $enterpriseId
+     * @param $warehouseId
+     * @param $tableName
+     * @throws \Exception
+     */
+    public function setBatchTable($enterpriseId, $warehouseId, $tableName)
+    {
+        $tableName = $tableName . '_' . $enterpriseId . '_' . $warehouseId;
+        $this->objDInventoryBatch->setTable($tableName);
+    }
+
+
+    /**
+     * 库存流水按照仓库+季度分表
+     * @param $enterpriseId
+     * @param $warehouseId
+     * @param $tableName
+     * @throws \Exception
+     */
+    private function setDetailsTable($enterpriseId, $warehouseId, $tableName)
+    {
+        $tableName = $tableName . '_' . $enterpriseId . '_' . $warehouseId . '_' . substr(date('Y'), -2) . ceil(date('m') / 3);
+        $this->objDInventoryDetails->setTable($tableName);
+    }
+}

+ 46 - 0
Jobs/Model/MTopic/MErp.Class.php

@@ -0,0 +1,46 @@
+<?php
+/**
+ * erp相关队列业务脚本
+ */
+namespace Jobs\Model\MTopic;
+
+class MErp
+{
+    /**
+     * 锁定库存
+     * @param string $callback_url 回调地址
+     * @param string $callback_params 回调参数
+     */
+    public function lockStock($params)
+    {
+        if(!$params){
+            echo '参数值有空值'.PHP_EOL;
+            return false;
+        }
+        $callback_url = $params['callback_url'];
+        $authorization = $params['token'];
+        unset($params['callback_url']);
+        unset($params['token']);
+
+        $i = 1;
+        do{
+            $curl_option = [
+                CURLOPT_HTTPHEADER => [
+                    'Content-Type:text/plain',
+                    'Authorization:'.$authorization,
+                ],
+            ];
+            $result = request($callback_url, json_encode($params['data']), 10, $curl_option);
+            if($result['httpcode'] == 200){
+                echo '请求业务脚本成功'.PHP_EOL;
+                return true;
+            }
+
+            $i ++;
+            sleep(1);
+        }while($result['httpcode'] != 200 && $i <= 3);
+
+        echo '请求业务脚本失败'.PHP_EOL;
+        return false;
+    }
+}

+ 149 - 0
Jobs/Model/MTopic/Market/MCoupon.Class.php

@@ -0,0 +1,149 @@
+<?php
+/**
+ * 优惠券公共方法
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/12/24
+ * Time: 9:46
+ */
+
+namespace Jobs\Model\MTopic\Market;
+
+use Jobs\Dao\DCoupon;
+use Jobs\Dao\DUserCoupon;
+use Mall\Framework\Core\StatusCode;
+
+trait MCoupon
+{
+    /**
+     * @param DCoupon $object
+     * @param $selectParams
+     * @param null $extends
+     * @return bool
+     */
+    public function selectCoupon(DCoupon $object, $selectParams, $extends = null)
+    {
+        $fields = 'id,isMutex,customerIds,startTime,endTime,name,couponType,reducePrice,minPrice,remark,grantType,totalNum,allowNum,customerSourceId,useShop,mustCondition,grantStartTime,grantEndTime,applyRange,categoryCollect,brandCollect,receiveNum,goodsCollect';
+        $nowTime = time();
+        $sql = 'SELECT ' . $fields . ' FROM qianniao_coupon_' . $this->onlineEnterpriseId . ' WHERE deleteStatus=' . StatusCode::$standard . ' AND enableStatus='.StatusCode::$standard.' AND auditStatus=' . StatusCode::$auditStatus['auditPass'] . ' AND grantStartTime<' . $nowTime . ' AND grantEndTime> ' . $nowTime . ' AND totalNum>receiveNum AND grantType=' . $selectParams['grantType'].' AND couponType='.StatusCode::$couponType['commonly'];
+
+        if (!empty($extends)) {
+            $sql .= $extends;
+        }
+
+        $dbResult = $object->query($sql);
+        if ($dbResult === false) {
+            echo '优惠券查询错误' . $object->error() . PHP_EOL;
+            exit;
+        }
+        if (empty($dbResult)) {
+            echo '没有可领取的优惠券' . PHP_EOL;
+            exit;
+        }
+        return $dbResult;
+    }
+
+    /**
+     * 验证优惠券,自己可以领取那些
+     * @param DUserCoupon $object
+     * @param $coupon
+     * @param $params
+     * @return mixed
+     */
+    public function checkCoupon(DUserCoupon $object, $coupon, $params)
+    {
+        foreach ($coupon as $key => $val) {
+            $coupon[$key]['allowNum'] = $val['allowNum'];
+            if ($val['receiveNum'] >= $val['totalNum']){
+                echo '优惠券'.$val['id'].'已经领取完了'.PHP_EOL;
+                unset($coupon[$key]);
+                continue;
+            }
+            $dbResult = $object->count(['couponId' => $val['id'], 'userId' => $params['userCenterId']]);
+            if ($dbResult === false) {
+                echo '领取记录查询失败' . $object->error() . PHP_EOL;
+                exit;
+            }
+            if ($dbResult >= $val['allowNum']){
+                echo '优惠券'.$val['id'].'已经领取了'.$dbResult.'张,每人限领取'.$val['allowNum'].'张'.PHP_EOL;
+                unset($coupon[$key]);
+                continue;
+            }
+
+            //剩余数量不足每人领取数量
+            if ($val['receiveNum']+$val['allowNum'] > $val['totalNum']){
+                $rec = $val['totalNum'] - $val['receiveNum'];
+                $coupon[$key]['allowNum'] = $rec;
+            }
+        }
+
+        if (empty($coupon)) {
+            echo '优惠券都领取过了' . PHP_EOL;
+            exit;
+        }
+        return $coupon;
+    }
+
+    /**
+     * 添加领取记录
+     * @param DUserCoupon $object
+     * @param $coupon
+     * @param $params
+     */
+    public function add(DUserCoupon $object, $coupon, $params)
+    {
+        $insert = [];
+        foreach ($coupon as $key => $val) {
+            for ($i = 0;$i < $val['allowNum'];$i++){
+                $insert[] = [
+                    'couponId'        => $val['id'],
+                    'name'            => $val['name'],
+                    'remark'          => $val['remark'],
+                    'couponType'      => $val['couponType'],
+                    'reducePrice'     => $val['reducePrice'],
+                    'minPrice'        => $val['minPrice'],
+                    'startTime'       => $val['startTime'],
+                    'endTime'         => $val['endTime'],
+                    'applyRange'      => $val['applyRange'],
+                    'categoryCollect' => $val['categoryCollect'],
+                    'brandCollect'    => $val['brandCollect'],
+                    'goodsCollect'    => $val['goodsCollect'],
+                    'isExpire'        => StatusCode::$delete,
+                    'isUse'           => StatusCode::$standard,
+                    'userId'          => $params['userCenterId'],
+                    'useShop'         => $val['useShop'],
+                    'customerId'      => $params['customerId'],
+                    'source'          => $val['grantType'],
+                    'createTime'      => time(),
+                    'updateTime'      => time(),
+                    'customerIds'     => $val['customerIds'],
+                    'isMutex'         => isset($val['isMutex']) ? $val['isMutex'] : StatusCode::$standard,
+                ];
+            }
+        }
+        $dbResult = $object->insert($insert, true);
+        if ($dbResult === false) {
+            echo '操作数据库失败' . $object->error() . PHP_EOL;
+            exit();
+        }
+        echo '优惠券发送成功' . PHP_EOL;
+    }
+
+    /**
+     * @param DCoupon $object
+     * @param $coupon
+     * @param $params
+     */
+    public function receiveNumIncr(DCoupon $object, $coupon, $params,$step=1)
+    {
+        foreach ($coupon as $val) {
+            $sql = 'UPDATE qianniao_coupon_' . $this->onlineEnterpriseId . ' SET receiveNum=receiveNum+' . $val['allowNum'] . ' WHERE id=' . $val['id'];
+            $dbResult = $object->query($sql);
+            if ($dbResult === false) {
+                echo '操作数据库失败' . $object->error() . PHP_EOL;
+                exit();
+            }
+            echo '增加' . $val['id'] . '领取数量成功' . PHP_EOL;
+        }
+    }
+}

+ 57 - 0
Jobs/Model/MTopic/Market/MGrantCoupon.Class.php

@@ -0,0 +1,57 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/12/24
+ * Time: 14:43
+ */
+
+namespace Jobs\Model\MTopic\Market;
+
+use Jobs\Dao\DCoupon;
+use Jobs\Dao\DUserCoupon;
+use Mall\Framework\Core\StatusCode;
+
+class MGrantCoupon
+{
+    use MCoupon;
+
+    private $objDUserCoupon;
+
+    private $objDCoupon;
+
+    private $onlineEnterpriseId;
+
+    /**
+     * MGrantCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        echo '定向发放优惠券:' . date('Y-d-d H:i:s') . ': ';
+        $this->objDUserCoupon = new DUserCoupon();
+        $this->objDCoupon = new DCoupon();
+        $this->objDUserCoupon->setSearchIndex('user_coupon_search')->setType('user_coupon');;
+    }
+
+    /**
+     * @param $params
+     * @throws \Exception
+     */
+    public function push($params)
+    {
+        $this->onlineEnterpriseId = $params['enterpriseId'];
+        // 计算分表
+        $this->objDUserCoupon->setTable($this->objDUserCoupon->get_Table() . '_' . $params['enterpriseId']);
+        $this->objDCoupon->setTable($this->objDCoupon->get_Table() . '_' . $params['enterpriseId']);
+        $extends = '';
+        if (!empty($params['customerId'])) {
+            $extends = ' AND FIND_IN_SET(' . $params['customerId'] . ',customerIds)';
+        }
+        $coupon = self::selectCoupon($this->objDCoupon, ['grantType' => StatusCode::$grantType['grant']], $extends);
+        $checkCoupon = self::checkCoupon($this->objDUserCoupon, $coupon, $params);
+        self::add($this->objDUserCoupon, $checkCoupon, $params);
+        self::receiveNumIncr($this->objDCoupon, $checkCoupon, $params);
+    }
+
+}

+ 55 - 0
Jobs/Model/MTopic/Market/MOnlinePayCoupon.Class.php

@@ -0,0 +1,55 @@
+<?php
+/**
+ * 在线支付发放优惠券
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/12/24
+ * Time: 9:43
+ */
+
+namespace Jobs\Model\MTopic\Market;
+
+use Mall\Framework\Core\StatusCode;
+use Jobs\Dao\DCoupon;
+use Jobs\Dao\DUserCoupon;
+
+class MOnlinePayCoupon
+{
+    use MCoupon;
+
+    private $objDUserCoupon;
+
+    private $objDCoupon;
+
+    private $onlineEnterpriseId;
+
+    /**
+     * MUserCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        echo '在线支付发放优惠券:'.date('Y-d-d H:i:s').': ';
+        $this->objDUserCoupon = new DUserCoupon();
+        $this->objDCoupon = new DCoupon();
+        $this->objDUserCoupon->setSearchIndex('user_coupon_search')->setType('user_coupon');;
+    }
+
+    /**
+     * @param $params
+     * @return bool
+     * @throws \Exception
+     */
+    public function push($params)
+    {
+        $this->onlineEnterpriseId = $params['enterpriseId'];
+        // 计算分表
+        $this->objDUserCoupon->setTable($this->objDUserCoupon->get_Table() . '_' . $params['enterpriseId']);
+        $this->objDCoupon->setTable($this->objDCoupon->get_Table() . '_' . $params['enterpriseId']);
+        $extends=' AND mustCondition<=' . $params['payAmount'];
+        $coupon = self::selectCoupon($this->objDCoupon,['grantType'=>StatusCode::$grantType['onlinePay']],$extends);
+        $checkCoupon = self::checkCoupon($this->objDUserCoupon,$coupon,$params);
+        self::add($this->objDUserCoupon,$checkCoupon,$params);
+        self::receiveNumIncr($this->objDCoupon,$checkCoupon,$params);
+    }
+}

+ 52 - 0
Jobs/Model/MTopic/Market/MRegisterCoupon.Class.php

@@ -0,0 +1,52 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2019/12/23
+ * Time: 16:21
+ */
+
+namespace Jobs\Model\MTopic\Market;
+
+use Jobs\Dao\DCoupon;
+use Jobs\Dao\DUserCoupon;
+use Mall\Framework\Core\StatusCode;
+
+class MRegisterCoupon
+{
+    use MCoupon;
+
+    private $objDUserCoupon;
+
+    private $objDCoupon;
+
+    private $onlineEnterpriseId;
+
+    /**
+     * MUserCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        echo '注册发放优惠券:'.date('Y-d-d H:i:s').': ';
+        $this->objDUserCoupon = new DUserCoupon();
+        $this->objDCoupon = new DCoupon();
+        $this->objDUserCoupon->setSearchIndex('user_coupon_search')->setType('user_coupon');;
+    }
+
+    /**
+     * @param $params
+     * @throws \Exception
+     */
+    public function push($params)
+    {
+        $this->onlineEnterpriseId = $params['enterpriseId'];
+        // 计算分表
+        $this->objDUserCoupon->setTable($this->objDUserCoupon->get_Table() . '_' . $params['enterpriseId']);
+        $this->objDCoupon->setTable($this->objDCoupon->get_Table() . '_' . $params['enterpriseId']);
+        $coupon = self::selectCoupon($this->objDCoupon,['grantType'=>StatusCode::$grantType['register']]);
+        $checkCoupon = self::checkCoupon($this->objDUserCoupon,$coupon,$params);
+        self::add($this->objDUserCoupon,$checkCoupon,$params);
+        self::receiveNumIncr($this->objDCoupon,$checkCoupon,$params);
+    }
+}

+ 95 - 0
Jobs/Model/MTopic/Message/MMessage.Class.php

@@ -0,0 +1,95 @@
+<?php
+/**
+ * 消息
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2020/04/03
+ * Time: 12:20
+ */
+
+namespace Jobs\Model\MTopic\Message;
+
+
+use Mall\Framework\Core\ErrorCode;
+use Mall\Framework\Core\ResultWrapper;
+use Mall\Framework\Core\StatusCode;
+
+use Jobs\Dao\BaseDao;
+use Jobs\Dao\Message\DMessage;
+
+class MMessage
+{
+    private $enterpriseId;
+
+    private $userCenterId;
+
+    private $objDMessage;
+
+    /**
+     * MGrantCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        $this->objDMessage = new DMessage();
+        echo '库存不足预警消息:' . date('Y-d-d H:i:s') . ':' . PHP_EOL;
+    }
+
+    /**
+     * 库存不足预警
+     * @param $params
+     * @return bool
+     * @throws \Exception
+     */
+    public function inventoryNumWarning($params)
+    {
+        echo '开始执行消息提醒队列方法**************************************************************************************************************************';
+        var_dump($params);
+        $data = $params['data']['data'];
+        if(empty($params['data']['enterpriseId'])){
+            echo '企业id参数错误'.PHP_EOL;
+            return false;
+        }
+        $enterpriseId = $params['data']['enterpriseId'];
+        $this->objDMessage->setTable($this->objDMessage->get_Table().'_'.$enterpriseId);
+        //查询企业管理员
+        $sql = 'select userCenterId from qianniao_user_bind_enterprise where enterpriseId = '.$enterpriseId.' and roleType = '.StatusCode::$roleType['admin'];
+        $dbResult = $this->objDMessage->query($sql);
+        if($dbResult === false){
+            echo $this->objDMessage->error() . PHP_EOL;
+            return false;
+        }
+        if(empty($dbResult)){
+            echo '企业管理员查询失败' . PHP_EOL;
+            return false;
+        }
+        $adminId = $dbResult[0]['userCenterId'];
+
+        $insertData = [];
+        foreach($data as $value){
+            $insertData[] = [
+                'sendId' => 0,//0为系统自动发送
+                'receiveId' => $adminId,
+                'title' => '库存不足',
+                'content' => $value.'库存不足',
+                'type' => StatusCode::$messageType['inventoryNull'],
+                'receiveStatus' => StatusCode::$delete,
+                'deleteStatus' => StatusCode::$standard,
+                'sendTime' => time(),
+                'createTime' => time(),
+                'receiveTime' => null,
+            ];
+        }
+
+        unset($dbResult);
+        $dbResult = $this->objDMessage->insert($insertData, true);
+        if($dbResult === false){
+            echo $this->objDMessage->error() . PHP_EOL;
+            return false;
+        }
+        echo '添加成功' . PHP_EOL;
+        return true;
+    }
+
+
+}

+ 132 - 0
Jobs/Model/MTopic/Order/MCommissionOrder.Class.php

@@ -0,0 +1,132 @@
+<?php
+
+
+namespace Jobs\Model\MTopic\Order;
+
+
+class MCommissionOrder
+{
+    public function __construct()
+    {
+        echo '订单分销开始执行:' . date('Y-m-d H:i:s') . ':' . PHP_EOL;
+    }
+
+    /**
+     * Doc: (des="")
+     * User: XMing
+     * Date: 2020/7/28
+     * Time: 4:52 下午
+     * @param $params
+     * @return boolean
+     */
+    public function push($params)
+    {
+        echo PHP_EOL;
+        $project_domain = $params['PROJECT_DOMAIN'];
+        switch ($project_domain){
+            case 'api':
+                $ip = URL_API.'/Commission/Commission/createCommission';
+                break;
+            default:
+                $ip = DEV_URL_API.'/Commission/Commission/createCommission';
+        }
+
+        $postData = [
+            'orderId' => $params['orderId'],
+            'customerId' => $params['customerId']
+        ];
+        $post = json_encode($postData);
+        $curl_option = [
+            CURLOPT_HTTPHEADER => [
+                'Content-Type:text/plain',
+                'Authorization:'.$params['Authorization'],
+                'Token:'.$params['Token']
+            ],
+        ];
+        $result = request($ip, $post, 40, false,$curl_option);
+        print_r($result);
+        echo '成功' . PHP_EOL;
+        return true;
+    }
+
+    /**
+     * Doc: (des="订单完成")
+     * User: XMing
+     * Date: 2020/7/30
+     * Time: 6:54 下午
+     * @param $params
+     * @return bool
+     */
+    public function updateBalance($params)
+    {
+        echo PHP_EOL;
+        $project_domain = $params['PROJECT_DOMAIN'];
+        switch ($project_domain){
+            case 'api':
+                $ip = URL_API.'/Commission/Commission/updateBalance';
+                break;
+            default:
+                $ip = DEV_URL_API.'/Commission/Commission/updateBalance';
+        }
+
+        $postData = [
+            'orderId' => $params['orderId'],
+        ];
+        $post = json_encode($postData);
+        $curl_option = [
+            CURLOPT_HTTPHEADER => [
+                'Content-Type:text/plain',
+                'Authorization:'.$params['Authorization'],
+                'Token:'.$params['Token']
+            ],
+        ];
+        $result = request($ip, $post, 40, false,$curl_option);
+        echo '成功' . PHP_EOL;
+        return true;
+    }
+
+    /**
+     * Doc: (des="取消订单")
+     * User: XMing
+     * Date: 2020/7/31
+     * Time: 6:18 下午
+     * @param $params
+     * @return bool
+     */
+    public function cancelSubCommission($params)
+    {
+        echo PHP_EOL;
+        $project_domain = $params['PROJECT_DOMAIN'];
+        switch ($project_domain){
+            case 'api':
+                $ip = URL_API.'/Commission/Commission/cancelSubCommission';
+                break;
+            default:
+                $ip = DEV_URL_API.'/Commission/Commission/cancelSubCommission';
+        }
+
+        $postData = [
+            'orderId' => $params['orderId'],
+        ];
+        $post = json_encode($postData);
+        $curl_option = [
+            CURLOPT_HTTPHEADER => [
+                'Content-Type:text/plain',
+                'Authorization:'.$params['Authorization'],
+                'Token:'.$params['Token']
+            ],
+        ];
+        $result = request($ip, $post, 40, false,$curl_option);
+        print_r($result);
+        echo '成功' . PHP_EOL;
+        return true;
+    }
+
+
+
+    public function __destruct()
+    {
+        // TODO: Implement __destruct() method.
+        echo '订单分销执行结束:' . date('Y-m-d H:i:s') . ':' . PHP_EOL;
+    }
+}

+ 33 - 0
Jobs/Model/MTopic/Order/MDelayedCancelOrder.Class.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2020/4/15
+ * Time: 17:06
+ */
+
+namespace Jobs\Model\MTopic\Order;
+
+
+class MDelayedCancelOrder
+{
+    /**
+     * @var int
+     */
+    private static $ms = 10 * 1000;
+
+    public function __construct()
+    {
+        echo '订单延时自动取消:' . date('Y-m-d H:i:s') . ':' . PHP_EOL;
+    }
+
+
+    public function push($params)
+    {
+        $taskId = \Swoole\Timer::after(self::$ms, function () use ($params) {
+            print_r($params);
+            echo date('Y-m-d H:i:s') . '订单延时自动取消10s' . PHP_EOL;
+        });
+        echo '定时器id:' . $taskId . PHP_EOL;
+    }
+}

+ 125 - 0
Jobs/Model/MTopic/Order/MOrder.Class.php

@@ -0,0 +1,125 @@
+<?php
+/**
+ * 订单
+ * Created by PhpStorm.
+ * User: 小威
+ * Date: 2020/03/14
+ * Time: 17:03
+ */
+
+namespace Jobs\Model\MTopic\Order;
+
+use Jobs\Dao\BaseDao;
+use Jobs\Dao\Order\DOrder;
+use Jobs\Dao\Order\DOrderGoods;
+use Mall\Framework\Core\ErrorCode;
+use Mall\Framework\Core\ResultWrapper;
+use Mall\Framework\Core\StatusCode;
+
+class MOrder
+{
+    private $enterpriseId;
+
+    private $userCenterId;
+
+    private $objDOrder;
+
+    private $objDOrderGoods;
+
+    private $cutTable = 200000;
+
+    /**
+     * MGrantCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        $this->objDOrder = new DOrder();
+        $this->objDOrderGoods = new DOrderGoods();
+        echo '编辑订单信息:' . date('Y-d-d H:i:s') . ':' . PHP_EOL;
+    }
+
+    /**
+     * 切换分表
+     * @param $enterpriseId
+     * @param $userCenterId
+     * @throws \Exception
+     */
+    public function orderSubTable($enterpriseId, $userCenterId)
+    {
+        $tableName = $this->objDOrder->getTableName($this->objDOrder->get_Table() . '_' . $enterpriseId, $userCenterId, $this->cutTable);
+        $this->objDOrder->setTable($tableName);
+        $tableName = $this->objDOrderGoods->getTableName($this->objDOrderGoods->get_Table() . '_' . $enterpriseId, $userCenterId, $this->cutTable);
+        $this->objDOrderGoods->setTable($tableName);
+    }
+
+    /**
+     * 回写订单库存成本
+     * @param $params
+     * @return ResultWrapper
+     * @throws \Exception
+     */
+    public function backOrderOutCostPrise($params)
+    {
+        var_dump($params);
+        $params = $params['data'];
+        //调用分表
+        self::orderSubTable($params['enterpriseId'], $params['userCenterId']);
+        //查询订单
+        $dbResult = $this->objDOrder->get(['id'=>$params['originId'], 'deleteStatus' => StatusCode::$standard]);
+        if($dbResult === false){
+            echo $this->objDOrder->error() . PHP_EOL;
+            return false;
+        }
+        if(empty($dbResult)){
+            echo '订单不存在' . PHP_EOL;
+            return false;
+        }
+        unset($dbResult);
+        //查询详情
+        $dbResult = $this->objDOrderGoods->get(['orderId' => $params['originId'], 'deleteStatus' => StatusCode::$standard, 'returnStatus' => StatusCode::$orderReturn['notReturn']]);
+        if($dbResult === false){
+            echo $this->objDOrderGoods->error() . PHP_EOL;
+            return false;
+        }
+        if(empty($dbResult)){
+            echo '商品数据为空' . PHP_EOL;
+            return false;
+        }
+        unset($dbResult);
+        foreach($params['stock'] as $skuId => $value){
+            //判断是那种计算成本方式
+            if($params['costType'] == StatusCode::$costType['mwa']){
+                //移动加权
+                $costPrise = $value['averageCost'];
+            }elseif($params['costType'] == StatusCode::$costType['sp']){
+                //批次成本
+                //计算平均值
+                $prise = 0;
+                foreach($value['batch'] as $v){
+                    $prise = bcadd($prise,$v['batchCost'],4);
+                }
+                $count = count($value['batch']);
+                $costPrise = bcdiv($prise ,$count,4);
+            }else{
+                echo '成本计算参数错误' . PHP_EOL;
+                return false;
+            }
+            echo '$skuId='.$skuId.'  --  '.'成本方式'.$params['costType'].', 成本单价'.$costPrise.PHP_EOL;
+            //修改订单详情
+            print_r(['outCostPrice' => $costPrise, 'updateTime' => time()]);
+            print_r(['id' => $params['originId'], 'skuId' => $skuId]);
+            print_r($this->objDOrderGoods->get_Table());
+            $dbResult = $this->objDOrderGoods->update(['outCostPrice' => $costPrise, 'updateTime' => time()], ['orderId' => $params['originId'], 'skuId' => $skuId]);
+            //var_dump($dbResult);
+            if($dbResult === false){
+                echo $this->objDOrderGoods->error() . PHP_EOL;
+                return false;
+            }
+        }
+        echo '修改成功' . PHP_EOL;
+        return true;
+    }
+
+
+}

+ 217 - 0
Jobs/Model/MTopic/Order/MOrderStatistics.Class.php

@@ -0,0 +1,217 @@
+<?php
+/**
+ * 订单,后台首页缓存数据统计
+ * Created by PhpStorm.
+ * User: XiaoMing
+ * Date: 2020/1/6
+ * Time: 17:23
+ */
+
+namespace Jobs\Model\MTopic\Order;
+
+use Jobs\Cache\CustomerCache;
+use Jobs\Cache\OverviewCache;
+use Jobs\Dao\BaseDao;
+use Jobs\Dao\DGoodsBasic;
+use Jobs\Dao\Order\DOrder;
+use Jobs\Dao\Order\DOrderGoods;
+use Jobs\Dao\Order\DOrderReceive;
+
+class MOrderStatistics
+{
+    private $enterpriseId;
+
+    private $userCenterId;
+
+    private $objOverviewCache;
+
+    private $objCustomerCache;
+
+    private $objDGoodsBasic;
+
+    private $objDOrder;
+
+    private $objDOrderGoods;
+
+    private $objDOrderReceive;
+
+    private $cutTable = 200000;
+
+    /**
+     * MGrantCoupon constructor.
+     * @throws \Exception
+     */
+    public function __construct()
+    {
+        $this->objCustomerCache = new CustomerCache();
+        $this->objOverviewCache = new OverviewCache();
+        $this->objDGoodsBasic = new DGoodsBasic();
+        $this->objDOrder = new DOrder();
+        $this->objDOrderGoods = new DOrderGoods();
+        $this->objDOrderReceive = new DOrderReceive();
+        echo '统计订单信息:' . date('Y-d-d H:i:s') . ':' . PHP_EOL;
+    }
+
+    /**
+     * 订单统计项
+     * @param $params
+     * @throws \Exception
+     */
+    public function push($params)
+    {
+        if (empty($params['no'])) die('订单数据为空');
+        $this->enterpriseId = $params['enterpriseId'];
+        $this->userCenterId = $params['userCenterId'];
+        self::orderSubTable($this->objDOrder);//切换订单分表
+        self::orderSubTable($this->objDOrderGoods);//切换订单商品分表
+        self::orderSubTable($this->objDOrderReceive);//切换订单收货分表
+        $formatData = self::getOrderInfo($params);//获取订单信息
+
+        switch ($params['noticeType']) {
+            case 'create'://创建订单
+                $allOrder = $formatData['orderData']['masterOrder'];
+                foreach ($allOrder as $order) {
+                    $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'orderTotalMoney', $order['payAmount']);//下单金额
+                    $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'orderTotalMoney', $order['payAmount'], $order['shopId']);
+                }
+                break;
+            case 'audit'://确认订单
+                if(isset($formatData['orderData']['masterOrder'][0]['createTime']) && $formatData['orderData']['masterOrder'][0]['createTime'] < strtotime(date("Y-m-d",time()))){
+                    echo '这不是今天的订单, 不缓存数据___________________________________________________________________________________';
+                    break;
+                }
+                echo '进入审核订单-------------------------------------------------------------------------------------------------------';
+                //var_dump($formatData);
+                $allOrder = $formatData['orderData']['masterOrder'][0];//订单主数据
+                $allOrderGoods = self::getBasicInfo($formatData['orderData']['orderGoods']);//订单商品数据
+                $allOrderReceive = $formatData['orderData']['orderReceive'][0];//订单收货信息
+
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'orderConfirmedMoney', $allOrder['payAmount']);//营业额
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'orderConfirmedMoney', $allOrder['payAmount'], $allOrder['shopId']);
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayConfirmedOrderNum', 1);//今日订单
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayConfirmedOrderNum', 1, $allOrder['shopId']);
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'orderNumOfNotOutOfStock', 1);//未出库订单
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'orderNumOfNotOutOfStock', '1', $allOrder['shopId']);
+                $this->objCustomerCache->cacheCustomerOrderInfo($this->enterpriseId, $allOrderReceive['provinceCode'], $allOrderReceive['cityCode'], $allOrderReceive['districtCode'], $allOrder['customerId']);//下单客户数
+                $this->objCustomerCache->cacheCustomerOrderInfo($this->enterpriseId, $allOrderReceive['provinceCode'], $allOrderReceive['cityCode'], $allOrderReceive['districtCode'], $allOrder['customerId'], $allOrder['shopId']);//下单客户数
+
+                $this->objOverviewCache->saveOrderTrend($this->enterpriseId, $allOrder['payAmount'], $allOrder['buyTotal']);//趋势图订单数量
+                foreach ($allOrderGoods as $goods) {
+                    //商品的大分类
+                    $this->objOverviewCache->saveRanking($this->enterpriseId, 'categoryRanking', $goods['parentCategoryId'], $goods['buyNum']);//销量
+                    $this->objOverviewCache->saveRanking($this->enterpriseId, 'categoryRanking', $goods['parentCategoryId'], $goods['buyNum'], $allOrder['shopId']);
+                    $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'categoryRanking', $goods['parentCategoryId'], $goods['totalMoney']);//销额
+                    $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'categoryRanking', $goods['parentCategoryId'], $goods['totalMoney'], $allOrder['shopId']);
+
+                    //查询商品
+                    $this->objOverviewCache->saveRanking($this->enterpriseId, 'goodsRanking', $goods['goodsBasicId'], $goods['buyNum']);//销量
+                    $this->objOverviewCache->saveRanking($this->enterpriseId, 'goodsRanking', $goods['goodsBasicId'], $goods['buyNum'], $allOrder['shopId']);
+                    $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'goodsRanking', $goods['goodsBasicId'], $goods['totalMoney']);//销额
+                    $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'goodsRanking', $goods['goodsBasicId'], $goods['totalMoney'], $allOrder['shopId']);
+
+                    //客户
+                    $this->objOverviewCache->saveRanking($this->enterpriseId, 'customerRanking', $allOrder['customerId'], $goods['buyNum']);//销量
+                    $this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'customerRanking', $allOrder['customerId'], $goods['totalMoney']);//销售额
+                }
+
+                //供应商
+                //$this->objOverviewCache->saveRanking($this->enterpriseId, 'supplierRanking', $allOrder['supplierId'], 1);//销量
+                //$this->objOverviewCache->saveRanking($this->enterpriseId, 'supplierRanking', $allOrder['supplierId'], 1, $allOrder['shopId']);
+                //$this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'supplierRanking', $allOrder['supplierId'], $allOrder['payAmount']);//销额
+                //$this->objOverviewCache->saveSalesMoneyRanking($this->enterpriseId, 'supplierRanking', $allOrder['supplierId'], $allOrder['payAmount'], $allOrder['shopId']);
+
+                //TODO
+                $this->objCustomerCache->delCustomerAfterPlaceOrder($allOrder['customerId'], $this->enterpriseId);
+                break;
+            case 'close'://取消订单
+                $allOrder = $formatData['orderData']['masterOrder'][0];
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayCanceledOrder', 1);//取消订单数
+                $this->objOverviewCache->saveBusinessOverview($this->enterpriseId, 'todayCanceledOrder', 1, $allOrder['shopId']);
+                break;
+        }
+        echo '统计订单信息成功' . PHP_EOL;
+    }
+
+    /**
+     * @param $allOrderGoods
+     * @return mixed
+     * @throws \Exception
+     */
+    private function getBasicInfo($allOrderGoods)
+    {
+        $this->objDGoodsBasic->setTable($this->objDGoodsBasic->get_Table() . '_' . $this->enterpriseId);
+        $dbResult = $this->objDGoodsBasic->select(['id' => array_column($allOrderGoods, 'goodsBasicId')], 'categoryPath,brandId,id');
+        if ($dbResult === false) {
+            echo '查询商品信息时发生错误' . $this->objDGoodsBasic->error() . PHP_EOL;
+            die;
+        }
+        if (empty($dbResult)) echo '查询商品信息为空' . PHP_EOL;
+
+        $allGoodsInfo = [];
+        foreach ($dbResult as &$val) {
+            $categoryArr = explode(',', $val['categoryPath']);
+            $val['parentCategoryId'] = array_shift($categoryArr);
+            $allGoodsInfo[$val['id']] = $val;
+        }
+
+        foreach ($allOrderGoods as &$goods) {
+            $goods['parentCategoryId'] = isset($allGoodsInfo[$goods['goodsBasicId']]['parentCategoryId']) ? $allGoodsInfo[$goods['goodsBasicId']]['parentCategoryId'] : 0;
+            $goods['brandId'] = isset($allGoodsInfo[$goods['goodsBasicId']]['brandId']) ? $allGoodsInfo[$goods['goodsBasicId']]['brandId'] : '';
+        }
+        return $allOrderGoods;
+    }
+
+    /**
+     * 获取订单信息
+     * @param $data
+     * @return mixed
+     */
+    private function getOrderInfo($data)
+    {
+        $no = $data['no'];//订单编号
+        $orderMaster = $this->objDOrder->select(['no' => $no]);
+        if ($orderMaster === false) {
+            echo '获取订单数据时出错' . $this->objDOrder->error() . PHP_EOL;
+            die;
+        }
+        if (empty($orderMaster)) {
+            echo '获取订单数据为空' . PHP_EOL;
+            die;
+        }
+        $data['orderData']['masterOrder'] = $orderMaster;
+        $orderGoods = $this->objDOrderGoods->select(['no' => $no]);
+        if ($orderGoods === false) {
+            echo '获取订单商品数据时出错' . $this->objDOrderGoods->error() . PHP_EOL;
+            die;
+        }
+        if (empty($orderGoods)) {
+            echo '获取订单商品数据为空' . PHP_EOL;
+            die;
+        }
+        $data['orderData']['orderGoods'] = $orderGoods;
+        $orderReceive = $this->objDOrderReceive->select(['no' => $no]);
+        if ($orderReceive === false) {
+            echo '获取订单收货数据时出错' . $this->objDOrderReceive->error() . PHP_EOL;
+            die;
+        }
+        if (empty($orderReceive)) {
+            echo '获取订单收货数据为空' . PHP_EOL;
+            die;
+        }
+        $data['orderData']['orderReceive'] = $orderReceive;
+//        echo '订单数据:';
+//        print_r($data);
+        return $data;
+    }
+
+    /**
+     * 切换分表
+     * @param BaseDao $object
+     * @throws \Exception
+     */
+    public function orderSubTable($object)
+    {
+        $tableName = $object->getTableName($object->get_Table() . '_' . $this->enterpriseId, $this->userCenterId, $this->cutTable);
+        $object->setTable($tableName);
+    }
+}

+ 246 - 0
Jobs/Model/MTopic/Push/MPush.Class.php

@@ -0,0 +1,246 @@
+<?php
+/**
+ * 亿成推送队列任务
+ * Created by PhpStorm.
+ * User: phperstar
+ * Date: 2018/6/10
+ * Time: 下午3:38
+ */
+namespace Jobs\Model\MTopic\Push;
+
+use Jobs\Model\Middleware;
+
+use Jobs\Dao\DMessageTemplate;
+use Jobs\Dao\DTmsMessageTemplate;
+use Jobs\Dao\DUserMessage;
+
+class MPush
+{
+
+    private $objDMessageTemplate;
+    public function __construct()
+    {
+
+    }
+
+    /**
+     * 推送消息
+     * @param array $params 推送任务参数
+     * @param string $callback_params 回调参数
+     */
+    public  function push($params)
+    {
+        self::initDao($params['push_source']);
+
+        // 1.读取推送任务模板
+        $template_id = intval($params['push_template_id']);
+        if(!$template_id){
+            echo '未指定推送模板id'.PHP_EOL;
+            return false;
+        }
+
+        $template_data = self::getMessageTemplateById($template_id);
+        if(empty($template_data)){
+            echo '指定的推送消息不存在'.PHP_EOL.$this->objDMessageTemplate->error();
+            return false;
+        }
+
+        if($template_data['status'] != 1){
+            echo '指定的推送消息未启用'.PHP_EOL;
+            return false;
+        }
+
+        // 2.获取推送的内容
+        $message_content = self::paseTemplateContent($template_data['template_content'], $params['push_template_params']);
+
+        if($message_content){
+            // 3.开启推送
+            self::pushMessage($message_content, $template_data, $params);
+        }
+
+    }
+
+    /*
+     * 初始化库
+     */
+    public function initDao($push_source)
+    {
+        switch ($push_source){
+            case 'wuliu':
+                $this->objDMessageTemplate = new DTmsMessageTemplate('wuliu');
+                break;
+            case 'pifabbc':
+                $this->objDMessageTemplate = new DMessageTemplate('newcloud');
+                break;
+            default:
+                $this->objDMessageTemplate = new DMessageTemplate('cloud');
+                break;
+        }
+
+    }
+
+    /**
+     * 获取推送模板数据
+     * @param int $template_id 模板id
+     */
+    public function getMessageTemplateById($template_id)
+    {
+        return $this->objDMessageTemplate->get($template_id);
+    }
+
+    /**
+     * 渲染模板消息中的参数
+     * @param string $template_content 模板内容
+     * @param array  $template_params  模板参数
+     * @return string
+     */
+    public function paseTemplateContent($template_content, $template_params)
+    {
+        // 比对模板参数数量和传输过来的替换的参数数量是否一致
+        preg_match_all('/<{(.*?)}>/', $template_content, $matchs);
+
+        if(count($matchs[0]) != count($template_params)){
+            var_dump($matchs);
+            echo '要替换的模板参数数量和实际模板参数数量不一致'.PHP_EOL;
+            return false;
+        }
+
+        foreach ($template_params as $key => $value){
+            if(empty($value) && $value != ''){
+                echo '模板变量'.$key.'的值为空'.PHP_EOL;
+                return false;
+            }
+            if(!in_array($key,$matchs[1])){
+                echo '传输过来的模板变量'.$key.'不在模板中'.PHP_EOL;
+                return false;
+            }
+        }
+
+        return str_replace($matchs[0], $template_params, $template_content);
+    }
+
+    /**
+     * 开启推送
+     * @param string $message_content 推送内容
+     * @param int    $push_to_userId  推送给的用户
+     * @param array  $message_template_data 推送任务模板数据
+     */
+    public function pushMessage($message_content, $message_template_data, $params)
+    {
+        if(empty($message_content)){
+            echo '推送内容为空'.PHP_EOL;
+            return false;
+        }
+
+        $message_template_data['send_type'] = json_decode($message_template_data['send_type'],true);
+
+        $appPushData = [
+            'push_source' => $params['push_source'],
+            'pushPlatForm' => $params['pushPlatForm'],
+            'pushType' => $params['pushType'],
+            'alias' => $params['alias'],
+            'content'  => $message_content,
+            'apns_production' => $params['apns_production'],
+            'extras' => isset($params['extras']) ? $params['extras'] : [],
+        ];
+
+        foreach ($message_template_data['send_type'] as $key => $value){
+            switch($value){
+                case 1: // app 推送消息
+                    self::appPush($appPushData);
+                    break;
+                case 2: // 站内消息
+                    self::siteMessagePush($message_content, $params['push_to_userId'], $params['push_source'], $message_template_data, $params['order_id']);
+                    break;
+            }
+        }
+
+        echo '推送完成'.PHP_EOL;
+        return true;
+    }
+
+    /**
+     * 极光app推送方式
+     */
+    public function appPush($appPushData)
+    {
+
+        /*  老版请求云端
+        $i = 1;
+        do{
+            $url = 'http://devcloud.91youxian.net/v2/baseinfo/aurora/jpush?message='.$message_content.'&user_id='.$push_to_userId;
+            $result = request($url, null, 5);
+            if($result['httpcode'] != 200){
+                file_put_contents('/tmp/jipush.log',date('Y-m-d H:i:s').var_export($result,true).PHP_EOL,FILE_APPEND);
+
+                echo '请求极光推送失败'.PHP_EOL;
+            }
+
+            $i ++;
+            sleep(1);
+        }while($result['httpcode'] != 200 && $i <= 3);*/
+
+        $i = 1;
+        do{
+            switch ($appPushData['pushType']){
+                case 'all':
+                    $swResult = Middleware::getInstance('ThirdPartyService')->sendSwoole('Jpush', 'broadcastPush', $appPushData);
+                    break;
+                case 'alias':
+                    $swResult = Middleware::getInstance('ThirdPartyService')->sendSwoole('Jpush', 'aliasPush', $appPushData);
+                    break;
+            }
+
+            if( !$swResult['state'] ){
+                file_put_contents('/tmp/jipush.log',date('Y-m-d H:i:s').var_export($swResult['data'],true).PHP_EOL,FILE_APPEND);
+
+                echo '请求极光推送失败'.PHP_EOL;
+            }else{
+                $jpushResult = $swResult['data'];
+            }
+
+            $i ++;
+            sleep(1);
+        }while( !$swResult['state'] && $i <= 3);
+
+        echo '请求极光推送完成'.json_encode($jpushResult).PHP_EOL;
+        return true;
+    }
+    
+    /**
+     * 站内信推送方式
+     */
+    public function siteMessagePush($message_content, $push_to_userId, $push_source, $message_template_data, $order_id)
+    {
+        if($push_source == 'pifabbc'){
+            $objDUserMessage = new DUserMessage('pifabbc');
+        }else{
+            $objDUserMessage = new DUserMessage('bbc');
+        }
+
+        if($message_template_data['type'] == 1){
+            $order_id = 0;
+        }
+
+        $data = [
+            'message_name' => $message_template_data['template_name'],
+            'message_content' => $message_content,
+            'message_from'    => 1,
+            'message_to'      => $push_to_userId,
+            'type'            => $message_template_data['type'],
+            'create_time'     => time(),
+            'order_id'        => $order_id,
+        ];
+
+        $result = $objDUserMessage->insert($data);
+        if(!$result){
+            echo '操作数据库失败'.PHP_EOL;
+            return false;
+        }
+
+        echo '站内消息推送完成'.PHP_EOL;
+        return true;
+    }
+
+
+}

+ 107 - 0
Jobs/Model/Middleware.Class.php

@@ -0,0 +1,107 @@
+<?php
+namespace Jobs\Model;
+
+use Mall\Framework\Core\Config;
+use Mall\Framework\Core\ErrorCode;
+use Mall\Framework\Factory;
+
+class Middleware
+{
+
+    static private $instance;
+
+    private $resourceConfig;
+    private $Swoole_Client;
+
+    public function __construct($serviceName)
+    {
+        $this->resourceConfig = Config::getInstance()->get('dataResources');
+
+        if (!empty($this->resourceConfig)) {
+            $this->Swoole_Client = Factory::swoole($this->resourceConfig[$serviceName]);
+        }
+    }
+
+    /**
+     * 单例模式
+     *
+     * @param string $serviceName 服务名称
+     *
+     * @return object
+     *
+     * @throws \Exception
+     */
+    static public function getInstance($serviceName)
+    {
+        /*$serviceNameIndex = md5($serviceName);
+        if (!isset(self::$instance[$serviceNameIndex])) {
+            self::$instance[$serviceNameIndex] = new self($serviceName);
+        }
+
+        if (is_null(self::$instance[$serviceNameIndex]->resourceConfig)) {
+            throw new \Exception('instance resourceConfig is null');
+        }
+        return self::$instance[$serviceNameIndex];*/
+        return new self($serviceName);
+    }
+
+    /**
+     * 发送swoole请求 目前统一封装为json消息体传输
+     *
+     * @param string $controller 控制器
+     * @param string $action 方法
+     * @param array $params 需要的参数
+     *
+     * @return mixed
+     */
+    public function sendSwoole($controller, $action, array $params = [])
+    {
+        //请求串号
+        $serid = self::getRequestId();
+
+        $msg = $this->structureMsg($controller, $action, $params, $serid);
+        $result = $this->Swoole_Client->sendMsg($msg, $serid);
+
+        if (!empty($result)) {
+            return $result;
+        } else {
+            //todo 日志记录返回为空时得请求消息体
+
+            return [
+                'state' => false,
+                'data' => 'swoole未返回消息',
+                'errorcode' => ErrorCode::$swooleRecvError
+            ];
+        }
+    }
+
+    /**
+     * 生成请求串号
+     * @return int
+     */
+    static function getRequestId()
+    {
+        $us = strstr(microtime(), ' ', true);
+        return intval(strval($us * 1000 * 1000) . rand(100, 999));
+    }
+
+    /**
+     * 构造发送消息体
+     *
+     * @param string $controller 控制器
+     * @param string $action 方法
+     * @param array $params 需要的参数
+     * @param int   $serid  请求串号
+     *
+     * @return string
+     */
+    private function structureMsg($controller, $action, $params = [], $serid,  $uid = 0)
+    {
+        $data = json_encode([
+            'contorller' => ucfirst($controller),
+            'action' => $action,
+            'params' => $params
+        ], JSON_UNESCAPED_UNICODE);
+        return pack('NNN', strlen($data), $uid, $serid) . $data;
+    }
+}

+ 55 - 0
Jobs/Model/Queue/MBaseTopicQueue.Class.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace Jobs\Model\Queue;
+
+use Jobs\Model\Queue\MTopicQueueInterface;
+
+abstract class MBaseTopicQueue implements MTopicQueueInterface
+{
+    //队列优先级
+    const HIGH_LEVEL_1=1;
+    const HIGH_LEVEL_2=2;
+    const HIGH_LEVEL_3=3;
+    const HIGH_LEVEL_4=4;
+    const HIGH_LEVEL_5=5;
+
+    public $topics = [];
+    public $queue  = null;
+
+    public static function getConnection(array $config, $logger)
+    {
+    }
+
+    public function getTopics()
+    {
+        //根据key大到小排序,并保持索引关系
+        arsort($this->topics);
+
+        return array_values($this->topics);
+    }
+
+    public function setTopics(array $topics)
+    {
+        $this->topics = $topics;
+    }
+
+    public function push($topic, $job)
+    {
+    }
+
+    public function pop($topic)
+    {
+    }
+
+    public function len($topic)
+    {
+    }
+
+    public function close()
+    {
+    }
+
+    public function isConnected()
+    {
+    }
+}

+ 114 - 0
Jobs/Model/Queue/MRedisTopicQueue.Class.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace Jobs\Model\Queue;
+
+use Jobs\Model\Queue\MBaseTopicQueue;
+
+class MRedisTopicQueue extends MBaseTopicQueue
+{
+    private $logger =null;
+
+    /**
+     * RedisTopicQueue constructor.
+     * 使用依赖注入的方式.
+     *
+     * @param \Redis $redis
+     */
+    public function __construct(\Redis $redis, $logger)
+    {
+        $this->queue   = $redis;
+        $this->logger  = $logger;
+    }
+
+    public static function getConnection(array $config, $logger)
+    {
+        try {
+            $redis = new \Redis();
+            $redis->connect($config['host'], $config['port']);
+
+            if (isset($config['password']) && !empty($config['password'])) {
+                $redis->auth($config['password']);
+            }
+            if (isset($config['database']) && !empty($config['database'])) {
+                $redis->select($config['database']);
+            }
+
+        } catch (\Throwable $e) {
+            catchError($logger, $e);
+
+            return false;
+        } catch (\Exception $e) {
+            catchError($logger, $e);
+
+            return false;
+        }
+        $connection = new self($redis, $logger);
+
+        return $connection;
+    }
+
+    /**
+     * Push message to queue.
+     *
+     * @param [type]    $topic
+     * @param object $job
+     *
+     * @return string
+     */
+    public function push($topic, $job)
+    {
+        if (!$this->isConnected()) {
+            return '';
+        }
+
+        $this->queue->lPush($topic, serialize($job));
+
+        return $job->uuid ?: '';
+    }
+
+    public function pop($topic)
+    {
+        if (!$this->isConnected()) {
+            return;
+        }
+
+        $result = $this->queue->lPop($topic);
+
+        return !empty($result) ? unserialize($result) : null;
+    }
+
+    public function len($topic)
+    {
+        if (!$this->isConnected()) {
+            return 0;
+        }
+
+        return (int) $this->queue->lLen($topic) ?: 0;
+    }
+
+    public function close()
+    {
+        if (!$this->isConnected()) {
+            return;
+        }
+
+        $this->queue->close();
+    }
+
+    public function isConnected()
+    {
+        try {
+            $this->queue->ping();
+        } catch (\Throwable $e) {
+            catchError($this->logger, $e);
+
+            return false;
+        } catch (\Exception $e) {
+            catchError($this->logger, $e);
+
+            return false;
+        }
+
+        return true;
+    }
+}

+ 48 - 0
Jobs/Model/Queue/MTopicQueueInterface.Class.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace Jobs\Model\Queue;
+
+interface MTopicQueueInterface
+{
+    public static function getConnection(array $config, $logger);
+
+    /**
+     * @return array a array of topics
+     */
+    public function getTopics();
+
+    /**
+     * @param array $topics
+     */
+    public function setTopics(array $topics);
+
+    /**
+     * 推送队列,返回jobid字符串.
+     *
+     * @param [type]    $topic
+     * @param JobObject $job
+     *
+     * @return string
+     */
+    public function push($topic, $job);
+
+    /**
+     * 从队列拿消息.
+     *
+     * @param [type] $topic
+     *
+     * @return array
+     */
+    public function pop($topic);
+
+    /**
+     * @param $topic
+     *
+     * @return int
+     */
+    public function len($topic);
+
+    public function close();
+
+    public function isConnected();
+}

+ 33 - 0
Jobs/Model/Test/K3Curl.Class.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: ASUS
+ * Date: 2018/7/18
+ * Time: 10:53
+ */
+
+namespace Jobs\Model\Test;
+class K3Curl
+{
+    public static function MyCurlPost($url, $post_content, $cookie_jar, $isLogin)
+    {
+        $ch = curl_init($url);
+        $this_header = array(
+            'Content-Type: application/json',
+            'Content-Length: ' . strlen($post_content)
+        );
+        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $this_header);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_content);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        if ($isLogin) {
+            curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar);
+        } else {
+            curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_jar);
+        }
+        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+        $result = curl_exec($ch);
+        curl_close($ch);
+        return $result;
+    }
+}

+ 165 - 0
Jobs/Model/Test/K3Handle.Class.php

@@ -0,0 +1,165 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: ASUS
+ * Date: 2018/7/18
+ * Time: 11:00
+ */
+
+namespace Jobs\Model\Test;
+
+use Jobs\Dao\DCloudUsers;
+use Jobs\Dao\DUsersCategory;
+use Jobs\Dao\DUsersTestify;
+class K3Handle
+{
+    public function store($data,$erp_no)
+    {
+        $param = [];
+        $DGusersCategory = new DUsersCategory();
+        $param['user_id'] = $data['user_id'];
+        $param['company_name'] = $data['company_name']?:'';
+        $param['referrer_phone'] = $data['referrer_phone']?:'';
+        $param['legal_person'] = $data['legal_person']?:'';
+        $param['contact_phone'] = $data['contact_phone']?:'';
+        $param['detail_address'] = $data['company_address']?:''.$data['detail_address']?:'';
+        $param['category_id'] = $data['category_id']?:0;
+
+        if ($param['category_id']){
+            $res_data =$DGusersCategory ->get($param['category_id']);
+        }
+        $param['erp_no'] = $erp_no;
+
+        //$param['referrer_name'] = $data['referrer_name'];
+        $param['referrer_no'] = $data['referrer_no'];
+        $param['referrer_group_no'] = $data['referrer_group_no'];
+        $DGusers = new DCloudUsers();
+        if (isset($res_data)&&!empty($res_data)) {
+            $param['category_no'] = $res_data['category_no'];
+
+            //$UserCat = new UsersCategoryModel[);
+            //取出分类
+            if ($param['category_no']) {
+                $cateInfo = $DGusersCategory->get(['category_no' => $param['category_no']]);
+                $id = $cateInfo['pid'];
+                $cateInfo2 = $DGusersCategory->get($id);
+                if ($cateInfo2) {
+                    $id = $cateInfo2['pid'];
+                    $cateInfo1 = $DGusersCategory  -> get($id);
+                    if ($cateInfo1) {
+                        $category_no2 = $cateInfo2['category_no'];
+                        $category_no1 = $cateInfo1['category_no'];
+                        $category_no3 = $param['category_no'];
+                    } else {
+                        $category_no1 = $cateInfo2['category_no'];
+                        $category_no2 = $param['category_no'];
+                        $category_no3 = '';
+                    }
+                } else {
+                    $category_no1 = $param['category_no'];
+                    $category_no2 = '';
+                    $category_no3 = '';
+                }
+            }
+        }else{
+
+            $res_uesr =$DGusers ->get($param['user_id']);
+            if (!empty($res_uesr)){
+                return $response = [
+                    'code' =>500,
+                ];
+                file_put_contents('K3_sync_empty_erp_no.log','法人;客户手机号;联系电话,详细地址'.PHP_EOL.$param['legal_person'] .';'.$res_uesr['phone'].';'.$param['contact_phone'].';'.$param['detail_address'].PHP_EOL,FILE_APPEND);
+            }else{
+                return $response = [
+                    'code' =>500,
+                ];
+            }
+
+        }
+
+        if ($param['referrer_group_no']){
+            $k3Result = $this ->syncCustomer(isset($category_no1)?$category_no1:'', $param, isset($category_no2)?$category_no2:'', isset($category_no3)?$category_no3:'',$data['id']);
+            if ($k3Result['code']!=200){
+                return ['code' =>500,'msg'=>$k3Result['msg']];
+            }
+        }else{
+            $res_uesr =$DGusers ->get($param['user_id']);
+            file_put_contents('K3_sync_empty_referrer_no.log','法人;客户手机号;联系电话,详细地址'.PHP_EOL.$param['legal_person'] .';'.$res_uesr['phone'].';'.$param['contact_phone'].';'.$param['detail_address'].PHP_EOL,FILE_APPEND);
+
+            return ['code' =>500];
+        }
+
+    }
+
+    public function syncCustomer($category_no1,$param,$category_no2,$category_no3, $id=0)
+    {
+        $objectDusersTestify = new DUsersTestify();
+        $cookie_jar = './k3.ini';
+        $data = array(
+            //业务对象表单Id(必录)
+            'Model'=>[
+                'FNumber' => $param['erp_no'],
+                'FCreateOrgId'=>['FNumber' => '101'], //
+                'FUseOrgId'=>['FNumber' => '101'],
+                'FName'=>$param['legal_person'],
+                'FADDRESS'=>$param['detail_address'],
+                'FTEL'=>$param['contact_phone'],
+                'FSALDEPTID'=>['FNumber' =>$param['referrer_no']],
+                'FSALGROUPID'=>['FNumber' =>$param['referrer_group_no']],
+                'FSELLER'=>['FNumber' =>$param['referrer_no']],
+                'FCustTypeId'=>['FNumber' =>'KHLB001_SYS'],
+                'FTRADINGCURRID'=>['FNumber' =>'PRE001'],
+                'F_PAEZ_Assistant5'=>['FNumber' =>$category_no1],
+                'F_PAEZ_Assistant6'=>['FNumber' =>$category_no2],
+                'F_PAEZ_Assistant3'=>['FNumber' =>$category_no3],
+            ],
+            'Creator' => '亿成商城'
+        );
+
+        //V($data);
+        //定义记录Cloud服务端返回的Session
+        $K3login = new K3Login();
+        $K3Curl = new K3Curl();
+        $post_content = $K3login->create_postdata(['BD_Customer',$data]);
+
+//        $url = 'http://192.168.0.135/k3cloud/'.'Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc';
+        $url = 'http://123.206.51.139/k3cloud/'.'Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc';
+        $res = $K3login->loginIfNeed();
+        //V($post_content);
+        //V($res);
+        $resultJsonSave =$K3Curl->MyCurlPost($url, $post_content, $cookie_jar, false);
+        //V($resultJsonSave);
+        file_put_contents('K3_sync_users_testify.log',date('Y-m-d H:i:s').'发送数据'.$post_content.PHP_EOL.'返回的数据:'.var_export($resultJsonSave ,true).PHP_EOL,FILE_APPEND);
+        $resultArray = json_decode($resultJsonSave, true);
+        //V($resultArray);
+        //判断是否已经有该客户
+        if ($resultArray['Result']['ResponseStatus']['IsSuccess']) {
+            $K3_id = $resultArray['Result']['Id'];
+            if ($K3_id){
+                $res = $objectDusersTestify->update(['k3_id' =>$K3_id],['id'=>$id]);
+            }
+            $response = array(
+                'code' => 200,
+                'msg' => 'K3保存成功',
+                'info' => 'K3保存成功',
+            );
+            return $response;
+        }else{
+            return  array(
+                'code' => 500,
+                'msg' => $resultArray['Result']['ResponseStatus']['Errors'][0]['Message'],
+                'info' => 'K3保存成功',
+            );
+        }
+//        if (!strpos($resultArray['Result']['ResponseStatus']['Errors'][0]['Message'], '客户,组织内编码唯一')) {
+//            $response = array(
+//                'code' => 500,
+//                'msg' => $resultArray['Result']['ResponseStatus']['Errors'][0]['Message'],
+//                'info' => 'K3:' . $resultArray['Result']['ResponseStatus']['Errors'][0]['Message'],
+//            );
+//            return $response;
+//        }
+
+
+        }
+    }

+ 54 - 0
Jobs/Model/Test/K3login.Class.php

@@ -0,0 +1,54 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: ASUS
+ * Date: 2018/7/18
+ * Time: 10:50
+ */
+
+namespace Jobs\Model\Test;
+
+
+class K3Login
+{
+
+    public function loginIfNeed()
+    {
+        $cookie_jar = './k3.ini';
+        $K3Curl = new K3Curl();
+        $data = array('597be128163613', '秦统业', 'Cwb20141222', '2052');        // 线上
+//        $data = array('5b499257f851c8', 'liuxin', '123456', '2052');        // 线上
+
+        $post_content = $this ->create_postdata($data);
+
+        $loginurl = 'http://123.206.51.139/k3cloud/' . 'Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc';
+//        $loginurl = 'http://192.168.0.135/k3cloud/' . 'Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc';
+        $loginResult = $K3Curl -> MyCurlPost($loginurl, $post_content, $cookie_jar, TRUE);
+        return $loginResult;
+    }
+    public function create_postdata($args){
+        $postdata = array(
+            'format' => 1,
+            'useragent' => 'ApiClient',
+            'rid' => self::create_guid(),
+            'parameters' => $args,
+            'timestamp' => time(),
+            'v' => '1.0'
+        );
+        return json_encode($postdata);
+    }
+
+    public static function create_guid()
+    {
+        $charid = strtoupper(md5(uniqid(mt_rand(), true)));
+        $hyphen = chr(45);// "-"
+        $uuid = chr(123)// "{"
+            . substr($charid, 0, 8) . $hyphen
+            . substr($charid, 8, 4) . $hyphen
+            . substr($charid, 12, 4) . $hyphen
+            . substr($charid, 16, 4) . $hyphen
+            . substr($charid, 20, 12)
+            . chr(125);// "}"
+        return $uuid;
+    }
+}

二进制
Jobs/Public/.DS_Store


+ 25 - 0
Jobs/Public/www/index.php

@@ -0,0 +1,25 @@
+<?php
+use Mall\Framework\Factory;
+use Mall\Framework\Core\Config;
+
+require_once __DIR__. DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR .'..' . DIRECTORY_SEPARATOR .'..' . DIRECTORY_SEPARATOR . 'Mall' . DIRECTORY_SEPARATOR . 'Bootstrap.php';
+// 加载项目全局变量
+require_once dirname(dirname(dirname(__FILE__))) .DS. '.ENV.php';
+
+//switch ($_SERVER['HTTP_ENV']){
+//    case 'beta':
+//        $configPath = PROJECT_PATH . DS . 'Config' . DS . 'BetaConfig.php';
+//        break;
+//    case 'master':
+//        $configPath = PROJECT_PATH . DS . 'Config' . DS . 'Config.php';
+//        break;
+//    default:
+//        $configPath = PROJECT_PATH . DS . 'Config' . DS . 'DevConfig.php';
+//}
+$configPath = PROJECT_PATH . DS . 'Config' . DS . 'Config.php';
+
+Config::load($configPath);
+
+
+// 加载框架入口文件
+Factory::request()->dispatch(false,false);

+ 23 - 0
Jobs/start.php

@@ -0,0 +1,23 @@
+<?php
+use Mall\Framework\Core\Config;
+use Jobs\Model\MConsole;
+
+require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR .  'Mall' . DIRECTORY_SEPARATOR . 'Bootstrap.php';
+
+// 加载项目全局变量
+require_once dirname(__FILE__) .DS. '.ENV.php';
+
+
+$configPath = __DIR__ . DS . 'Config' . DS . 'Config.php';
+
+if (!file_exists($configPath)) {
+    exit($configPath . 'config file is not found');
+}
+
+Config::load($configPath);
+$config = Config::getInstance()->all();
+
+$console = new MConsole($config);
+$console->run();
+//【影子:报错添加】
+Swoole\Event::wait();

+ 40 - 0
index.html

@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>恭喜,站点创建成功!</title>
+    <style>
+        .container {
+            width: 60%;
+            margin: 10% auto 0;
+            background-color: #f0f0f0;
+            padding: 2% 5%;
+            border-radius: 10px
+        }
+
+        ul {
+            padding-left: 20px;
+        }
+
+            ul li {
+                line-height: 2.3
+            }
+
+        a {
+            color: #20a53a
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <h1>恭喜, 站点创建成功!</h1>
+        <h3>这是默认index.html,本页面由系统自动生成</h3>
+        <ul>
+            <li>本页面在FTP根目录下的index.html</li>
+            <li>您可以修改、删除或覆盖本页面</li>
+            <li>FTP相关信息,请到“面板系统后台 > FTP” 查看</li>
+            <li>更多功能了解,请查看<a href="https://www.bt.cn" target="_blank">宝塔官网(www.bt.cn)</a></li>
+        </ul>
+    </div>
+</body>
+</html>