CheckService.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <?php
  2. namespace App\Service;
  3. use App\Model\Construction;
  4. use App\Model\ConstructionProductInfo;
  5. use App\Model\InOutRecord;
  6. use App\Model\InvoiceOrder;
  7. use App\Model\InvoiceOrderInfo;
  8. use App\Model\KqLeave;
  9. use App\Model\KqOvertime;
  10. use App\Model\OrderOperation;
  11. use App\Model\PaymentReceipt;
  12. use App\Model\PaymentReceiptInfo;
  13. use App\Model\ProductInventory;
  14. use App\Model\ProductInventorySet;
  15. use App\Model\PurchaseOrder;
  16. use App\Model\PurchaseOrderInfo;
  17. use App\Model\PurchaseOrderSpecial;
  18. use App\Model\PurchaseOrderSpecialInfo;
  19. use App\Model\ReturnExchangeOrder;
  20. use App\Model\ReturnExchangeOrderProductInfo;
  21. use App\Model\SalesOrder;
  22. use App\Model\SalesOrderInfo;
  23. use App\Model\SalesOrderOtherFee;
  24. use App\Model\SalesOrderProductInfo;
  25. use App\Model\SeeRange;
  26. use App\Model\SportsBag;
  27. use App\Model\Storehouse;
  28. use App\Model\Supplier;
  29. use App\Service\OaService;
  30. use Illuminate\Support\Facades\DB;
  31. class CheckService extends Service
  32. {
  33. //特殊操作数
  34. const minus_one = -1;//跳出库存流水
  35. //审批操作对应的数值
  36. const one = 1;
  37. const two = 2;
  38. const three = 3;
  39. const four = 4;
  40. const five = 5;
  41. const six = 6;
  42. const seven = 7;
  43. const eight = 8;
  44. const nine = 9;
  45. const ten = 10;
  46. const eve = 11;
  47. const twl = 12;
  48. //中文对照
  49. public $map = [
  50. self::one => '请假申请',
  51. self::two => '加班申请',
  52. self::three => '',
  53. self::four => '',
  54. self::five => '',
  55. self::six => '',
  56. self::seven => '',
  57. self::eight => '',
  58. self::nine => '',
  59. self::ten => '',
  60. self::eve => '',
  61. self::twl => '',
  62. ];
  63. //入库操作
  64. public static $in_opt = [
  65. ];
  66. //出库操作
  67. public static $out_opt = [
  68. ];
  69. const TYPE_ONE = 1;//通过
  70. const TYPE_TWO = 2;//不通过
  71. const TYPE_THREE = 3;//通过后驳回
  72. //改为待审核状态
  73. public static $opt_1case = [
  74. self::one => 'leave',
  75. self::two => 'overtime',
  76. ];
  77. //改为最终状态
  78. public static $opt_case = [
  79. self::one => 'leave_final',
  80. self::two => 'overtime_final',
  81. ];
  82. //审核通过后 弃审
  83. public static $opt_case_reject = [
  84. ];
  85. //直接完成
  86. public static $finished = [
  87. ];
  88. //单据库存流水
  89. public static $record = [
  90. ];
  91. //审核通过后 驳回 产生流水
  92. public static $reject_record = [
  93. ];
  94. //旅程日志 同意
  95. public static $operation_order = [
  96. self::eight => OrderOperation::three,
  97. ];
  98. //旅程日志 驳回
  99. public static $operation_order_reject = [
  100. self::four => OrderOperation::four,
  101. ];
  102. //以下具体方法----------------------------------------------------------------------------------------
  103. //改为待审核---------------------------------
  104. public function leave($data){
  105. $model = KqLeave::where('order_number',$data['order_number'])
  106. ->where('del_time',0)
  107. ->first();
  108. if(empty($model)) return [false, '请假申请不存在或已被删除'];
  109. if($model->state != KqLeave::STATE_ZERO) return [false, '请确认请假申请状态,操作失败'];
  110. KqLeave::where('del_time',0)
  111. ->where('id',$data['id'])
  112. ->update(['state' => KqLeave::STATE_ONE]);
  113. return [true, $model->toArray()];
  114. }
  115. public function overtime($data){
  116. $model = KqOvertime::where('order_number',$data['order_number'])
  117. ->where('del_time',0)
  118. ->first();
  119. if(empty($model)) return [false, '加班申请不存在或已被删除'];
  120. if($model->state != KqOvertime::STATE_ZERO) return [false, '请确认加班申请状态,操作失败'];
  121. KqOvertime::where('del_time',0)
  122. ->where('id',$data['id'])
  123. ->update(['state' => KqOvertime::STATE_ONE]);
  124. return [true, $model->toArray()];
  125. }
  126. //改为待审核---------------------------------
  127. //改为最终结果---------------------------------
  128. public function leave_final($data){
  129. $model = KqLeave::where('order_number',$data['order_number'])
  130. ->where('del_time',0)
  131. ->first();
  132. if(empty($model)) return [false, '请假申请不存在或已被删除'];
  133. if($model->state != KqLeave::STATE_ONE) return [false, '请确认请假申请的状态,操作失败'];
  134. if($data['type'] == self::TYPE_ONE){
  135. //通过
  136. $model->state = KqLeave::STATE_TWO;
  137. $model->save();
  138. }else{
  139. //驳回
  140. $model->state = KqLeave::State_minus_one;
  141. $model->save();
  142. }
  143. return [true, $model->toArray()];
  144. }
  145. public function overtime_final($data){
  146. $model = KqOvertime::where('order_number',$data['order_number'])
  147. ->where('del_time',0)
  148. ->first();
  149. if(empty($model)) return [false, '加班申请不存在或已被删除'];
  150. if($model->state != KqLeave::STATE_ONE) return [false, '请确认加班申请的状态,操作失败'];
  151. if($data['type'] == self::TYPE_ONE){
  152. //通过
  153. $model->state = KqOvertime::STATE_TWO;
  154. $model->save();
  155. }else{
  156. //驳回
  157. $model->state = KqOvertime::State_minus_one;
  158. $model->save();
  159. }
  160. return [true, $model->toArray()];
  161. }
  162. //改为最终结果---------------------------------
  163. //通过后弃审
  164. //通过后弃审
  165. public function getOrderDetail($data,$user){
  166. if(empty($data['order_number'])) return [false,'必传参数不能为空'];
  167. $array = [];
  168. foreach (Construction::$prefix as $value){
  169. $array[$value] = "\App\Service\\ConstructionService";
  170. }
  171. foreach (ReturnExchangeOrder::$prefix as $value){
  172. $array[$value] = "\App\Service\\ReturnExchangeOrderService";
  173. }
  174. foreach (SalesOrder::$prefix as $value){
  175. $array[$value] = "\App\Service\\SalesOrderService";
  176. }
  177. $status = true;
  178. $msg = [];
  179. foreach ($array as $key => $value){
  180. if(strpos($data['order_number'],$key) !== false) {
  181. list($status, $msg) = (new $value)->detail($data);
  182. return [$status, $msg];
  183. }
  184. }
  185. if(strpos($data['order_number'],PurchaseOrder::prefix) !== false){
  186. $service = "\App\Service\\PurchaseOrderService";
  187. list($status, $msg) = (new $service)->detail($data,$user);
  188. return [$status, $msg];
  189. }
  190. return [$status, $msg];
  191. }
  192. public function checkAll($data,$user){
  193. if(empty($data['id']) || empty($data['order_number'])|| empty($data['opt_case'])) return [false,'必传参数不能为空或者参数值错误!'];
  194. list($status,$msg) = $this->limitingSendRequestBackgExpire($data['order_number'] . $data['opt_case']);
  195. if(! $status) return [false,$msg];
  196. //走审批流 单据状态改为待审批方法
  197. $function = self::$opt_1case[$data['opt_case']] ?? '';
  198. //单据不走审批流 直接完成
  199. $function2 = self::$finished[$data['opt_case']] ?? '';
  200. try{
  201. DB::beginTransaction();
  202. //不走审批流,更新完直接返回
  203. if($function2) {
  204. list($bool,$msg) = $this->$function2($data,$user);
  205. if($bool) {
  206. $order = $msg;
  207. list($bool,$err) = $this->createRecordAndInventoryMy($data,$user,$order);
  208. if($bool){
  209. DB::commit();
  210. return [true, ''];
  211. }else{
  212. DB::rollBack();
  213. return [false, $err];
  214. }
  215. }else{
  216. DB::rollBack();
  217. return [false, $msg];
  218. }
  219. }
  220. //需要审批流,从未审核变成待审核
  221. if($function){
  222. list($bool,$msg) = $this->$function($data);
  223. if(! $bool){
  224. DB::rollBack();
  225. return [false, $msg];
  226. }
  227. //生成审批流
  228. $data['option_data'] = $msg; // 操作数据信息
  229. $workFlowService = new WorkFlowService();
  230. list($bool,$msg) = $workFlowService->create($data, $user);
  231. if(! $bool) {
  232. DB::rollBack();
  233. list($s, $m) = $msg;
  234. if($s == -1) return [-1, $m];
  235. if($msg) return [false,$msg];
  236. // 指向下个需要审批人的流程
  237. $workFlowService->runWorkFlow($data['order_number']);
  238. }
  239. }
  240. DB::commit();
  241. return [true, ''];
  242. }catch (\Throwable $e){
  243. DB::rollBack();
  244. return [false, $e->getFile() . '|' . $e->getLine() . '|' . $e->getMessage()];
  245. }
  246. }
  247. //更新库存
  248. public function changeInventory($data,$order,$user){
  249. $number_symbol = "";
  250. if(in_array($data['opt_case'],self::$in_opt)){
  251. $number_symbol = ">";
  252. }elseif (in_array($data['opt_case'],self::$out_opt)){
  253. $number_symbol = "<";
  254. }
  255. //获取单据最新数据时间 正常审核的数据
  256. $latest = InOutRecord::where('del_time',0)
  257. ->where('order_number',$order['order_number'])
  258. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  259. return $query->where('number', $number_symbol,0);
  260. })
  261. ->select('crt_time')
  262. ->orderBy('crt_time', 'desc')
  263. ->first();
  264. $model = InOutRecord::where('del_time',0)
  265. ->where('order_number',$order['order_number'])
  266. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  267. return $query->where('number', $number_symbol,0);
  268. })
  269. ->select('number','crt_time','product_id','storehouse_id','top_depart_id');
  270. if(! empty($latest)) {
  271. $t = $latest->toArray();
  272. $model->where('crt_time',$t['crt_time']);
  273. }
  274. $record = $model->get()->toArray();
  275. if (empty($record)) return [false,'流水记录不存在'];
  276. $top_depart_id = Storehouse::where('id', $order['storehouse_id'])->value('top_depart_id');
  277. $result = $lock_number = [];
  278. foreach ($record as $value){
  279. $key = $value['product_id'] . $value['storehouse_id'];
  280. if(isset($result[$key])){
  281. $result[$key]['number'] += $value['number'];
  282. }else{
  283. $result[$key] = [
  284. 'product_id' => $value['product_id'],
  285. 'number' => $value['number'],
  286. 'crt_time' => $value['crt_time'],
  287. 'storehouse_id' => $value['storehouse_id'],
  288. 'top_depart_id' => $top_depart_id,
  289. ];
  290. }
  291. if($value['number'] < 0){
  292. if(isset($lock_number[$key])){
  293. $lock_number[$key] += $value['number'];
  294. }else{
  295. $lock_number[$key] = $value['number'];
  296. }
  297. }
  298. }
  299. //是否校验库存 是的话锁定数量要更新(根据当前操作人所在门店是否校验库存)
  300. $lock = $user['is_check_stock'];
  301. $result = array_values($result);
  302. foreach ($result as $key => $value){
  303. $keys = $value['product_id'] . $value['storehouse_id'];
  304. $m = ProductInventory::where('product_id',$value['product_id'])
  305. ->where('storehouse_id',$value['storehouse_id'])
  306. ->select('product_id','number','storehouse_id')
  307. ->first();
  308. if(empty($m)){
  309. ProductInventory::insert($result[$key]);
  310. }else{
  311. //锁定数量
  312. $lock_number_tmp = 0;
  313. if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
  314. ProductInventory::where('product_id',$m->product_id)
  315. ->where('storehouse_id',$m->storehouse_id)
  316. ->lockForUpdate()
  317. ->update([
  318. 'number' => DB::raw('number + ('. $value['number'] . ')'),
  319. 'lock_number' => DB::raw('lock_number + ('. $lock_number_tmp . ')')
  320. ]);
  321. }
  322. }
  323. return [true,''];
  324. }
  325. //业务单据审批通过后 驳回 更新库存
  326. public function changeInventoryReject($data,$order,$user){
  327. $number_symbol = "";
  328. if(in_array($data['opt_case'],self::$in_opt)){
  329. $number_symbol = "<";
  330. }elseif (in_array($data['opt_case'],self::$out_opt)){
  331. $number_symbol = ">";
  332. }
  333. //获取单据最新数据时间 正常审核的数据
  334. $latest = InOutRecord::where('del_time',0)
  335. ->where('order_number',$order['order_number'])
  336. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  337. return $query->where('number', $number_symbol,0);
  338. })
  339. ->select('crt_time')
  340. ->orderBy('crt_time', 'desc')
  341. ->first();
  342. $model = InOutRecord::where('del_time',0)
  343. ->where('order_number',$order['order_number'])
  344. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  345. return $query->where('number', $number_symbol,0);
  346. })
  347. ->select('number','crt_time','product_id','storehouse_id','top_depart_id');
  348. if(! empty($latest)) {
  349. $t = $latest->toArray();
  350. $model->where('crt_time',$t['crt_time']);
  351. }
  352. $record = $model->get()->toArray();
  353. if (empty($record)) return [false,'流水记录不存在'];
  354. $top_depart_id = Storehouse::where('id', $order['storehouse_id'])->value('top_depart_id');
  355. $result = $lock_number = [];
  356. foreach ($record as $value){
  357. $key = $value['product_id'] . $value['storehouse_id'];
  358. if(isset($result[$key])){
  359. $result[$key]['number'] += $value['number'];
  360. }else{
  361. $result[$key] = [
  362. 'product_id' => $value['product_id'],
  363. 'number' => $value['number'],
  364. 'crt_time' => $value['crt_time'],
  365. 'storehouse_id' => $value['storehouse_id'],
  366. 'top_depart_id' => $top_depart_id,
  367. ];
  368. }
  369. if($value['number'] > 0){
  370. if(isset($lock_number[$key])){
  371. $lock_number[$key] += $value['number'];
  372. }else{
  373. $lock_number[$key] = $value['number'];
  374. }
  375. }
  376. }
  377. //是否校验库存 是的话锁定数量要更新(根据当前操作人所在门店是否校验库存)
  378. $lock = $user['is_check_stock'];
  379. $result = array_values($result);
  380. foreach ($result as $key => $value){
  381. $keys = $value['product_id'] . $value['storehouse_id'];
  382. $m = ProductInventory::where('product_id',$value['product_id'])
  383. ->where('storehouse_id',$value['storehouse_id'])
  384. ->select('product_id','number','storehouse_id')
  385. ->first();
  386. if(empty($m)){
  387. ProductInventory::insert($result[$key]);
  388. }else{
  389. //锁定数量
  390. $lock_number_tmp = 0;
  391. if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
  392. ProductInventory::where('product_id',$m->product_id)
  393. ->where('storehouse_id',$m->storehouse_id)
  394. ->lockForUpdate()
  395. ->update([
  396. 'number' => DB::raw('number + ('. $value['number'] . ')'),
  397. 'lock_number' => DB::raw('lock_number + ('. $lock_number_tmp . ')')
  398. ]);
  399. }
  400. }
  401. return [true,''];
  402. }
  403. public function createRecordAndInventory($data = []){
  404. if(empty($data['type']) || empty($data['opt_case']) || empty($data['order_number'])) return [false, '传递参数缺少'];
  405. $user = $data['user_data'] ?? [];
  406. if($data['type'] == self::TYPE_THREE){
  407. //通过后弃审
  408. if(! isset(self::$opt_case_reject[$data['opt_case']])) return [false, '该操作不存在'];
  409. //具体方法
  410. $function = self::$opt_case_reject[$data['opt_case']];
  411. //流水
  412. $function2 = self::$reject_record[$data['opt_case']] ?? '';
  413. try{
  414. DB::beginTransaction();
  415. //更新单据的状态
  416. list($bool,$msg) = $this->$function($data);
  417. if(! $bool){
  418. DB::rollBack();
  419. return [false, $msg];
  420. }
  421. $order = $msg;
  422. if($function2) {
  423. //流水
  424. list($boolean,$msg) = $this->$function2($data,$order);
  425. if(! $boolean) {
  426. DB::rollBack();
  427. return [false, $msg];
  428. }
  429. if($msg != self::minus_one){
  430. //库存
  431. list($bool,$msg) = $this->changeInventoryReject($data,$order,$user);
  432. if(! $bool){
  433. DB::rollBack();
  434. return [false, $msg];
  435. }
  436. }
  437. }
  438. if(! empty(self::$operation_order_reject[$data['opt_case']])){
  439. $type = self::$operation_order_reject[$data['opt_case']];
  440. (new OrderOperationService())->add([
  441. 'order_number' => $order['order_number'],
  442. 'msg' => OrderOperation::$type[$type],
  443. 'type' => $type
  444. ],$user);
  445. }
  446. DB::commit();
  447. return [true, ''];
  448. }catch (\Throwable $exception){
  449. DB::rollBack();
  450. return [false, $exception->getMessage() . $exception->getLine() . $exception->getFile()];
  451. }
  452. }else{
  453. //具体方法
  454. $function = self::$opt_case[$data['opt_case']] ?? "";
  455. $record = self::$record[$data['opt_case']] ?? "";
  456. try{
  457. DB::beginTransaction();
  458. list($bool,$msg) = $this->$function($data);
  459. if(! $bool){
  460. DB::rollBack();
  461. return [false, $msg];
  462. }
  463. $order = $msg;
  464. if($data['type'] == self::TYPE_ONE){
  465. if($record) {
  466. //流水
  467. list($bool,$msg) = $this->$record($data, $order);
  468. if(! $bool) {
  469. DB::rollBack();
  470. return [false, $msg];
  471. }
  472. if($msg != self::minus_one){
  473. //库存
  474. list($bool,$msg) = $this->changeInventory($data, $order, $user);
  475. if(! $bool) {
  476. DB::rollBack();
  477. return [false, $msg];
  478. }
  479. }
  480. }
  481. }
  482. if(! empty(self::$operation_order[$data['opt_case']])){
  483. $user = $data['user_data'] ?? [];
  484. $type = self::$operation_order[$data['opt_case']];
  485. (new OrderOperationService())->add([
  486. 'order_number' => $order['order_number'],
  487. 'msg' => OrderOperation::$type[$type],
  488. 'type' => $type
  489. ],$user);
  490. }
  491. DB::commit();
  492. return [true, ''];
  493. }catch (\Throwable $exception){
  494. DB::rollBack();
  495. return [false, $exception->getMessage() . $exception->getLine() . $exception->getFile()];
  496. }
  497. }
  498. }
  499. //不需要走审批流 直接调用
  500. public function createRecordAndInventoryMy($data = [],$user = [],$order = []){
  501. if(! empty($data['type']) && $data['type'] == self::TYPE_THREE){
  502. }else{
  503. //具体方法
  504. $record = self::$record[$data['opt_case']] ?? "";
  505. try{
  506. DB::beginTransaction();
  507. if($record) {
  508. //流水
  509. list($bool,$msg) = $this->$record($data, $order);
  510. if(! $bool) {
  511. DB::rollBack();
  512. return [false, $msg];
  513. }
  514. if($msg != self::minus_one){
  515. //库存
  516. list($bool,$msg) = $this->changeInventory($data, $order, $user);
  517. if(! $bool) {
  518. DB::rollBack();
  519. return [false, $msg];
  520. }
  521. }
  522. }
  523. if(! empty(self::$operation_order[$data['opt_case']])){
  524. $type = self::$operation_order[$data['opt_case']];
  525. (new OrderOperationService())->add([
  526. 'order_number' => $order['order_number'],
  527. 'msg' => OrderOperation::$type[$type],
  528. 'type' => $type
  529. ],$user);
  530. }
  531. DB::commit();
  532. return [true, ''];
  533. }catch (\Throwable $exception){
  534. DB::rollBack();
  535. return [false, $exception->getMessage() . $exception->getLine() . $exception->getFile()];
  536. }
  537. }
  538. }
  539. }