EngineerSettlementLogic.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeadmin快速开发前后端分离管理后台(PHP版)
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
  8. // | github下载:https://github.com/likeshop-github/likeadmin
  9. // | 访问官网:https://www.likeadmin.cn
  10. // | likeadmin团队 版权所有 拥有最终解释权
  11. // +----------------------------------------------------------------------
  12. // | author: likeadminTeam
  13. // +----------------------------------------------------------------------
  14. namespace app\adminapi\logic\master_worker;
  15. use app\common\enum\worker\WorkerAccountLogEnum;
  16. use app\common\logic\WorkerAccountLogLogic;
  17. use app\common\model\finance\MasterWorkerCaseOutLog;
  18. use app\common\model\financial\FinancialPaymentRecords;
  19. use app\common\model\financial\MasterSettlementDetails;
  20. use app\common\model\master_worker\EngineerSettlement;
  21. use app\common\logic\BaseLogic;
  22. use app\common\model\master_worker\MasterWorker;
  23. use think\facade\Db;
  24. /**
  25. * EngineerSettlement逻辑
  26. * Class EngineerSettlementLogic
  27. * @package app\adminapi\logic
  28. */
  29. class EngineerSettlementLogic extends BaseLogic
  30. {
  31. /**
  32. * @notes 添加
  33. * @param array $params
  34. * @return bool
  35. * @author likeadmin
  36. * @date 2024/11/15 17:21
  37. */
  38. public static function add(array $params, $adminId): bool
  39. {
  40. Db::startTrans();
  41. try {
  42. foreach ($params as $param) {
  43. //$param['payment_status'] == 1 默认上传的都是已经打款了
  44. $engineerSettlement = EngineerSettlement::where('master_worker_id', $param['master_worker_id'])
  45. ->where('batch_number', $param['batch_number'])
  46. ->where('is_export', 1)
  47. ->where('is_deduction', 0)
  48. ->where('payment_status', 0)
  49. ->findOrEmpty();
  50. if(!$engineerSettlement->isEmpty()){
  51. $masterWorker = MasterWorker::where('id', $param['master_worker_id'])->where('worker_number', $param['worker_number'])->find();
  52. if($masterWorker && $masterWorker->user_money >= $param['total_settlement_amount']){
  53. //$masterWorker->user_money = $masterWorker->user_money - $param['total_settlement_amount'];
  54. //$masterWorker->save();
  55. //实发扣款
  56. if($param['final_settlement_amount']){
  57. $final_res = WorkerAccountLogLogic::masterAccountLog($param['master_worker_id'],(float)$param['final_settlement_amount'],WorkerAccountLogEnum::UM_DEC_ADMIN,WorkerAccountLogEnum::DEC, '实发扣款','',[
  58. 'engineerSettlementId'=>$engineerSettlement->id,
  59. 'batch_number'=>$param['batch_number'],
  60. ]);
  61. if($final_res->id){
  62. MasterSettlementDetails::create([
  63. 'account_log_id' => $final_res->id,
  64. 'payment_time' => $param['settlement_time']??date('Y-m-d H:i:s'),
  65. 'batch_number' => $param['batch_number'],
  66. 'status' => 3,
  67. 'master_worker_id' => $param['master_worker_id'],
  68. 'amount_change' => -(float)$param['final_settlement_amount'],
  69. 'change_time' => time(),
  70. 'remark' => '实发扣款'
  71. ]);
  72. }
  73. }
  74. //直接扣款
  75. if($param['deduction_amount']){
  76. $deduction_res = WorkerAccountLogLogic::masterAccountLog($param['master_worker_id'],(float)$param['deduction_amount'],WorkerAccountLogEnum::UM_DEC_ADMIN,WorkerAccountLogEnum::DEC, '直接扣款','',[
  77. 'engineerSettlementId'=>$engineerSettlement->id,
  78. 'batch_number'=>$param['batch_number'],
  79. ]);
  80. if($deduction_res->id){
  81. MasterSettlementDetails::create([
  82. 'account_log_id' => $deduction_res->id,
  83. 'payment_time' => $param['settlement_time']??date('Y-m-d H:i:s'),
  84. 'batch_number' => $param['batch_number'],
  85. 'status' => 3,
  86. 'master_worker_id' => $param['master_worker_id'],
  87. 'amount_change' => -(float)$param['deduction_amount'],
  88. 'change_time' => time(),
  89. 'remark' => '直接扣款'
  90. ]);
  91. }
  92. }
  93. // 提现记录
  94. $case_remark = '应发:'.$param['total_settlement_amount'].($param['deduction_amount']>0?',扣款:'.$param['deduction_amount'].',扣款说明:'.$param['deduction_describe']:'').',实发:'.$param['final_settlement_amount'];
  95. MasterWorkerCaseOutLog::create([
  96. 'sn' => generate_sn(MasterWorkerCaseOutLog::class,'sn'),
  97. 'worker_id' => $masterWorker->id,
  98. 'title' => '财务打款',
  99. 'change_amount' => $param['total_settlement_amount'],
  100. 'review_status' => 3,
  101. 'admin_id' => $adminId,
  102. 'remark' => '财务打款-'.$case_remark,
  103. 'create_time' => time(),
  104. 'update_time' => time(),
  105. ]);
  106. $engineerSettlement->deduction_amount = $param['deduction_amount']??0;
  107. $engineerSettlement->deduction_describe = $param['deduction_describe']??'';
  108. $engineerSettlement->final_settlement_amount = $param['final_settlement_amount']??0;
  109. $engineerSettlement->settlement_time = $param['settlement_time']??date('Y-m-d H:i:s');
  110. $engineerSettlement->settlement_details_remarks = $param['settlement_details_remarks']??'';
  111. $engineerSettlement->new_balance = $masterWorker->user_money;
  112. $engineerSettlement->payment_status = 1;
  113. $engineerSettlement->is_export = 2;
  114. $engineerSettlement->admin_id = $adminId;
  115. $engineerSettlement->is_deduction = 1;
  116. $engineerSettlement->save();
  117. MasterSettlementDetails::where('master_worker_id', $param['master_worker_id'])
  118. ->where('batch_number', $param['batch_number'])
  119. ->where('status', 2)
  120. ->update([
  121. 'payment_time' => $param['settlement_time']??date('Y-m-d H:i:s'),
  122. 'status'=>3, 'remark'=>''
  123. ]);
  124. }else{
  125. $engineerSettlement->deduction_amount = $param['deduction_amount']??0;
  126. $engineerSettlement->deduction_describe = $param['deduction_describe']??'';
  127. $engineerSettlement->final_settlement_amount = $param['final_settlement_amount']??0;
  128. $engineerSettlement->settlement_time = $param['settlement_time']??date('Y-m-d H:i:s');
  129. $engineerSettlement->settlement_details_remarks = ($param['settlement_details_remarks']??'').'-余额不足';
  130. $engineerSettlement->new_balance = $masterWorker->user_money;
  131. $engineerSettlement->payment_status = 1;
  132. $engineerSettlement->is_export = 2;
  133. $engineerSettlement->admin_id = $adminId;
  134. $engineerSettlement->is_deduction = 2;
  135. $engineerSettlement->save();
  136. //throw new \Exception('工程师不存在、余额不足');
  137. }
  138. }
  139. }
  140. $payment_num = MasterSettlementDetails::where('batch_number', $params[0]['batch_number'])->where('status','<', 3)->count('id');
  141. FinancialPaymentRecords::where('batch_number', $params[0]['batch_number'])
  142. ->where('upload_status', 1)
  143. ->where('payment_status', 1)
  144. ->update([
  145. 'upload_status' => 3,
  146. 'payment_status'=> $payment_num>0?2:3
  147. ]);
  148. Db::commit();
  149. return true;
  150. } catch (\Exception $e) {
  151. Db::rollback();
  152. self::setError($e->getMessage());
  153. return false;
  154. }
  155. }
  156. /**
  157. * @notes 编辑
  158. * @param array $params
  159. * @return bool
  160. * @author likeadmin
  161. * @date 2024/11/15 17:21
  162. */
  163. public static function edit(array $params): bool
  164. {
  165. Db::startTrans();
  166. try {
  167. EngineerSettlement::where('id', $params['id'])->update([
  168. 'master_worker_id' => $params['master_worker_id'],
  169. 'worker_number' => $params['worker_number'],
  170. 'engineer_name' => $params['engineer_name'],
  171. 'original_balance' => $params['original_balance'],
  172. 'total_settlement_amount' => $params['total_settlement_amount'],
  173. 'deduction_amount' => $params['deduction_amount'],
  174. 'final_settlement_amount' => $params['final_settlement_amount'],
  175. 'settlement_time' => $params['settlement_time'],
  176. 'settlement_details_remarks' => $params['settlement_details_remarks'],
  177. ]);
  178. Db::commit();
  179. return true;
  180. } catch (\Exception $e) {
  181. Db::rollback();
  182. self::setError($e->getMessage());
  183. return false;
  184. }
  185. }
  186. /**
  187. * @notes 删除
  188. * @param array $params
  189. * @return bool
  190. * @author likeadmin
  191. * @date 2024/11/15 17:21
  192. */
  193. public static function delete(array $params): bool
  194. {
  195. return EngineerSettlement::destroy($params['id']);
  196. }
  197. /**
  198. * @notes 获取详情
  199. * @param $params
  200. * @return array
  201. * @author likeadmin
  202. * @date 2024/11/15 17:21
  203. */
  204. public static function detail($params): array
  205. {
  206. return EngineerSettlement::findOrEmpty($params['id'])->toArray();
  207. }
  208. public static function downloadLists(): array
  209. {
  210. return [EngineerSettlement::where('id','>',0)
  211. ->field(['id', 'master_worker_id', 'worker_number', 'engineer_name', 'original_balance', 'total_settlement_amount', 'deduction_amount', 'final_settlement_amount', 'settlement_time', 'settlement_details_remarks'])
  212. ->order(['id' => 'desc'])
  213. ->select()
  214. ->toArray()[0]];
  215. }
  216. public static function engineerSettlementValidate($params)
  217. {
  218. //
  219. //上传表格中所有批号必须相同
  220. //$engineerSettlement 中每条都不能为空
  221. // $masterWorker->user_money >= $param['total_settlement_amount']
  222. //$param['total_settlement_amount'] = $params['final_settlement_amount']+deduction_amount;
  223. // 该批次是否为待上传
  224. try {
  225. if(empty($params)) throw new \Exception('表格数据为空');
  226. $master_worker_ids = array_column($params, 'master_worker_id');
  227. //上传表格中所有 master_worker_id 不能存在重复
  228. array_filter(array_count_values($master_worker_ids), function($count) {
  229. if($count>1) throw new \Exception('上传表格中所有工程师不能存在重复');
  230. });
  231. //上传表格中所有批号必须相同
  232. if(count(array_unique(array_column($params, 'batch_number')))>1){
  233. throw new \Exception('上传表格中所有批号必须同批次');
  234. }
  235. $batch_number = $params[0]['batch_number'];
  236. // 该批次是否为待上传
  237. $financialRecords = FinancialPaymentRecords::where('batch_number', $batch_number)->where('upload_status', 1)->findOrEmpty();
  238. if($financialRecords->isEmpty()){
  239. throw new \Exception('该批次不存在或已取消/已上传,禁止上传');
  240. }
  241. // 每条数据在表 EngineerSettlement 中不能为空即 下载记录必须存在
  242. $engineer_worker_ids = EngineerSettlement::where('batch_number', $batch_number)
  243. ->where('is_export', 1)
  244. ->where('is_deduction', 0)
  245. ->where('payment_status', 0)
  246. ->column('master_worker_id');
  247. $masterWorkers = MasterWorker::where('id', 'in',$master_worker_ids)->column('user_money', 'id');
  248. foreach ($params as &$param) {
  249. $param['deduction_amount'] = $param['deduction_amount']??0;
  250. $param['deduction_describe'] = $param['deduction_describe']??'';
  251. $param['settlement_details_remarks'] = $param['settlement_details_remarks']??'';
  252. if(!isset($param['total_settlement_amount']) || $param['total_settlement_amount']<0){
  253. throw new \Exception('应付金额不能为空或负数:'.$param['master_worker_id']);
  254. }
  255. if(!isset($param['final_settlement_amount']) || $param['final_settlement_amount']<0){
  256. throw new \Exception('实付金额不能为空或负数:'.$param['master_worker_id']);
  257. }
  258. if(isset($param['deduction_amount']) && $param['deduction_amount']<0){
  259. throw new \Exception('扣款金额不能为负数:'.$param['master_worker_id']);
  260. }
  261. if($param['deduction_amount'] > 0 && (!isset($param['deduction_describe']) || empty($param['deduction_describe']))){
  262. throw new \Exception('扣款存在,扣款说明不能为空:'.$param['master_worker_id']);
  263. }
  264. if(!in_array($param['master_worker_id'], $engineer_worker_ids)) throw new \Exception('下载记录不存在:'.$param['master_worker_id']);
  265. //判断日期时间格式是否正确 2024/1/1 00:00:00 或 2024-1-1 00:00:00
  266. if(
  267. isset($param['settlement_time'])
  268. && !preg_match('/^[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$/', $param['settlement_time'])
  269. && !preg_match('/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$/', $param['settlement_time'])
  270. && !preg_match('/^[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2}$/', $param['settlement_time'])
  271. && !preg_match('/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/', $param['settlement_time'])
  272. ){
  273. throw new \Exception('日期时间格式错误:'.$param['master_worker_id']);
  274. }
  275. $param['settlement_time'] = isset($param['settlement_time'])?date('Y-m-d H:i:s', strtotime($param['settlement_time'])):date('Y-m-d H:i:s');
  276. if(!is_numeric($param['original_balance']) || !is_numeric($param['total_settlement_amount']) || !is_numeric($param['deduction_amount']) || !is_numeric($param['final_settlement_amount'])){
  277. throw new \Exception('金额格式错误:'.$param['master_worker_id']);
  278. }
  279. if (bccomp((float)$param['total_settlement_amount'], bcadd((float)$param['final_settlement_amount'], (float)$param['deduction_amount'], 2), 2) !== 0) {
  280. throw new \Exception('金额计算错误:' . $param['master_worker_id']);
  281. }
  282. if(!preg_match('/^[0-9]*$/', $param['worker_number'])){
  283. throw new \Exception('工程师编号格式错误:'.$param['master_worker_id']);
  284. }
  285. if(!preg_match('/^[0-9]*$/', $param['master_worker_id'])){
  286. throw new \Exception('工程师ID格式错误:'.$param['master_worker_id']);
  287. }
  288. if($masterWorkers[$param['master_worker_id']] < $param['total_settlement_amount']) throw new \Exception('余额不足-'.$param['master_worker_id']);
  289. }
  290. return $params;
  291. } catch (\Exception $e) {
  292. throw new \Exception($e->getMessage());
  293. }
  294. }
  295. public static function insertSettlementDetails()
  296. {
  297. $insert_sql = "INSERT INTO la_master_settlement_details (account_log_id, master_worker_id, amount_change, change_time)
  298. SELECT
  299. a.id,
  300. a.worker_id AS master_worker_id,
  301. CASE
  302. WHEN a.change_amount > 0 AND a.action = 1 THEN a.change_amount
  303. WHEN a.change_amount > 0 AND a.action = 2 THEN -a.change_amount
  304. ELSE 0
  305. END AS amount_change,
  306. a.create_time
  307. FROM
  308. `la_master_worker_account_log` a
  309. LEFT JOIN
  310. `la_master_settlement_details` b ON a.id = b.account_log_id
  311. WHERE
  312. a.change_object = 1
  313. AND b.account_log_id IS NULL";
  314. return Db::execute($insert_sql);
  315. }
  316. }