DepartmentService.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * Name: 芸众商城系统
  5. * Author: 广州市芸众信息科技有限公司
  6. * Profile: 广州市芸众信息科技有限公司位于国际商贸中心的广州,专注于移动电子商务生态系统打造,拥有芸众社交电商系统、区块链数字资产管理系统、供应链管理系统、电子合同等产品/服务。官网 :www.yunzmall.com www.yunzshop.com
  7. * Date: 2021/9/22
  8. * Time: 13:37
  9. */
  10. namespace business\common\services;
  11. use business\common\models\Department;
  12. use business\common\models\DepartmentStaff;
  13. use Illuminate\Support\Collection;
  14. use Illuminate\Support\Facades\DB;
  15. use Exception;
  16. class DepartmentService
  17. {
  18. /*
  19. * 根据方法获取可操作的部门
  20. */
  21. public static function checkDepartmentIdByMethod($method, $department_id)
  22. {
  23. $right = BusinessService::checkBusinessRight();
  24. if ($right['identity'] > 1) {
  25. return true;
  26. }
  27. if (empty($right['route_department_id'][$method])) {
  28. return false;
  29. }
  30. if (in_array($department_id, $right['route_department_id'][$method])) {
  31. return true;
  32. }
  33. return false;
  34. }
  35. /*
  36. * 删除部门
  37. */
  38. public static function deleteDepartment($department_id)
  39. {
  40. DB::beginTransaction();
  41. try {
  42. if (!$department = Department::business()->find($department_id)) {
  43. throw new Exception('部门不存在');
  44. }
  45. if ($department->level == 1) {
  46. throw new Exception('一级部门不允许删除');
  47. }
  48. if ($delete_sub_department_id = Department::getAllDepartmentSubId([$department->id])) {
  49. throw new Exception('请先删除下级部门');
  50. }
  51. if (DepartmentStaff::where('department_id', $department->id)->first()) {
  52. throw new Exception('请先移除该部门的员工');
  53. }
  54. if (!$department->delete()) {
  55. throw new Exception('部门删除失败');
  56. }
  57. if ($department->wechat_department_id && SettingService::EnabledQyWx()) {
  58. $res = (new QyWechatRequestService())->request('deleteDepartment', ['id' => $department->wechat_department_id]);
  59. if (!$res['result']) {
  60. throw new Exception($res['msg']);
  61. }
  62. }
  63. } catch (Exception $e) {
  64. DB::rollBack();
  65. return self::returnArr(0, $e->getMessage());
  66. }
  67. DB::commit();
  68. BusinessService::flush(SettingService::getBusinessId()); //清除企业缓存
  69. return self::returnArr(1, '删除部门成功');
  70. }
  71. /*
  72. * 创建/编辑部门
  73. */
  74. public static function changeDepartment($name, $parent_id = 0, $id = 0, $order = 0, $enable = 1)
  75. {
  76. DB::beginTransaction();
  77. try {
  78. $business_id = SettingService::getBusinessId();
  79. if ($parent_id) {
  80. if (!$parent_department = Department::business()->find($parent_id)) {
  81. throw new Exception('上级部门不存在');
  82. }
  83. if (SettingService::EnabledQyWx() && $parent_department->wechat_department_id == 0) {
  84. throw new Exception('上级部门未与企业微信关联');
  85. }
  86. } else {
  87. if (!$id && Department::business()->where('level', 1)->first()) {
  88. throw new Exception('一级部门只允许存在一个');
  89. }
  90. }
  91. $update_data = [
  92. 'name' => $name,
  93. 'parent_id' => $parent_id,
  94. 'level' => $parent_department ? $parent_department->level + 1 : 1,
  95. ];
  96. if (!$id) {
  97. if (Department::where($update_data)->first()) {
  98. throw new Exception('同一部门下不能存在名称相同的部门');
  99. }
  100. $update_data['order'] = intval($order) ?: 10000;
  101. if (!$department = Department::create(array_merge($update_data, [
  102. 'business_id' => $business_id,
  103. 'uniacid' => \YunShop::app()->uniacid,
  104. 'wechat_department_id' => 0
  105. ]))) {
  106. throw new Exception('创建部门失败');
  107. }
  108. } else {
  109. if (!$department = Department::business()->find($id)) {
  110. throw new Exception('部门不存在');
  111. }
  112. if (intval($order)) $update_data['order'] = intval($order);
  113. $department->fill($update_data);
  114. $department->save();
  115. }
  116. if (SettingService::EnabledQyWx() && $enable) { //如果开启了企业微信设置,进行推送
  117. $res = self::pushDepartment($department);
  118. if (!$res['result']) {
  119. throw new Exception($res['msg']);
  120. }
  121. }
  122. } catch (Exception $e) {
  123. DB::rollBack();
  124. return self::returnArr(0, $e->getMessage());
  125. }
  126. DB::commit();
  127. BusinessService::flush(SettingService::getBusinessId()); //清除企业缓存
  128. return self::returnArr(1, '成功');
  129. }
  130. /*
  131. * 推送部门到企业微信
  132. */
  133. public static function pushDepartment(Department $department)
  134. {
  135. try {
  136. if ($department->level == 1 && !$department->wechat_department_id) {
  137. $first_department = (new QyWechatRequestService())->request('getDepartmentList');
  138. foreach ($first_department['data']['department'] as $v) {
  139. if ($v['parentid'] == 0 && $v['name'] == $department->name) {
  140. $department->wechat_department_id = $v['id'];
  141. $department->save();
  142. break;
  143. }
  144. }
  145. if (!$department->wechat_department_id) {
  146. throw new Exception('一级部门未与企业微信关联');
  147. }
  148. }
  149. if ($department->level != 1 && !$department->hasOneParentDepartment->wechat_department_id) {
  150. throw new Exception($department->name . '的上级部门未与企业微信关联');
  151. }
  152. $request_data = [
  153. 'id' => $department->wechat_department_id ?: 0,
  154. 'name' => $department->name,
  155. 'parent_id' => $department->hasOneParentDepartment->wechat_department_id ?: 0,
  156. 'order' => $department->order,
  157. ];
  158. //判断是创建同步 还是 编辑同步
  159. $function = $request_data['id'] ? 'updateDepartment' : 'createDepartment';
  160. $res = (new QyWechatRequestService())->request($function, $request_data);
  161. if (!$res['result']) {
  162. throw new Exception($res['msg']);
  163. }
  164. if ($function == 'createDepartment') {
  165. $department->wechat_department_id = $res['data']['id'];
  166. $department->save();
  167. }
  168. } catch (Exception $e) {
  169. return self::returnArr(0, $e->getMessage());
  170. }
  171. return self::returnArr(1, '推送部门成功');
  172. }
  173. /*
  174. * 给部门添加权限数据
  175. */
  176. public static function addDepartmentPremission($data, &$right = [], $parent_name = '', &$count = [])
  177. {
  178. if (!$count) {
  179. $count = DepartmentStaff::business()->select(DB::raw('COUNT(distinct staff_id) as count'), 'department_id')->groupBy('department_id')->get()->toArray();
  180. $count = array_column($count, 'count', 'department_id');
  181. }
  182. $function_arr = ['createDepartment', 'updateDepartment', 'deleteDepartment', 'getStaffList', 'createStaff', 'updateStaff'];
  183. if (!$right) {
  184. $right = BusinessService::checkBusinessRight();
  185. }
  186. foreach ($data as &$v) {
  187. $v['staff_count'] = $count[$v['id']] ?: 0;
  188. $v['parent_name'] = $parent_name;
  189. $v['premission']['setDepartmentLeader'] = $right['identity'] > 1 ? 1 : 0;
  190. foreach ($function_arr as $vv) {
  191. if ($right['identity'] > 1) {
  192. $v['premission'][$vv] = 1;
  193. } else {
  194. $v['premission'][$vv] = in_array($v['id'], $right['route_department_id'][$vv]) ? 1 : 0;
  195. }
  196. }
  197. $v['create_staff_disabled'] = $v['premission']['createStaff'] ? false : true;
  198. $v['update_staff_disabled'] = $v['premission']['updateStaff'] ? false : true;
  199. $v['create_department_disabled'] = $v['premission']['createDepartment'] ? false : true;
  200. if ($v['has_one_sub_department']) {
  201. $v['has_one_sub_department'] = self::addDepartmentPremission($v['has_one_sub_department'], $right, $v['name'], $count);
  202. }
  203. }
  204. return $data;
  205. }
  206. /*
  207. * 获取部门列表
  208. */
  209. public static function getDepartmentList($parent_id = 0)
  210. {
  211. if (!$business_id = SettingService::getBusinessId()) {
  212. return self::returnArr(0, '请先选择要管理的企业');
  213. }
  214. $where = [['business_id', $business_id],];
  215. if ($parent_id) {
  216. if (!$parent_department = Department::uniacid()->where($where)->find($parent_id)) {
  217. return self::returnArr(0, '部门不存在');
  218. }
  219. $where[] = ['level', '>', $parent_department->level];
  220. }
  221. $department_list = Department::uniacid()->where($where)->orderBy('order', 'DESC', 'id', 'ASC')
  222. ->select('id', 'business_id', 'name', 'level', 'parent_id', 'wechat_department_id', 'order')->get();
  223. $return_data = [];
  224. if ($parent_department) {
  225. $return_data[] = $parent_department->toArray();
  226. } elseif ($department_list->isNotEmpty()) {
  227. $return_data = $department_list->where('level', 1)->values()->toArray();
  228. }
  229. $department_list = $department_list->toArray();
  230. foreach ($return_data as $k => $v) {
  231. $return_data[$k]['has_one_sub_department'] = self::foreachDepartment($department_list, $v['id']);
  232. }
  233. return self::returnArr(1, '成功', $return_data);
  234. }
  235. /*
  236. * 递归获取部门列表下级(不使用集合,很慢)
  237. */
  238. public static function foreachDepartment(&$department_list, $id)
  239. {
  240. $res = [];
  241. foreach ($department_list as $k => $v) {
  242. if ($v['parent_id'] == $id) {
  243. unset($department_list[$k]);
  244. $v['has_one_sub_department'] = static::foreachDepartment($department_list, $v['id']);
  245. if (empty($v['has_one_sub_department'])) {
  246. unset($v['has_one_sub_department']);
  247. }
  248. $res[] = $v;
  249. }
  250. }
  251. return $res;
  252. }
  253. /*
  254. * 获取所有下级部门id(包括当前)
  255. */
  256. public static function getDepartmentChildIds($department_ids)
  257. {
  258. $department_list = Department::business()->select('id', 'name', 'level', 'parent_id')->get();
  259. $check_department_list = $department_list->whereIn('id', $department_ids);
  260. $group_department_list = $department_list->groupBy('level');
  261. static::$department_ids = array();
  262. unset($department_list);
  263. foreach ($check_department_list as $department) {
  264. static::recursionDown($department, $group_department_list);
  265. }
  266. $ids = array_values(array_filter(array_unique(static::$department_ids)));
  267. static::$department_ids = array();
  268. return $ids;
  269. }
  270. static $department_ids = array();
  271. public static function recursionDown(Department $department, Collection $groupList)
  272. {
  273. if (in_array($department->id, static::$department_ids)) {
  274. return static::$department_ids;
  275. }
  276. static::$department_ids[] = $department->id;
  277. if (!$group = $groupList[$department->level + 1]) {
  278. return static::$department_ids;
  279. }
  280. foreach ($group as $key => $item) {
  281. if ($item->id == $department->parent_id) {
  282. unset($group[$key]);
  283. static::recursionDown($item, $groupList);
  284. }
  285. }
  286. return static::$department_ids;
  287. }
  288. /*
  289. * 从企业微信同步部门列表
  290. */
  291. public static function refreshDepartment($business_id = 0)
  292. {
  293. try {
  294. if (!$business_id = $business_id ?: SettingService::getBusinessId()) {
  295. throw new Exception('请先选择要管理的企业');
  296. }
  297. $class = new QyWechatRequestService();
  298. $res = $class->request('getDepartmentList');
  299. if (!$res['result']) {
  300. throw new Exception($res['msg']);
  301. }
  302. /*删除部门*/
  303. $all_department_id_list = array_column($res['data']['department'], 'id');
  304. Department::business($business_id)->where('wechat_department_id', '<>', 0)->whereNotIn('wechat_department_id', $all_department_id_list)->delete();
  305. /*删除部门*/
  306. if ($department = $res['data']['department']) {
  307. $department = self::formWechatDepartment($department);
  308. foreach ($department as $k => $v) {
  309. foreach ($v as $kk => $vv) {
  310. $is_create = false;
  311. $this_isset_department = Department::business($business_id)->with('hasOneParentDepartment')
  312. ->where('wechat_department_id', $vv['id'])->first();
  313. if ($this_isset_department) { //判断是否存在已绑定了微信部门并且上级id关联正确的数据
  314. if (($this_isset_department->hasOneParentDepartment->wechat_department_id != $vv['parentid'] && $vv['parentid'] != 0)) {
  315. if (!$true_parent_department = Department::business($business_id)->where('wechat_department_id', $vv['parentid'])->first()) {
  316. $this_isset_department->wechat_department_id = 0;
  317. $this_isset_department->save();
  318. $is_create = true;
  319. unset($this_isset_department);
  320. } else {
  321. $old_level = $this_isset_department->level;
  322. $new_level = $true_parent_department->level + 1;
  323. $change_level = $new_level - $old_level;
  324. $this_isset_department->parent_id = $true_parent_department->id;
  325. $this_isset_department->save();
  326. if ($change_level != 0) {
  327. $sub_level_id = Department::getAllDepartmentSubId([$this_isset_department->id]);
  328. Department::whereIn('id', array_merge([$this_isset_department->id], $sub_level_id))->update([
  329. 'level' => DB::raw("level + {$change_level}")
  330. ]);
  331. }
  332. }
  333. } elseif ($vv['parentid'] == 0 && $this_isset_department->hasOneParentDepartment) {
  334. $this_isset_department->wechat_department_id = 0;
  335. $this_isset_department->save();
  336. $is_create = true;
  337. unset($this_isset_department);
  338. }
  339. } else {
  340. $is_create = true;
  341. }
  342. if (!$is_create) { //如果存在已绑定了微信部门并且上级id关联正确的数据
  343. $this_isset_department->name = $vv['name'];
  344. $this_isset_department->order = $vv['order'] ?: 1;
  345. $this_isset_department->save();
  346. continue;
  347. }
  348. $where = [
  349. ['name', 'like', $vv['name']],
  350. ['level', $vv['level']]
  351. ];
  352. $this_isset_departments = Department::uniacid()->with('hasOneParentDepartment')
  353. ->where('business_id', SettingService::getBusinessId())
  354. ->where($where)->get();
  355. if ($this_isset_departments->isNotEmpty()) { //判断是否存在层级相同、名称相同 并且 没有关联微信部门 并且 微信上级id正确的部门
  356. $is_break = false;
  357. $this_isset_departments->each(function ($value) use (&$is_break, $vv) {
  358. if (!$is_break && ($vv['parentid'] == $value->hasOneParentDepartment->wechat_department_id || $vv['parentid'] == 0)) {
  359. $value->wechat_department_id = $vv['id'];
  360. $value->order = $vv['order'];
  361. $value->save();
  362. $is_break = true;
  363. }
  364. });
  365. if ($is_break) {
  366. continue;
  367. }
  368. }
  369. if ($vv['parentid']) {
  370. $parent = Department::business($business_id)->where('wechat_department_id', $vv['parentid'])->first();
  371. $parent_id = $parent->id ?: 0;
  372. } else {
  373. $parent_id = 0;
  374. $department = Department::business($business_id)->where('level', 1)->first();
  375. if ($department) {
  376. $department->name = $vv['name'] ?: '';
  377. $department->en_name = $vv['en_name'] ?: '';
  378. $department->order = $vv['order'];
  379. $department->wechat_department_id = $vv['id'];
  380. $department->save();
  381. continue;
  382. // throw new Exception('只能存在1个一级部门,请将一级部门名称修改为与企业微信一级部门(' . $vv['name'] . ')一致再尝试同步');
  383. }
  384. }
  385. Department::create([
  386. 'uniacid' => \YunShop::app()->uniacid,
  387. 'business_id' => $business_id,
  388. 'name' => $vv['name'] ?: '',
  389. 'en_name' => $vv['en_name'] ?: '',
  390. 'level' => $vv['level'],
  391. 'parent_id' => $parent_id,
  392. 'order' => $vv['order'],
  393. 'wechat_department_id' => $vv['id']
  394. ]);
  395. }
  396. }
  397. }
  398. BusinessService::flush(SettingService::getBusinessId()); //清除企业缓存
  399. } catch (Exception $e) {
  400. return self::returnArr(0, $e->getMessage());
  401. }
  402. return self::returnArr(1, '成功');
  403. }
  404. /*
  405. * 组装企业微信接口返回的部门列表
  406. */
  407. public static function formWechatDepartment($department)
  408. {
  409. $return_data = [];
  410. $all_data = [];
  411. do {
  412. foreach ($department as $k => $v) {
  413. if ($v['parentid'] == 0) {
  414. $v['level'] = 1;
  415. $return_data[$v['level']][] = $all_data[$v['id']] = $v;
  416. unset($department[$k]);
  417. } else {
  418. if (isset($all_data[$v['parentid']])) {
  419. $v['level'] = $all_data[$v['parentid']]['level'] + 1;
  420. $return_data[$v['level']][] = $all_data[$v['id']] = $v;
  421. unset($department[$k]);
  422. }
  423. }
  424. }
  425. } while (count($department) != 0);
  426. return $return_data;
  427. }
  428. public static function returnArr($result, $msg = '', $data = [])
  429. {
  430. return ['result' => $result, 'msg' => $msg, 'data' => $data];
  431. }
  432. // 递归获取当前部门所有下级id
  433. public static function getDepartmentIds($department_id = 0, $is_identity = false)
  434. {
  435. static $ids = array();
  436. $model = Department::business()->select('id');
  437. if (!$department_id) {
  438. $model = $model->where(['level' => 1, 'parent_id' => 0])->get();
  439. } else {
  440. $model = $model->where('parent_id', $department_id)->get();
  441. }
  442. if ($model->isNotEmpty()) {
  443. // $ids = array_unique(array_merge($ids,$model->pluck('id')->toArray()));
  444. foreach ($model as $v) {
  445. if ($is_identity) {
  446. if (!DepartmentService::checkDepartmentIdByMethod('getStaffList', $v->id)) {
  447. continue;
  448. }
  449. }
  450. $ids[] = $v->id;
  451. self::getDepartmentIds($v->id, $is_identity);
  452. }
  453. }
  454. return array_unique($ids);
  455. }
  456. }