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. $args = [
  229. 'order_no' => $data['order_number'],
  230. 'menu_id' => $data['menu_id'] ?? 0,
  231. 'opt_case' => $data['opt_case'],
  232. 'order' => $msg,
  233. ];
  234. $oa = new OaService($user);
  235. list($bool,$msg) = $oa->createOaOrder($args);
  236. if(! $bool) {
  237. DB::rollBack();
  238. if($msg) return [false,$msg];
  239. }
  240. }
  241. DB::commit();
  242. return [true, ''];
  243. }catch (\Throwable $exception){
  244. DB::rollBack();
  245. return [false, $exception->getMessage() . $exception->getFile(). $exception->getLine()];
  246. }
  247. }
  248. //更新库存
  249. public function changeInventory($data,$order,$user){
  250. $number_symbol = "";
  251. if(in_array($data['opt_case'],self::$in_opt)){
  252. $number_symbol = ">";
  253. }elseif (in_array($data['opt_case'],self::$out_opt)){
  254. $number_symbol = "<";
  255. }
  256. //获取单据最新数据时间 正常审核的数据
  257. $latest = InOutRecord::where('del_time',0)
  258. ->where('order_number',$order['order_number'])
  259. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  260. return $query->where('number', $number_symbol,0);
  261. })
  262. ->select('crt_time')
  263. ->orderBy('crt_time', 'desc')
  264. ->first();
  265. $model = InOutRecord::where('del_time',0)
  266. ->where('order_number',$order['order_number'])
  267. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  268. return $query->where('number', $number_symbol,0);
  269. })
  270. ->select('number','crt_time','product_id','storehouse_id','top_depart_id');
  271. if(! empty($latest)) {
  272. $t = $latest->toArray();
  273. $model->where('crt_time',$t['crt_time']);
  274. }
  275. $record = $model->get()->toArray();
  276. if (empty($record)) return [false,'流水记录不存在'];
  277. $top_depart_id = Storehouse::where('id', $order['storehouse_id'])->value('top_depart_id');
  278. $result = $lock_number = [];
  279. foreach ($record as $value){
  280. $key = $value['product_id'] . $value['storehouse_id'];
  281. if(isset($result[$key])){
  282. $result[$key]['number'] += $value['number'];
  283. }else{
  284. $result[$key] = [
  285. 'product_id' => $value['product_id'],
  286. 'number' => $value['number'],
  287. 'crt_time' => $value['crt_time'],
  288. 'storehouse_id' => $value['storehouse_id'],
  289. 'top_depart_id' => $top_depart_id,
  290. ];
  291. }
  292. if($value['number'] < 0){
  293. if(isset($lock_number[$key])){
  294. $lock_number[$key] += $value['number'];
  295. }else{
  296. $lock_number[$key] = $value['number'];
  297. }
  298. }
  299. }
  300. //是否校验库存 是的话锁定数量要更新(根据当前操作人所在门店是否校验库存)
  301. $lock = $user['is_check_stock'];
  302. $result = array_values($result);
  303. foreach ($result as $key => $value){
  304. $keys = $value['product_id'] . $value['storehouse_id'];
  305. $m = ProductInventory::where('product_id',$value['product_id'])
  306. ->where('storehouse_id',$value['storehouse_id'])
  307. ->select('product_id','number','storehouse_id')
  308. ->first();
  309. if(empty($m)){
  310. ProductInventory::insert($result[$key]);
  311. }else{
  312. //锁定数量
  313. $lock_number_tmp = 0;
  314. if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
  315. ProductInventory::where('product_id',$m->product_id)
  316. ->where('storehouse_id',$m->storehouse_id)
  317. ->lockForUpdate()
  318. ->update([
  319. 'number' => DB::raw('number + ('. $value['number'] . ')'),
  320. 'lock_number' => DB::raw('lock_number + ('. $lock_number_tmp . ')')
  321. ]);
  322. }
  323. }
  324. return [true,''];
  325. }
  326. //业务单据审批通过后 驳回 更新库存
  327. public function changeInventoryReject($data,$order,$user){
  328. $number_symbol = "";
  329. if(in_array($data['opt_case'],self::$in_opt)){
  330. $number_symbol = "<";
  331. }elseif (in_array($data['opt_case'],self::$out_opt)){
  332. $number_symbol = ">";
  333. }
  334. //获取单据最新数据时间 正常审核的数据
  335. $latest = InOutRecord::where('del_time',0)
  336. ->where('order_number',$order['order_number'])
  337. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  338. return $query->where('number', $number_symbol,0);
  339. })
  340. ->select('crt_time')
  341. ->orderBy('crt_time', 'desc')
  342. ->first();
  343. $model = InOutRecord::where('del_time',0)
  344. ->where('order_number',$order['order_number'])
  345. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  346. return $query->where('number', $number_symbol,0);
  347. })
  348. ->select('number','crt_time','product_id','storehouse_id','top_depart_id');
  349. if(! empty($latest)) {
  350. $t = $latest->toArray();
  351. $model->where('crt_time',$t['crt_time']);
  352. }
  353. $record = $model->get()->toArray();
  354. if (empty($record)) return [false,'流水记录不存在'];
  355. $top_depart_id = Storehouse::where('id', $order['storehouse_id'])->value('top_depart_id');
  356. $result = $lock_number = [];
  357. foreach ($record as $value){
  358. $key = $value['product_id'] . $value['storehouse_id'];
  359. if(isset($result[$key])){
  360. $result[$key]['number'] += $value['number'];
  361. }else{
  362. $result[$key] = [
  363. 'product_id' => $value['product_id'],
  364. 'number' => $value['number'],
  365. 'crt_time' => $value['crt_time'],
  366. 'storehouse_id' => $value['storehouse_id'],
  367. 'top_depart_id' => $top_depart_id,
  368. ];
  369. }
  370. if($value['number'] > 0){
  371. if(isset($lock_number[$key])){
  372. $lock_number[$key] += $value['number'];
  373. }else{
  374. $lock_number[$key] = $value['number'];
  375. }
  376. }
  377. }
  378. //是否校验库存 是的话锁定数量要更新(根据当前操作人所在门店是否校验库存)
  379. $lock = $user['is_check_stock'];
  380. $result = array_values($result);
  381. foreach ($result as $key => $value){
  382. $keys = $value['product_id'] . $value['storehouse_id'];
  383. $m = ProductInventory::where('product_id',$value['product_id'])
  384. ->where('storehouse_id',$value['storehouse_id'])
  385. ->select('product_id','number','storehouse_id')
  386. ->first();
  387. if(empty($m)){
  388. ProductInventory::insert($result[$key]);
  389. }else{
  390. //锁定数量
  391. $lock_number_tmp = 0;
  392. if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
  393. ProductInventory::where('product_id',$m->product_id)
  394. ->where('storehouse_id',$m->storehouse_id)
  395. ->lockForUpdate()
  396. ->update([
  397. 'number' => DB::raw('number + ('. $value['number'] . ')'),
  398. 'lock_number' => DB::raw('lock_number + ('. $lock_number_tmp . ')')
  399. ]);
  400. }
  401. }
  402. return [true,''];
  403. }
  404. public function createRecordAndInventory($data = []){
  405. if(empty($data['type']) || empty($data['opt_case']) || empty($data['order_number'])) return [false, '传递参数缺少'];
  406. $user = $data['user_data'] ?? [];
  407. if($data['type'] == self::TYPE_THREE){
  408. //通过后弃审
  409. if(! isset(self::$opt_case_reject[$data['opt_case']])) return [false, '该操作不存在'];
  410. //具体方法
  411. $function = self::$opt_case_reject[$data['opt_case']];
  412. //流水
  413. $function2 = self::$reject_record[$data['opt_case']] ?? '';
  414. try{
  415. DB::beginTransaction();
  416. //更新单据的状态
  417. list($bool,$msg) = $this->$function($data);
  418. if(! $bool){
  419. DB::rollBack();
  420. return [false, $msg];
  421. }
  422. $order = $msg;
  423. if($function2) {
  424. //流水
  425. list($boolean,$msg) = $this->$function2($data,$order);
  426. if(! $boolean) {
  427. DB::rollBack();
  428. return [false, $msg];
  429. }
  430. if($msg != self::minus_one){
  431. //库存
  432. list($bool,$msg) = $this->changeInventoryReject($data,$order,$user);
  433. if(! $bool){
  434. DB::rollBack();
  435. return [false, $msg];
  436. }
  437. }
  438. }
  439. if(! empty(self::$operation_order_reject[$data['opt_case']])){
  440. $type = self::$operation_order_reject[$data['opt_case']];
  441. (new OrderOperationService())->add([
  442. 'order_number' => $order['order_number'],
  443. 'msg' => OrderOperation::$type[$type],
  444. 'type' => $type
  445. ],$user);
  446. }
  447. DB::commit();
  448. return [true, ''];
  449. }catch (\Throwable $exception){
  450. DB::rollBack();
  451. return [false, $exception->getMessage() . $exception->getLine() . $exception->getFile()];
  452. }
  453. }else{
  454. //具体方法
  455. $function = self::$opt_case[$data['opt_case']] ?? "";
  456. $record = self::$record[$data['opt_case']] ?? "";
  457. try{
  458. DB::beginTransaction();
  459. list($bool,$msg) = $this->$function($data);
  460. if(! $bool){
  461. DB::rollBack();
  462. return [false, $msg];
  463. }
  464. $order = $msg;
  465. if($data['type'] == self::TYPE_ONE){
  466. if($record) {
  467. //流水
  468. list($bool,$msg) = $this->$record($data, $order);
  469. if(! $bool) {
  470. DB::rollBack();
  471. return [false, $msg];
  472. }
  473. if($msg != self::minus_one){
  474. //库存
  475. list($bool,$msg) = $this->changeInventory($data, $order, $user);
  476. if(! $bool) {
  477. DB::rollBack();
  478. return [false, $msg];
  479. }
  480. }
  481. }
  482. }
  483. if(! empty(self::$operation_order[$data['opt_case']])){
  484. $user = $data['user_data'] ?? [];
  485. $type = self::$operation_order[$data['opt_case']];
  486. (new OrderOperationService())->add([
  487. 'order_number' => $order['order_number'],
  488. 'msg' => OrderOperation::$type[$type],
  489. 'type' => $type
  490. ],$user);
  491. }
  492. DB::commit();
  493. return [true, ''];
  494. }catch (\Throwable $exception){
  495. DB::rollBack();
  496. return [false, $exception->getMessage() . $exception->getLine() . $exception->getFile()];
  497. }
  498. }
  499. }
  500. //不需要走审批流 直接调用
  501. public function createRecordAndInventoryMy($data = [],$user = [],$order = []){
  502. if(! empty($data['type']) && $data['type'] == self::TYPE_THREE){
  503. }else{
  504. //具体方法
  505. $record = self::$record[$data['opt_case']] ?? "";
  506. try{
  507. DB::beginTransaction();
  508. if($record) {
  509. //流水
  510. list($bool,$msg) = $this->$record($data, $order);
  511. if(! $bool) {
  512. DB::rollBack();
  513. return [false, $msg];
  514. }
  515. if($msg != self::minus_one){
  516. //库存
  517. list($bool,$msg) = $this->changeInventory($data, $order, $user);
  518. if(! $bool) {
  519. DB::rollBack();
  520. return [false, $msg];
  521. }
  522. }
  523. }
  524. if(! empty(self::$operation_order[$data['opt_case']])){
  525. $type = self::$operation_order[$data['opt_case']];
  526. (new OrderOperationService())->add([
  527. 'order_number' => $order['order_number'],
  528. 'msg' => OrderOperation::$type[$type],
  529. 'type' => $type
  530. ],$user);
  531. }
  532. DB::commit();
  533. return [true, ''];
  534. }catch (\Throwable $exception){
  535. DB::rollBack();
  536. return [false, $exception->getMessage() . $exception->getLine() . $exception->getFile()];
  537. }
  538. }
  539. }
  540. }