FinancialManager.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. namespace app\cxinv\model;
  3. use think\facade\Log;use think\Model;use think\model\concern\SoftDelete;
  4. class FinancialManager extends Base{
  5. use SoftDelete;
  6. protected $schema=[
  7. 'id'=>'int',//主键,自动递增
  8. 'code'=>'string',//订单或记录的唯一标识符
  9. 'invoiceCode'=>'string',//订单或记录的唯一标识符
  10. 'type'=>'int',//记录类型 1入库2出库 3入库红冲 4 出库红冲
  11. 'source'=>'int',//数据来源,1结算 2 线下订单
  12. 'channel'=>'int',//渠道 1订单导入 2 非订单商品导入 3 c端无发票导入
  13. 'seller_code'=>'string',//卖方代码
  14. 'seller_name'=>'string',//卖方名称
  15. 'buyer_code'=>'string',//买方代码
  16. 'buyer_name'=>'string',//买方名称
  17. 'orderCode'=>'string',//订单编号
  18. 'cxCode'=>'string',//客户编号
  19. 'poCode'=>'string',//采购订单编号
  20. 'platform_type'=>'int',//平台类型,1ToB 2ToC
  21. 'goodType'=>'int',//商品类型 1库存 2非库存 3采返
  22. 'goodNo'=>'string',//商品编号
  23. 'goodName'=>'string',//商品名称
  24. 'unit'=>'string',//商品单位
  25. 'num'=>'int',//商品数量
  26. 'goodPrice'=>'decimal',//商品单价
  27. 'totalPrice'=>'decimal',//商品总价
  28. 'cat_code'=>'string',//商品分类代码
  29. 'cat_name'=>'string',//商品分类名称
  30. 'tax'=>'decimal',//税率或税费
  31. 'inv_fee'=>'decimal',//发票费用
  32. 'inv_seller_code'=>'string',//发票卖方代码
  33. 'inv_seller_name'=>'string',//发票卖方名称
  34. 'inv_buyer_code'=>'string',//发票买方代码
  35. 'inv_buyer_name'=>'string',//发票买方名称
  36. 'inv_number'=>'string',//发票编号
  37. 'inv_type'=>'string',//发票类型
  38. 'inv_item_id'=>'int',//发票项目ID
  39. 'inv_good_name'=>'string',//发票商品名称
  40. 'inv_cat_code'=>'string',//发票商品分类代码
  41. 'inv_spec'=>'string',//发票商品规格
  42. 'inv_unit'=>'string',//发票商品单位
  43. 'inv_num'=>'decimal',//发票商品数量
  44. 'inv_subprice'=>'decimal',//发票商品子项单价
  45. 'inv_subtotal'=>'decimal',//发票商品子项总价
  46. 'inv_tax'=>'decimal',//发票税额
  47. 'inv_tax_total'=>'decimal',//发票总税额
  48. 'inv_price'=>'decimal',//发票单价
  49. 'inv_total'=>'decimal',//发票总价
  50. 'cat_diff'=>'int',//分类差异
  51. 'tax_diff'=>'int',//税费差异
  52. 'remark'=>'string',//备注或说明
  53. 'status'=>'int',//1 待处理 2 待审核
  54. 'manager_status'=>'int',//1 正常 2计提 3 异常
  55. 'balance_num'=>'decimal',//库存数量
  56. 'total_num'=>'decimal',//总库存数量,
  57. 'check_fee'=>'decimal',
  58. 'is_checkOrder'=>'int',
  59. 'apply_id'=>'int',
  60. 'apply_name'=>'string',
  61. 'create_time'=>'datetime',
  62. 'update_time'=>'datetime',
  63. 'delete_time'=>'datetime',
  64. ];
  65. protected $createTime='create_time';
  66. protected $updateTime='update_time';
  67. protected $deleteTime='delete_time';
  68. public static $ManagerType=[1=>'入库',2=>'出库'];
  69. public static $ManagerSource=[1=>'结算',2=>'线下订单'];
  70. public static $PlatformType=[1=>'ToB',2=>'ToC'];
  71. public static $ManagerStatusCn=[1=>'正常',2=>'计提',3=>'异常'];
  72. public function ProductRela(){
  73. return $this->hasMany(ManagerProduct::class,'manager_id','id');
  74. }
  75. public function setErrorRemarkAttr($value,$data){
  76. return $data['manager_status']==3?$value:'';
  77. }
  78. public function CreateData($data){
  79. if(!empty($data)){
  80. switch ($data['channel']){
  81. case 1:
  82. $this->OrderImport($data);
  83. break;
  84. case 2:
  85. $this->OfflineImport($data);
  86. break;
  87. case 3:
  88. $this->CImport($data);
  89. break;
  90. default:
  91. throw new \Exception('导入渠道不存在');
  92. break;
  93. }
  94. }
  95. return true;
  96. }
  97. // 订单导入
  98. public function OrderImport($data){
  99. $data['total_num'] = $data['balance_num'] =$data['inv_num'];
  100. try{
  101. if($data['type']==1){
  102. $product= $this->inProduct($data);
  103. }
  104. if($data['type']==2){
  105. $product= $this->outProduct($data);
  106. }
  107. $data['manager_status']=$data['balance_num']=='0'?1:2;
  108. }catch (\Exception $e){
  109. $data['manager_status'] =3;
  110. $data['error_remark'] = $e->getMessage();
  111. }
  112. $data['status'] = $data['manager_status'] ==1?2:1;
  113. $info=$this->create($data);
  114. if($info->isEmpty()) throw new \Exception('添加失败');
  115. if (isset($product)) ManagerProduct::AddProduct($info->id,$product);
  116. }
  117. // 线下订单导入入库
  118. public function inProduct(&$data){
  119. $productID=[];
  120. try{
  121. $product = FinancialProducts::with(['productStock','ProductsCombind'])->where($this->getCondition($data))->findOrEmpty();
  122. if($product->isEmpty()){
  123. if($data['type']==4) throw new \Exception('红冲未找到财务商品信息');
  124. if($data['channel']==2 || $data['channel']==3) throw new \Exception('入库未找到财务商品信息');
  125. else{
  126. $goodinfo = Good::where('spuCode',$data['goodNo'])->findOrEmpty();
  127. $good_type=3;
  128. if(!$goodinfo->isEmpty()){
  129. $good_type=$goodinfo->isZx==1?3:($goodinfo->is_stock==1?1:2);
  130. }
  131. $product_data=[
  132. 'skuCode'=>$data['goodNo'],
  133. 'goodName'=>$data['goodName'],
  134. 'good_type'=>$good_type,
  135. 'buyer_name'=>$data['buyer_name'],
  136. 'buyer_code'=>$data['buyer_code'],
  137. 'seller_name'=>$data['seller_name'],
  138. 'seller_code'=>$data['seller_code'],
  139. 'good_source'=>1,
  140. 'inv_good_name'=>$data['inv_good_name'],
  141. 'unit'=>$data['inv_unit'],
  142. 'unit_price'=>$data['inv_price'],
  143. 'subunit_price'=>$data['inv_subprice'],
  144. 'unit_weight'=>$data['unit_weight']??0,
  145. 'cat_code'=>$data['inv_cat_code'],
  146. 'cat_tax'=>$data['inv_tax'],
  147. 'inv_type'=>$data['inv_type'],
  148. "is_combind"=>0,
  149. 'basic_status'=>1,
  150. 'spectral'=>'',
  151. 'apply_id'=>$data['apply_id'],
  152. 'apply_name'=>$data['apply_name'],
  153. 'status'=>1
  154. ];
  155. $product = FinancialProducts::create($product_data);
  156. }
  157. }
  158. if($product->is_combin==1){
  159. $rednum=$data['balance_num'];
  160. if($product->ProductsCombind->isEmpty()) throw new \Exception('组合商品未找到明细');
  161. $product->ProductsCombind->each(function ($item) use ($rednum, &$productID) {
  162. ProductStock::AddStock($item->child_id, $rednum * $item->child_num);
  163. $productID[] = ['product_id' => $item->child_id, 'type'=>1,'num' => $rednum * $item->child_num];
  164. });
  165. }else{
  166. ProductStock::AddStock($product->id,$data['balance_num']);
  167. $productID[]=["product_id"=>$product->id,"type"=>1,"num"=>$data['balance_num']];
  168. }
  169. $data['balance_num']="0";
  170. $data['status']=1;
  171. return $productID;
  172. }catch (\Exception $e){
  173. throw new \Exception($e->getMessage());
  174. }
  175. }
  176. // 出库
  177. public function outProduct(&$data){
  178. $productID=[];
  179. try{
  180. if ($data['channel'] == 1) {
  181. $this->processSingleProduct($data, $productID);
  182. } else {
  183. if (isset($data['relaArr']) && is_array($data['relaArr'])) {
  184. foreach ($data['relaArr'] as $item) {
  185. if (!isset($item['id']) || !isset($item['num'])) {
  186. throw new \Exception('relaArr 中的元素缺少 id 或 num');
  187. }
  188. $this->processSingleProduct($item, $productID, $data);
  189. }
  190. } else {
  191. throw new \Exception('relaArr 为空或格式不正确');
  192. }
  193. }
  194. }catch (\Exception $e){
  195. throw new \Exception($e->getMessage());
  196. }
  197. return $productID;
  198. }
  199. // 单商品处理
  200. private function processSingleProduct($data, &$productID, &$mainData = null) {
  201. $product = FinancialProducts::with(['productStock',"ProductsCombind"])->findOrEmpty($data['id']);
  202. if (!$product->isEmpty()) {
  203. if($mainData['type']!=2 && $product->basic_status==2) throw new \Exception($product->skuCode.'商品不可为预估成本商品');
  204. $rednum = $data['num'];
  205. if ($product->residue_stock < $data['num']) {
  206. if($mainData['type']==4) throw new \Exception($product->skuCode.'商品库存不足');
  207. $rednum = $product->residue_stock;
  208. if ($mainData !== null) {
  209. $mainData['balance_num'] = bcsub($mainData['balance_num'], $product->residue_stock, 8);
  210. }
  211. } else {
  212. if ($mainData !== null) {
  213. $mainData['balance_num'] = bcsub($mainData['balance_num'], $data['num'], 8);
  214. }
  215. }
  216. if($product->is_combind==1 ){
  217. if($product->ProductsCombind->isEmpty()) throw new \Exception('组合商品未找到明细');
  218. $product->ProductsCombind->each(function ($item) use ($rednum, &$productID) {
  219. ProductStock::OutStock($item->child_id, $rednum * $item->child_num);
  220. $productID[] = ['product_id' => $item->child_id, 'type'=>2,'num' => $rednum * $item->child_num];
  221. });
  222. }else{
  223. ProductStock::OutStock($product->id, $rednum);
  224. $productID[] = ['product_id' => $product->id, 'type'=>2,'num' => $rednum];
  225. }
  226. // $mainData['manager_status']=$mainData['balance_num']=='0'?1:2;
  227. } else {
  228. throw new \Exception('出库未找到财务商品信息');
  229. }
  230. }
  231. public function getCondition($data){
  232. $where=[];
  233. if($data['channel']==1 && (empty($data['relaArr'])|| !isset($data['relaArr']))) $where=[
  234. 'skuCode'=>$data['goodNo'],
  235. 'buyer_code'=>$data['buyer_code'],
  236. 'subunit_price'=>$data['inv_subprice'],
  237. 'inv_type'=>$data['inv_type'],
  238. 'cat_code'=>$data['inv_cat_code'],
  239. "basic_status"=>1
  240. ];
  241. else $where[]=[
  242. 'id','in',array_column($data['relaArr'],"id")
  243. ];
  244. return $where;
  245. }
  246. // 线下订单导入
  247. public function OfflineImport($data){
  248. $data['total_num'] = $data['balance_num'] =$data['inv_num'];
  249. try{
  250. if($data['type']==1){
  251. $product=$this->inProduct($data);
  252. }
  253. if($data['type']==2){
  254. $product=$this->outProduct($data);
  255. }
  256. $data['manager_status']=$data['balance_num']=='0'?1:2;
  257. }catch (\Exception $e){
  258. $data['manager_status'] =3;
  259. $data['error_remark'] = $e->getMessage();
  260. }
  261. $data['status'] = $data['manager_status'] ==1?2:1;
  262. $info=$this->create($data);
  263. if($info->isEmpty()) throw new \Exception('添加失败');
  264. if(isset($product) && !empty($product))ManagerProduct::AddProduct($info->id,$product);
  265. }
  266. // c端无发票导入
  267. public function CImport($data){
  268. $data['total_num'] = $data['balance_num'] =$data['num'];
  269. try{
  270. if($data['type']==1){
  271. $product=$this->inProduct($data);
  272. }
  273. if($data['type']==2){
  274. $product=$this->outProduct($data);
  275. }
  276. $data['manager_status']=$data['balance_num']=='0'?1:2;
  277. }catch (\Exception $e){
  278. $data['manager_status'] =3;
  279. $data['error_remark'] = $e->getMessage();
  280. }
  281. $data['status'] = $data['manager_status'] ==1?2:1;
  282. $info=$this->create($data);
  283. if($info->isEmpty()) throw new \Exception('添加失败');
  284. if(isset($product) && !empty($product))ManagerProduct::AddProduct($info->id,$product);
  285. }
  286. // 校验数据
  287. public function CheckDatas($data){
  288. $error=[];
  289. $invoice = PayInvoice::where('hpNo',$data['invoiceCode'])->findOrEmpty();
  290. if($invoice->isEmpty()){
  291. $invoice = InvoicePool::where("invNo",$data['invoiceCode'])->findOrEmpty();
  292. if($invoice->isEmpty()){
  293. $error[] = ['code'=>$data['invoiceCode'],'msg'=>'发票号未找到数据'];
  294. }
  295. }
  296. if(!$invoice->isEmpty() && $invoice->status!=4) $error[] = ['code'=>$data['invoiceCode'],'msg'=>'发票状态不正确'];
  297. $order = CgdInfo::where("sequenceNo",$data['orderCode'])->findOrEmpty();
  298. if($order->isEmpty()){
  299. $order = QrdInfo::where("sequenceNo",$data['orderCode'])->findOrEmpty();
  300. if($order->isEmpty())$error[] = ['code'=>$data['orderCode'],'msg'=>'订单未找到数据'];
  301. }
  302. if(!$order->isEmpty() && $order->cxCode!=$data['cxCode']) $error[] = ['code'=>$data['orderCode'],'msg'=>'订单主单号不一致'];
  303. return $error;
  304. }
  305. public static function onAfterWrite(Model $model)
  306. {
  307. $changedData = $model->getChangedData();
  308. $origin = $model->getOrigin();
  309. Log::info("changeData:".json_encode($changedData,JSON_UNESCAPED_UNICODE));
  310. Log::info("origin:".json_encode($origin,JSON_UNESCAPED_UNICODE));
  311. if(isset($origin['manager_status']) && $origin['manager_status']==2 && $origin['status']==1&& isset($origin['is_checkOrder'])&& $origin['is_checkOrder']==0){
  312. if($changedData['is_checkOrder']==1 && $changedData['status']==2){
  313. $check=[
  314. "checkCode"=>makeNo("CWTZ"),
  315. "code"=>$model->code,
  316. "itemid"=>$model->inv_item_id,
  317. "goodNo"=>$model->goodNo,
  318. 'goodType'=>$model->goodType,
  319. "goodName"=>$model->goodName,
  320. "spec"=>$model->inv_spec,
  321. "unit"=>$model->inv_unit,
  322. "company_code"=>$model->seller_code,
  323. "company_name"=>$model->seller_name,
  324. "num"=>0, // 出库调整金额
  325. "price"=>$model->inv_price,
  326. "subprice"=>$model->inv_subprice,
  327. "check_fee"=>$model->check_fee,
  328. "check_uid"=>$changedData['uid'],
  329. "fz_date"=>date("Ym"),
  330. "check_uname"=>$changedData['uname'],
  331. ];
  332. FinancialCheck::create($check);
  333. }
  334. }
  335. }
  336. }