CheckService.php 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. <?php
  2. namespace App\Service;
  3. use App\Model\Construction;
  4. use App\Model\ConstructionProductInfo;
  5. use App\Model\Depart;
  6. use App\Model\Employee;
  7. use App\Model\InOutRecord;
  8. use App\Model\InvoiceOrder;
  9. use App\Model\InvoiceOrderInfo;
  10. use App\Model\ProductInventory;
  11. use App\Model\PurchaseOrder;
  12. use App\Model\PurchaseOrderInfo;
  13. use App\Model\PurchaseOrderSpecial;
  14. use App\Model\PurchaseOrderSpecialInfo;
  15. use App\Model\ReturnExchangeOrder;
  16. use App\Model\ReturnExchangeOrderProductInfo;
  17. use App\Model\SalesOrder;
  18. use App\Model\SalesOrderOtherFee;
  19. use App\Model\SalesOrderProductInfo;
  20. use App\Model\SeeRange;
  21. use App\Model\Storehouse;
  22. use App\Model\Supplier;
  23. use App\Service\Oa\OaService;
  24. use Illuminate\Support\Facades\DB;
  25. class CheckService extends Service
  26. {
  27. //审批操作对应的数值
  28. const one = 1; //收货
  29. const two = 2; //发货
  30. const three = 3; //采购单入库
  31. const four = 4; //合同公司完结
  32. const five = 5; //施工单
  33. const six = 6; //退换货单
  34. const seven = 7; //采购单确认
  35. const eight = 8; //合同确认
  36. const nine = 9; //合同客户完结
  37. //中文对照
  38. public $map = [
  39. self::one => '收货单',
  40. self::two => '发货单',//确认后出库
  41. self::three => '采购单',//确认后入库
  42. self::four => '合同', // 安装件 合同完结
  43. self::five => '施工单',//确认后出库
  44. self::six => '退换货单',//确认后出库或出库入库
  45. self::seven => '采购单确认',
  46. self::eight => '合同确认',
  47. ];
  48. //入库操作
  49. public static $in_opt = [
  50. self::three,
  51. ];
  52. //出库操作
  53. public static $out_opt = [
  54. self::two,
  55. self::five,
  56. ];
  57. const TYPE_ONE = 1;//通过
  58. const TYPE_TWO = 2;//不通过
  59. const TYPE_THREE = 3;//通过后驳回
  60. //改为待审核状态
  61. public static $opt_1case = [
  62. self::two => 'waitInvoice',//发货单
  63. self::three => 'waitPurchase',//采购单 入库
  64. self::five => 'waitConstruction',//施工单
  65. self::six => 'waitReturnExchange',//退换货单
  66. self::seven => 'waitPurchaseConfirm', //采购单确认
  67. self::eight => 'waitSales', // 合同安装件 合同确认
  68. ];
  69. public static $finished = [
  70. self::four => 'confirmSalesOrder', // 合同 安装件 合同公司完结
  71. self::nine => 'confirmSalesOrder2', // 合同 安装件 合同客户完结
  72. ];
  73. //单据操作
  74. public static $opt_case = [
  75. self::two => 'confirmInvoiceOrder',
  76. self::three => 'confirmPurchaseOrder',
  77. self::five => 'confirmConstruction',
  78. self::six => 'confirmReturnExchangeOrder',
  79. self::seven => 'confirmPurchaseOrderState',
  80. self::eight => 'confirmSales', // 合同 安装件 合同确认
  81. ];
  82. //单据库存流水
  83. public static $record = [
  84. self::two => 'recordInvoiceOrder',
  85. self::three => 'recordPurchaseOrder',
  86. self::five => 'recordConstruction',
  87. self::six => 'recordReturnExchangeOrder'
  88. ];
  89. //自动生成
  90. public static $create = [
  91. self::seven => 'createPurchaseOrderSales', //分社合同生成
  92. self::four => 'createPurchaseOrder', // 派给分社的合同确认以后生成虚拟采购单
  93. ];
  94. //审核通过后 驳回
  95. public static $opt_case_reject = [
  96. self::four => 'reject_sales', // 合同
  97. self::three => 'reject_purchase', //采购
  98. self::five => 'reject_construction',//施工单
  99. self::six => 'reject_return_exchange',//退换货
  100. ];
  101. //审核通过后 驳回 产生流水
  102. public static $reject_record = [
  103. self::five => 'reject_record_construction', //施工单驳回
  104. self::three => 'reject_record_purchase', //采购
  105. self::six => 'reject_record_return_exchange',//退换货
  106. ];
  107. //改为待审核---------------------------------
  108. public function waitInvoice($data){
  109. $model = InvoiceOrder::where('id',$data['id'])
  110. ->where('del_time',0)
  111. ->first();
  112. if(empty($model)) return [false, '发货单不存在或已被删除'];
  113. if($model->state != InvoiceOrder::STATE_ONE) return [false, '请确认发货单状态,操作失败'];
  114. InvoiceOrder::where('del_time',0)->where('id',$data['id'])
  115. ->update(['state' => InvoiceOrder::STATE_ONE]);
  116. return [true, $model->toArray()];
  117. }
  118. public function waitPurchaseConfirm($data){
  119. $model = PurchaseOrder::where('id',$data['id'])
  120. ->where('del_time',0)
  121. ->first();
  122. if(empty($model)) return [false,'采购单不存在或已被删除'];
  123. if($model->state != PurchaseOrder::STATE_ZERO) return [false,'请确认采购单状态,操作失败'];
  124. //待确认
  125. PurchaseOrder::where('id',$data['id'])->update(['state' => PurchaseOrder::STATE_ONE]);
  126. return [true, $model->toArray()];
  127. }
  128. public function waitPurchase($data){
  129. $model = PurchaseOrder::where('id',$data['id'])
  130. ->where('del_time',0)
  131. ->first();
  132. if(empty($model)) return [false, '采购订单不存在或已被删除'];
  133. if($model->state != PurchaseOrder::STATE_TWO) return [false, '请确认采购订单状态,操作失败'];
  134. //待入库
  135. PurchaseOrder::where('del_time',0)->where('id',$data['id'])
  136. ->update(['state' => PurchaseOrder::STATE_Three]);
  137. return [true, $model->toArray()];
  138. }
  139. public function waitConstruction($data){
  140. $model = Construction::where('id',$data['id'])
  141. ->where('del_time',0)
  142. ->first();
  143. if(empty($model)) return [false, '施工单不存在或已被删除'];
  144. if($model->state != Construction::STATE_ZERO) return [false, '请确认施工单状态,操作失败'];
  145. //待确认
  146. Construction::where('del_time',0)->where('id',$data['id'])
  147. ->update(['state' => Construction::STATE_ONE]);
  148. return [true, $model->toArray()];
  149. }
  150. public function waitReturnExchange($data){
  151. $model = ReturnExchangeOrder::where('id',$data['id'])
  152. ->where('del_time',0)
  153. ->first();
  154. if(empty($model)) return [false, '退换货单不存在或已被删除'];
  155. if($model->state != ReturnExchangeOrder::State_zero) return [false, '请确认退换货单状态,操作失败'];
  156. //待确认
  157. ReturnExchangeOrder::where('del_time',0)->where('id',$data['id'])
  158. ->update(['state' => ReturnExchangeOrder::State_one]);
  159. return [true, $model->toArray()];
  160. }
  161. public function waitSales($data){
  162. $model = SalesOrder::where('id', $data['id'])
  163. ->where('del_time',0)
  164. ->first();
  165. if(empty($model)) return [false, '合同不存在或已被删除'];
  166. //安装件
  167. if($model->state != SalesOrder::State_zero) return [false, '请确认合同状态,操作失败'];
  168. SalesOrder::where('del_time',0)->where('id',$data['id'])
  169. ->update(['state' => SalesOrder::State_one]);
  170. return [true, $model->toArray()];
  171. }
  172. //改为待审核---------------------------------
  173. public function confirmInvoiceOrder($data){
  174. $model = InvoiceOrder::where('order_number',$data['order_number'])
  175. ->where('del_time',0)
  176. ->first();
  177. if(empty($model)) return [false, '发货单不存在或已被删除'];
  178. if($model->state != InvoiceOrder::STATE_ONE) return [false, '请确认发货单状态,操作失败'];
  179. InvoiceOrder::where('del_time',0)->where('order_number',$data['order_number'])
  180. ->update(['state' => InvoiceOrder::STATE_TWO]);
  181. SalesOrder::where('id',$model->sales_order_id)->update(['state' => SalesOrder::State2_one]);
  182. return [true, $model->toArray()];
  183. }
  184. public function recordInvoiceOrder($data, $order){
  185. $result = InvoiceOrderInfo::where('del_time',0)
  186. ->where('order_number',$order['order_number'])
  187. ->get()->toArray();
  188. if(empty($result)) return [false,'发货单产品信息不存在或已被删除'];
  189. $insert = [];
  190. $time = time();
  191. foreach ($result as $value){
  192. $key = $value['product_id'] . $value['storehouse_id'];
  193. if(isset($insert[$key])){
  194. $insert[$key]['number'] += -($value['number']);
  195. }else{
  196. $insert[$key] = [
  197. 'product_id' => $value['product_id'],
  198. 'number' => -($value['number']),
  199. 'order_type' => InvoiceOrder::prefix,
  200. 'order_number' => $order['order_number'],
  201. 'crt_time' => $time,
  202. 'storehouse_id' => $value['storehouse_id'],
  203. 'depart_id' => $order['depart_id'],
  204. 'top_depart_id' => $order['top_depart_id'],
  205. ];
  206. }
  207. }
  208. $insert = array_values($insert);
  209. $bool = InOutRecord::insert($insert);
  210. if(! $bool) return [false,'流水写入失败'];
  211. return [true,''];
  212. }
  213. public function confirmPurchaseOrderState($data){
  214. $model = PurchaseOrder::where('order_number',$data['order_number'])
  215. ->where('del_time',0)
  216. ->first();
  217. if(empty($model)) return [false,'采购单不存在或已被删除'];
  218. if($model->state != PurchaseOrder::STATE_ONE) return [false,'请确认采购单状态,操作失败'];
  219. //未入库
  220. PurchaseOrder::where('order_number',$data['order_number'])->update(['state' => PurchaseOrder::STATE_TWO]);
  221. return [true, $model->toArray()];
  222. }
  223. public function confirmPurchaseOrder($data){
  224. $model = PurchaseOrder::where('order_number',$data['order_number'])
  225. ->where('del_time',0)
  226. ->first();
  227. if(empty($model)) return [false, '采购订单不存在或已被删除'];
  228. if($model->state != PurchaseOrder::STATE_Three) return [false, '请确认采购订单状态,操作失败'];
  229. // 已出库
  230. PurchaseOrder::where('del_time',0)->where('order_number',$data['order_number'])
  231. ->update(['state' => PurchaseOrder::STATE_Four]);
  232. return [true, $model->toArray()];
  233. }
  234. public function recordPurchaseOrder($data, $order){
  235. $result = PurchaseOrderInfo::where('del_time',0)
  236. ->where('order_number',$order['order_number'])
  237. ->get()->toArray();
  238. if(empty($result)) return [false,'采购单产品信息不存在或已被删除'];
  239. $insert = [];
  240. $time = time();
  241. foreach ($result as $value){
  242. $key = $value['product_id'] . $value['storehouse_id'];
  243. if(isset($insert[$key])){
  244. $insert[$key]['number'] += $value['number'];
  245. }else{
  246. $insert[$key] = [
  247. 'product_id' => $value['product_id'],
  248. 'number' => $value['number'],
  249. 'order_type' => PurchaseOrder::prefix,
  250. 'order_number' => $order['order_number'],
  251. 'crt_time' => $time,
  252. 'storehouse_id' => $value['storehouse_id'],
  253. 'depart_id' => $order['depart_id'],
  254. 'top_depart_id' => $order['top_depart_id'],
  255. ];
  256. }
  257. }
  258. $insert = array_values($insert);
  259. $bool = InOutRecord::insert($insert);
  260. if(! $bool) return [false,'流水写入失败'];
  261. return [true,''];
  262. }
  263. //todo
  264. public function createPurchaseOrderSales($order){
  265. //没有供应商 不创建合同
  266. if(empty($order['supplier'])) return [true, ''];
  267. //总公司的采购单 不创建合同
  268. $depart = Depart::where('del_time',0)
  269. ->where('is_main',1)
  270. ->where('parent_id',0)
  271. ->first();
  272. $head = 0;
  273. if(! empty($depart)) $head = $depart->id;//总社
  274. if($head == $order['top_depart_id']) return [true, ''];
  275. //分社公司的采购单 不向总供应商采购 不创建合同
  276. $is_create = Supplier::where('id',$order['supplier'])->value('is_main');
  277. if(empty($is_create)) return [true, ''];
  278. $prefix = SalesOrder::$prefix[SalesOrder::Model_type_two];
  279. $order_number = OrderNoService::createSalesOrderNumber($prefix);
  280. $product = PurchaseOrderInfo::where('del_time',0)
  281. ->where('purchase_order_id',$order['id'])
  282. ->get()->toArray();
  283. if(empty($product)) return [false, '采购订单产品数据不能为空'];
  284. $depart_id = Depart::where('del_time',0)->where('parent_id',0)->where('is_main',1)->value('id');
  285. $model = new SalesOrder();
  286. $model->model_type = SalesOrder::Model_type_two;
  287. $model->sales_order_type = SalesOrder::Order_type_one;
  288. $model->order_number = $order_number;
  289. $model->crt_id = $order['crt_id'];
  290. $model->depart_id = $depart_id;
  291. $model->top_depart_id = $depart_id;
  292. $model->other_fee = $order['other_fee'];
  293. $model->discount_fee = $order['discount_fee'];
  294. $model->contract_fee = $order['purchase_total'];
  295. $model->save();
  296. $sales_order_id = $model->id;
  297. //产品字典
  298. $product_map = (new ProductService())->getProductDetail(array_column($product,'product_id'));
  299. //获取产品采购使用金额
  300. $map = (new ProductService())->getProductPrice(array_column($product,'product_id'),1);
  301. //获取部门目前使用的分社价
  302. $basic_type_id = Depart::where('id',$order['top_depart_id'])->value('basic_type_id');
  303. //产品对应的分社价
  304. $new_map = [];
  305. foreach ($map as $product_id => $value){
  306. foreach ($value as $v){
  307. if($v['basic_type_id'] == $basic_type_id && ! empty($v['price'])) $new_map[$product_id] = $v['price'];
  308. }
  309. }
  310. $insert = [];
  311. $product_total = 0;
  312. foreach ($product as $value){
  313. $tmp = $product_map[$value['product_id']] ?? [];
  314. $fs_price = $new_map[$value['product_id']] ?? 0;
  315. //有分社价就是分社价格 没有就是零售
  316. $price = $fs_price ? $fs_price : $tmp['retail_price'];
  317. $product_total += $price * $value['number'];
  318. $insert[] = [
  319. 'sales_order_id' => $sales_order_id,
  320. 'product_id' => $value['product_id'],
  321. 'number' => $value['number'],
  322. 'basic_type_id' => $basic_type_id,
  323. 'price' => $price,
  324. 'cost' => $tmp['cost'] ?? 0,
  325. 'retail_price' => $tmp['retail_price'] ?? 0,
  326. ];
  327. }
  328. $bool = SalesOrderProductInfo::insert($insert);
  329. if(! $bool) return [false,'合同生成失败!'];
  330. //反写产品总计
  331. SalesOrder::where('id',$sales_order_id)->update(['product_total' => $product_total]);
  332. return [true,''];
  333. }
  334. public function confirmConstruction($data){
  335. $model = Construction::where('order_number',$data['order_number'])
  336. ->where('del_time',0)
  337. ->first();
  338. if(empty($model)) return [false, '施工单不存在或已被删除'];
  339. if($model->state != Construction::STATE_ONE) return [false, '请确认施工单状态,操作失败'];
  340. //已确认
  341. Construction::where('del_time',0)->where('order_number',$data['order_number'])
  342. ->update(['state' => Construction::STATE_TWO]);
  343. //已下施工
  344. SalesOrder::where('id',$model->sales_order_id)->update(['state' => SalesOrder::State_five]);
  345. return [true, $model->toArray()];
  346. }
  347. public function recordConstruction($data, $order){
  348. $result = ConstructionProductInfo::where('del_time',0)
  349. ->where('construction_id',$order['id'])
  350. ->get()->toArray();
  351. if(empty($result)) return [false,'施工单产品信息不存在或已被删除'];
  352. $insert = [];
  353. $time = time();
  354. foreach ($result as $value){
  355. $key = $value['product_id'] . $value['storehouse_id'];
  356. if(isset($insert[$key])){
  357. $insert[$key]['number'] += -($value['number']);
  358. }else{
  359. $insert[$key] = [
  360. 'product_id' => $value['product_id'],
  361. 'number' => -($value['number']),
  362. 'order_type' => Construction::$prefix[$order['model_type']] ?? '',
  363. 'order_number' => $order['order_number'],
  364. 'crt_time' => $time,
  365. 'storehouse_id' => $value['storehouse_id'],
  366. 'depart_id' => $order['depart_id'],
  367. 'top_depart_id' => $order['top_depart_id'],
  368. ];
  369. }
  370. }
  371. $insert = array_values($insert);
  372. $bool = InOutRecord::insert($insert);
  373. if(! $bool) return [false,'流水写入失败'];
  374. return [true,''];
  375. }
  376. public function confirmReturnExchangeOrder($data){
  377. $model = ReturnExchangeOrder::where('order_number',$data['order_number'])
  378. ->where('del_time',0)
  379. ->first();
  380. if(empty($model)) return [false, '退换货单不存在或已被删除'];
  381. if($model->state != ReturnExchangeOrder::State_one) return [false, '请确认退换货单状态,操作失败'];
  382. ReturnExchangeOrder::where('del_time',0)->where('order_number',$data['order_number'])
  383. ->update(['state' => ReturnExchangeOrder::State_two]);
  384. if($model->data_type == ReturnExchangeOrder::Order_type){
  385. SalesOrder::where('id', $model->data_id)->update([
  386. 'state' => SalesOrder::State_six
  387. ]);
  388. }
  389. return [true, $model->toArray()];
  390. }
  391. public function recordReturnExchangeOrder($data, $order){
  392. $result = ReturnExchangeOrderProductInfo::where('del_time',0)
  393. ->where('return_exchange_id',$order['id'])
  394. ->get()->toArray();
  395. if(empty($result)) return [false,'退换货单产品信息不存在或已被删除'];
  396. $insert = $insert2 = [];
  397. $time = time();
  398. foreach ($result as $value){
  399. $key = $value['product_id'] . $value['storehouse_id'];
  400. $prefix = ReturnExchangeOrder::$prefix[$value['return_or_exchange']] ?? '';
  401. if($value['return_or_exchange'] == ReturnExchangeOrderProductInfo::type_one){
  402. //退货
  403. if(isset($insert[$key])){
  404. $insert[$key]['number'] += $value['number'];
  405. }else{
  406. $insert[$key] = [
  407. 'product_id' => $value['product_id'],
  408. 'number' => $value['number'],
  409. 'order_type' => $prefix,
  410. 'order_number' => $order['order_number'],
  411. 'crt_time' => $time,
  412. 'storehouse_id' => $value['storehouse_id'],
  413. 'depart_id' => $order['depart_id'],
  414. 'top_depart_id' => $order['top_depart_id'],
  415. ];
  416. }
  417. }else{
  418. //换货
  419. if(isset($insert2[$key])){
  420. $insert2[$key]['number'] += -($value['number']);
  421. }else{
  422. $insert2[$key] = [
  423. 'product_id' => $value['product_id'],
  424. 'number' => -($value['number']),
  425. 'order_type' => $prefix,
  426. 'order_number' => $order['order_number'],
  427. 'crt_time' => $time,
  428. 'storehouse_id' => $value['storehouse_id'],
  429. 'depart_id' => $order['depart_id'],
  430. 'top_depart_id' => $order['top_depart_id'],
  431. ];
  432. }
  433. }
  434. }
  435. $insert = array_values($insert);
  436. $bool = InOutRecord::insert($insert);
  437. if(! $bool) return [false,'流水写入失败'];
  438. if(! empty($insert2)) {
  439. $insert2 = array_values($insert2);
  440. $bool = InOutRecord::insert($insert2);
  441. if(! $bool) return [false,'流水写入失败'];
  442. }
  443. return [true,''];
  444. }
  445. public function confirmSalesOrder($data){
  446. $model = SalesOrder::where('order_number', $data['order_number'])
  447. ->where('del_time',0)
  448. ->first();
  449. if(empty($model)) return [false, '合同不存在或已被删除'];
  450. //安装件
  451. if($model->state <= SalesOrder::State_four || $model->state >= SalesOrder::State_seven) return [false, '请确认合同状态,操作失败'];
  452. SalesOrder::where('del_time',0)->where('order_number',$data['order_number'])
  453. ->update(['state' => SalesOrder::State_seven]);
  454. return [true, $model->toArray()];
  455. }
  456. public function confirmSalesOrder2($data){
  457. $model = SalesOrder::where('order_number', $data['order_number'])
  458. ->where('del_time',0)
  459. ->first();
  460. if(empty($model)) return [false, '合同不存在或已被删除'];
  461. //安装件
  462. if($model->state != SalesOrder::State_seven) return [false, '请确认合同状态,操作失败'];
  463. SalesOrder::where('del_time',0)->where('order_number',$data['order_number'])
  464. ->update(['state' => SalesOrder::State_eight]);
  465. return [true, $model->toArray()];
  466. }
  467. public function confirmSales($data){
  468. $model = SalesOrder::where('order_number', $data['order_number'])
  469. ->where('del_time',0)
  470. ->first();
  471. if(empty($model)) return [false, '合同不存在或已被删除'];
  472. if($model->state != SalesOrder::State_one) return [false, '请确认合同状态,操作失败'];
  473. //已确认
  474. SalesOrder::where('del_time',0)->where('order_number',$data['order_number'])
  475. ->update(['state' => SalesOrder::State_two]);
  476. return [true, $model->toArray()];
  477. }
  478. //总社派给分社的合同 完成生成虚拟采购单
  479. public function createPurchaseOrder($order){
  480. //快递件
  481. if($order['sales_order_type'] == SalesOrder::Order_type_two) return [true,''];
  482. //不是总公司的合同
  483. $depart = Depart::where('del_time',0)
  484. ->where('is_main',1)
  485. ->where('parent_id',0)
  486. ->first();
  487. $head = 0;
  488. if(! empty($depart)) $head = $depart->id;//总社
  489. if($head != $order['top_depart_id']) return [true, ''];
  490. $see = SeeRange::where('del_time',0)
  491. ->where('data_id',$order['id'])
  492. ->where('data_type',SeeRange::type_seven)
  493. ->where('type',SeeRange::data_three)
  494. ->first();
  495. if(empty($see)) return [false, '未找到指派分社信息'];
  496. $depart_id = $see->param_id;//指派的分社
  497. //总社指派给自己
  498. if($depart_id == $head) return [true, ''];
  499. //获取指派分社时候的金额
  500. $fee = SalesOrderOtherFee::where('del_time',0)
  501. ->where('sales_order_id',$order['id'])
  502. ->first();
  503. if(empty($fee)) return [false, '未找到指派分社时填写的金额'];
  504. $fee = $fee->toArray();
  505. $order_number = (new OrderNoService())->createOrderNumber(PurchaseOrderSpecial::prefix);
  506. $storehouse = Storehouse::where('depart_id',$head)->value('id');
  507. $product = SalesOrderProductInfo::where('del_time',0)
  508. ->where('sales_order_id',$order['id'])
  509. ->select('product_id','number','retail_price')
  510. ->get()->toArray();
  511. $product_map = $rate = [];
  512. $total = 0;
  513. foreach ($product as $value){
  514. $total += $value['number'] * $value['retail_price'];
  515. if(isset($product_map[$value['product_id']])){
  516. $product_map[$value['product_id']] += $value['retail_price'] * $value['number'];
  517. }else{
  518. $product_map[$value['product_id']] = $value['retail_price'] * $value['number'];
  519. }
  520. }
  521. foreach ($product_map as $key => $value){
  522. $rate[$key] = sprintf("%.2f", round($value / $total, 2));
  523. }
  524. $model = new PurchaseOrderSpecial();
  525. $model->order_number = $order_number;
  526. $model->sales_order_id = $order['id'];
  527. $model->depart_id = $head;
  528. $model->top_depart_id = $head;
  529. $model->crt_id = Employee::SPECIAL_ADMIN;
  530. $model->purchase_id = Employee::SPECIAL_ADMIN;
  531. $model->purchase_total = $fee['other_fee_1'] ?? 0;
  532. $model->storehouse_id = $storehouse ?? 0;
  533. $model->save();
  534. if(empty($model->id)) return [false,'采购单主信息生成失败'];
  535. $purchase_order_id = $model->id;
  536. $insert = [];$product_total = 0;
  537. foreach ($product as $value){
  538. $rate_tmp = $rate[$value['product_id']] ?? 0;
  539. $price = sprintf("%.2f", round($rate_tmp * $fee['other_fee_1'] / $value['number'], 2));
  540. $product_total += $price * $value['number'];
  541. $insert[] = [
  542. 'purchase_order_special_id' => $purchase_order_id,
  543. 'product_id' => $value['product_id'],
  544. 'order_number' => $order_number,
  545. 'number' => $value['number'],
  546. 'price' => $price,
  547. 'storehouse_id' => $storehouse,
  548. ];
  549. }
  550. PurchaseOrderSpecialInfo::insert($insert);
  551. PurchaseOrderSpecial::where('id',$purchase_order_id)->update(['total' => $product_total]);
  552. return [true, ''];
  553. }
  554. public function reject_sales($data){
  555. $model = SalesOrder::where('order_number', $data['order_number'])
  556. ->where('del_time',0)
  557. ->first();
  558. if(empty($model)) return [false, '合同不存在或已被删除'];
  559. //安装件
  560. if($model->state != SalesOrder::State_two) return [false, '请确认合同状态,操作失败'];
  561. //未确认
  562. SalesOrder::where('del_time',0)->where('order_number',$data['order_number'])
  563. ->update(['state' => SalesOrder::State_zero]);
  564. return [true, $model->toArray()];
  565. }
  566. public function reject_purchase($data){
  567. $model = PurchaseOrder::where('order_number', $data['order_number'])
  568. ->where('del_time',0)
  569. ->first();
  570. if(empty($model)) return [false, '采购单不存在或已被删除'];
  571. //安装件
  572. if($model->state != PurchaseOrder::STATE_Four) return [false, '请确认采购单状态,操作失败'];
  573. //未出库
  574. PurchaseOrder::where('del_time',0)->where('order_number',$data['order_number'])
  575. ->update(['state' => PurchaseOrder::STATE_TWO]);
  576. return [true, $model->toArray()];
  577. }
  578. public function reject_construction($data){
  579. $model = Construction::where('order_number', $data['order_number'])
  580. ->where('del_time',0)
  581. ->first();
  582. if(empty($model)) return [false, '施工单不存在或已被删除'];
  583. //安装件
  584. if($model->state != Construction::STATE_TWO) return [false, '请确认施工单状态,操作失败'];
  585. Construction::where('del_time',0)->where('order_number',$data['order_number'])
  586. ->update(['state' => Construction::STATE_ZERO]);
  587. return [true, $model->toArray()];
  588. }
  589. public function reject_return_exchange($data){
  590. $model = ReturnExchangeOrder::where('order_number', $data['order_number'])
  591. ->where('del_time',0)
  592. ->first();
  593. if(empty($model)) return [false, '退换货单不存在或已被删除'];
  594. //安装件
  595. if($model->state != ReturnExchangeOrder::State_two) return [false, '请确认退换货单状态,操作失败'];
  596. ReturnExchangeOrder::where('del_time',0)->where('order_number',$data['order_number'])
  597. ->update(['state' => ReturnExchangeOrder::State_zero]);
  598. return [true, $model->toArray()];
  599. }
  600. public function reject_record_construction($data,$order){
  601. //获取单据最新数据时间 正常施工数据
  602. $latest = InOutRecord::where('del_time',0)
  603. ->where('order_number',$data['order_number'])
  604. ->where('number','<',0)
  605. ->select('crt_time')
  606. ->orderBy('crt_time', 'desc')
  607. ->first();
  608. $latest = $latest->toArray();
  609. $result = InOutRecord::where('del_time',0)
  610. ->where('crt_time',$latest['crt_time'])
  611. ->where('order_number',$data['order_number'])
  612. ->where('number','<',0)
  613. ->select('product_id','storehouse_id','number','depart_id','order_number','top_depart_id','order_type')
  614. ->get()->toArray();
  615. if(empty($result)) return false;
  616. //生成对冲数据
  617. $time = time();
  618. foreach ($result as $key => $value){
  619. $result[$key]['number'] = abs($value['number']);
  620. $result[$key]['crt_time'] = $time;
  621. }
  622. //写入流水
  623. return InOutRecord::insert($result);
  624. }
  625. public function reject_record_purchase($data,$order){
  626. //获取单据最新数据时间 正常采购入库数据
  627. $latest = InOutRecord::where('del_time',0)
  628. ->where('order_number',$data['order_number'])
  629. ->where('number','>',0)
  630. ->select('crt_time')
  631. ->orderBy('crt_time', 'desc')
  632. ->first();
  633. $latest = $latest->toArray();
  634. $result = InOutRecord::where('del_time',0)
  635. ->where('crt_time',$latest['crt_time'])
  636. ->where('order_number',$data['order_number'])
  637. ->where('number','>',0)
  638. ->select('product_id','storehouse_id','number','depart_id','order_number','top_depart_id','order_type')
  639. ->get()->toArray();
  640. if(empty($result)) return false;
  641. //生成对冲数据
  642. $time = time();
  643. foreach ($result as $key => $value){
  644. $result[$key]['number'] = - $value['number'];
  645. $result[$key]['crt_time'] = $time;
  646. }
  647. //写入流水
  648. return InOutRecord::insert($result);
  649. }
  650. public function reject_record_return_exchange($data,$order){
  651. $result = ReturnExchangeOrderProductInfo::where('del_time',0)
  652. ->where('return_exchange_id',$order['id'])
  653. ->get()->toArray();
  654. if(empty($result)) return [false,'退换货单产品信息不存在或已被删除'];
  655. $insert = $insert2 = [];
  656. $time = time();
  657. foreach ($result as $value){
  658. $key = $value['product_id'] . $value['storehouse_id'];
  659. $prefix = ReturnExchangeOrder::$prefix[$value['return_or_exchange']] ?? '';
  660. if($value['return_or_exchange'] == ReturnExchangeOrderProductInfo::type_one){
  661. //退货 扣出
  662. if(isset($insert[$key])){
  663. $insert[$key]['number'] += -($value['number']);
  664. }else{
  665. $insert[$key] = [
  666. 'product_id' => $value['product_id'],
  667. 'number' => -($value['number']),
  668. 'order_type' => $prefix,
  669. 'order_number' => $order['order_number'],
  670. 'crt_time' => $time,
  671. 'storehouse_id' => $value['storehouse_id'],
  672. 'depart_id' => $order['depart_id'],
  673. 'top_depart_id' => $order['top_depart_id'],
  674. ];
  675. }
  676. }else{
  677. //换货 加回
  678. if(isset($insert2[$key])){
  679. $insert2[$key]['number'] += $value['number'];
  680. }else{
  681. $insert2[$key] = [
  682. 'product_id' => $value['product_id'],
  683. 'number' => $value['number'],
  684. 'order_type' => $prefix,
  685. 'order_number' => $order['order_number'],
  686. 'crt_time' => $time,
  687. 'storehouse_id' => $value['storehouse_id'],
  688. 'depart_id' => $order['depart_id'],
  689. 'top_depart_id' => $order['top_depart_id'],
  690. ];
  691. }
  692. }
  693. }
  694. $insert = array_values($insert);
  695. $bool = InOutRecord::insert($insert);
  696. if(! $bool) return [false,'流水写入失败'];
  697. if(! empty($insert2)) {
  698. $insert2 = array_values($insert2);
  699. $bool = InOutRecord::insert($insert2);
  700. if(! $bool) return [false,'流水写入失败'];
  701. }
  702. return [true,''];
  703. }
  704. public function checkAll($data,$user){
  705. if(empty($data['id']) || empty($data['order_number'])|| empty($data['opt_case'])) return [false,'必传参数不能为空或者参数值错误!'];
  706. list($status,$msg) = $this->limitingSendRequestBackgExpire($data['order_number'].$data['opt_case']);
  707. if(! $status) return [false,$msg];
  708. //单据状态改为待审批方法
  709. $function = self::$opt_1case[$data['opt_case']] ?? '';
  710. $function2 = self::$finished[$data['opt_case']] ?? '';
  711. try{
  712. DB::beginTransaction();
  713. if($function2) {
  714. list($bool,$msg) = $this->$function($data);
  715. if($bool) {
  716. DB::commit();
  717. return [true, ''];
  718. }else{
  719. DB::rollBack();
  720. return [false, $msg];
  721. }
  722. }
  723. //更新单据的状态 从未审核变成待审核
  724. list($bool,$msg) = $this->$function($data);
  725. if(! $bool){
  726. DB::rollBack();
  727. return [false, $msg];
  728. }
  729. //创建审批流
  730. $args = [
  731. 'order_no' => $data['order_number'],
  732. 'menu_id' => $data['menu_id'] ?? 0,
  733. 'opt_case' => $data['opt_case'],
  734. 'order' => $msg,
  735. ];
  736. $return_msg = '';
  737. $oa = new OaService();
  738. $bool = $oa->createOaOrder($args);
  739. if(! $bool) $return_msg = '审批失败!';
  740. DB::commit();
  741. if($return_msg) return [false,$msg];
  742. return [true, ''];
  743. }catch (\Throwable $exception){
  744. DB::rollBack();
  745. return [false, $exception->getMessage() . $exception->getFile(). $exception->getLine()];
  746. }
  747. }
  748. //更新库存
  749. public function changeInventory($data,$order){
  750. $number_symbol = "";
  751. if(in_array($data['opt_case'],self::$in_opt)){
  752. $number_symbol = ">";
  753. }elseif (in_array($data['opt_case'],self::$out_opt)){
  754. $number_symbol = "<";
  755. }
  756. //获取单据最新数据时间 正常审核的数据
  757. $latest = InOutRecord::where('del_time',0)
  758. ->where('order_number',$order['order_number'])
  759. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  760. return $query->where('number', $number_symbol,0);
  761. })
  762. ->select('crt_time')
  763. ->orderBy('crt_time', 'desc')
  764. ->first();
  765. $model = InOutRecord::where('del_time',0)
  766. ->where('order_number',$order['order_number'])
  767. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  768. return $query->where('number', $number_symbol,0);
  769. })
  770. ->select('number','crt_time','product_id','storehouse_id','top_depart_id');
  771. if(! empty($latest)) {
  772. $t = $latest->toArray();
  773. $model->where('crt_time',$t['crt_time']);
  774. }
  775. $record = $model->get()->toArray();
  776. if (empty($record)) return [false,'流水记录不存在'];
  777. $result = $lock_number = [];
  778. foreach ($record as $value){
  779. $key = $value['product_id'] . $value['storehouse_id'];
  780. if(isset($result[$key])){
  781. $result[$key]['number'] += $value['number'];
  782. }else{
  783. $result[$key] = [
  784. 'product_id' => $value['product_id'],
  785. 'number' => $value['number'],
  786. 'crt_time' => $value['crt_time'],
  787. 'storehouse_id' => $value['storehouse_id'],
  788. 'top_depart_id' => $value['top_depart_id'],
  789. ];
  790. }
  791. if($value['number'] < 0){
  792. if(isset($lock_number[$key])){
  793. $lock_number[$key] += $value['number'];
  794. }else{
  795. $lock_number[$key] = $value['number'];
  796. }
  797. }
  798. }
  799. //是否锁定
  800. $lock = 0;
  801. $depart = Depart::where('del_time',0)
  802. ->where('is_main',1)
  803. ->where('parent_id',0)
  804. ->first();
  805. $head = 0;
  806. if(! empty($depart)) $head = $depart->id;//总社
  807. if($head != $order['top_depart_id']) $lock = DB::table('depart_set')->where('top_depart_id',$order['top_depart_id'])->value('param_one');
  808. $result = array_values($result);
  809. foreach ($result as $key => $value){
  810. $keys = $value['product_id'] . $value['storehouse_id'];
  811. $m = ProductInventory::where('product_id',$value['product_id'])
  812. ->where('storehouse_id',$value['storehouse_id'])
  813. ->select('product_id','number','storehouse_id')
  814. ->first();
  815. if(empty($m)){
  816. ProductInventory::insert($result[$key]);
  817. }else{
  818. $lock_number_tmp = 0;
  819. if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
  820. ProductInventory::where('product_id',$m->product_id)
  821. ->where('storehouse_id',$m->storehouse_id)
  822. ->lockForUpdate()
  823. ->update([
  824. 'number' => DB::raw('number + ('. $value['number'] . ')'),
  825. 'lock_number' => DB::raw('lock_number + ('. $lock_number_tmp . ')')
  826. ]);
  827. }
  828. }
  829. return [true,''];
  830. }
  831. //业务单据审批通过后 驳回 更新库存
  832. public function changeInventoryReject($data,$order){
  833. $number_symbol = "";
  834. if(in_array($data['opt_case'],self::$in_opt)){
  835. $number_symbol = "<";
  836. }elseif (in_array($data['opt_case'],self::$out_opt)){
  837. $number_symbol = ">";
  838. }
  839. //获取单据最新数据时间 正常审核的数据
  840. $latest = InOutRecord::where('del_time',0)
  841. ->where('order_number',$order['order_number'])
  842. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  843. return $query->where('number', $number_symbol,0);
  844. })
  845. ->select('crt_time')
  846. ->orderBy('crt_time', 'desc')
  847. ->first();
  848. $model = InOutRecord::where('del_time',0)
  849. ->where('order_number',$order['order_number'])
  850. ->when(! empty($number_symbol), function ($query) use ($number_symbol) {
  851. return $query->where('number', $number_symbol,0);
  852. })
  853. ->select('number','crt_time','product_id','storehouse_id','top_depart_id');
  854. if(! empty($latest)) {
  855. $t = $latest->toArray();
  856. $model->where('crt_time',$t['crt_time']);
  857. }
  858. $record = $model->get()->toArray();
  859. if (empty($record)) return [false,'流水记录不存在'];
  860. $result = $lock_number = [];
  861. foreach ($record as $value){
  862. $key = $value['product_id'] . $value['storehouse_id'];
  863. if(isset($result[$key])){
  864. $result[$key]['number'] += $value['number'];
  865. }else{
  866. $result[$key] = [
  867. 'product_id' => $value['product_id'],
  868. 'number' => $value['number'],
  869. 'crt_time' => $value['crt_time'],
  870. 'storehouse_id' => $value['storehouse_id'],
  871. 'top_depart_id' => $value['top_depart_id'],
  872. ];
  873. }
  874. if($value['number'] > 0){
  875. if(isset($lock_number[$key])){
  876. $lock_number[$key] += $value['number'];
  877. }else{
  878. $lock_number[$key] = $value['number'];
  879. }
  880. }
  881. }
  882. //是否锁定
  883. $lock = 0;
  884. $depart = Depart::where('del_time',0)
  885. ->where('is_main',1)
  886. ->where('parent_id',0)
  887. ->first();
  888. $head = 0;
  889. if(! empty($depart)) $head = $depart->id;//总社
  890. if($head != $order['top_depart_id']) $lock = DB::table('depart_set')->where('top_depart_id',$order['top_depart_id'])->value('param_one');
  891. $result = array_values($result);
  892. foreach ($result as $key => $value){
  893. $keys = $value['product_id'] . $value['storehouse_id'];
  894. $m = ProductInventory::where('product_id',$value['product_id'])
  895. ->where('storehouse_id',$value['storehouse_id'])
  896. ->select('product_id','number','storehouse_id')
  897. ->first();
  898. if(empty($m)){
  899. ProductInventory::insert($result[$key]);
  900. }else{
  901. $lock_number_tmp = 0;
  902. if($lock && ! empty($lock_number[$keys])) $lock_number_tmp = $lock_number[$keys];
  903. ProductInventory::where('product_id',$m->product_id)
  904. ->where('storehouse_id',$m->storehouse_id)
  905. ->lockForUpdate()
  906. ->update([
  907. 'number' => DB::raw('number + ('. $value['number'] . ')'),
  908. 'lock_number' => DB::raw('lock_number + ('. $lock_number_tmp . ')')
  909. ]);
  910. }
  911. }
  912. return [true,''];
  913. }
  914. public function createRecordAndInventory($data = []){
  915. if(empty($data['type']) || empty($data['opt_case']) || empty($data['order_number'])) return [false, ''];
  916. if($data['type'] == self::TYPE_THREE){
  917. //通过后弃审
  918. if(! isset(self::$opt_case_reject[$data['opt_case']])) return [false, ''];
  919. //具体方法
  920. $function = self::$opt_case_reject[$data['opt_case']];
  921. //流水
  922. $function2 = self::$reject_record[$data['opt_case']] ?? '';
  923. try{
  924. DB::beginTransaction();
  925. //更新单据的状态
  926. list($bool,$msg) = $this->$function($data);
  927. if(! $bool){
  928. DB::rollBack();
  929. return [false, ''];
  930. }
  931. $order = $msg;
  932. if($function2) {
  933. //流水
  934. $boolean = $this->$function2($data,$order);
  935. if(! $boolean) {
  936. DB::rollBack();
  937. return [false, ''];
  938. }
  939. //库存
  940. $bool = $this->changeInventoryReject($data,$order);
  941. if(! $bool){
  942. DB::rollBack();
  943. return [false, ''];
  944. }
  945. }
  946. DB::commit();
  947. return [true, ''];
  948. }catch (\Throwable $exception){
  949. DB::rollBack();
  950. return [false, $exception->getLine(). $exception->getMessage()];
  951. }
  952. }else{
  953. //具体方法
  954. $function = self::$opt_case[$data['opt_case']] ?? "";
  955. $record = self::$record[$data['opt_case']] ?? "";
  956. $create = self::$create[$data['opt_case']] ?? "";
  957. try{
  958. DB::beginTransaction();
  959. list($bool,$msg) = $this->$function($data);
  960. if(! $bool){
  961. DB::rollBack();
  962. return [false, $msg];
  963. }
  964. $order = $msg;
  965. if($record) {
  966. //流水
  967. $bool = $this->$record($data, $order);
  968. if(! $bool) {
  969. DB::rollBack();
  970. return [false, $msg];
  971. }
  972. //库存
  973. $bool = $this->changeInventory($data, $order);
  974. if(! $bool) {
  975. DB::rollBack();
  976. return [false, $msg];
  977. }
  978. }
  979. if($create) {
  980. $bool = $this->$create($order);
  981. if(! $bool) {
  982. DB::rollBack();
  983. return [false, $msg];
  984. }
  985. }
  986. DB::commit();
  987. return [true, ''];
  988. }catch (\Throwable $exception){
  989. DB::rollBack();
  990. return [false, $exception->getMessage().$exception->getLine()];
  991. }
  992. }
  993. }
  994. }