<?php /** * v2 账单模块 */ namespace app\em\controller; use app\admin\controller\Base; use app\em\model\EmInvoice; use app\em\model\EmInvoiceUseage; use app\em\model\EmPayment; use app\em\model\EmPaymentInvoice; use app\em\model\EmPaymentInvoiceBalance; use app\em\model\EmSettle; use app\em\model\EmSettleInvoice; use app\em\model\EmSettleInvoiceBalance; use app\em\model\UseageDetail; use think\facade\Request; use think\facade\Session; class Invoice extends Base { //账单列表 public function index(){ $map=[]; //权限检测 $user = Session::get('user'); if(!$user['is_admin']){ $permissionData=check_data(); if($permissionData){ $map[]=$permissionData; } } $search_text = Request::get('search_text'); $search_type = Request::get('search_type'); $payment_status = Request::get('payment_status'); $settle_status = Request::get('settle_status'); if($search_text){ switch ($search_type) { case '1': $this->assign('search_text',$search_text); $map[]=['inv.invoice_id','like',"%$search_text%"]; $this->assign('search_type',$search_type); break; case '2': $this->assign('search_text',$search_text); $searchArr = explode(',',$search_text); foreach($searchArr as &$v){ $v = '%'.$v.'%'; } $map[] = ['station.station_name','like',$searchArr,'or']; $this->assign('search_type',$search_type); break; case '3': $this->assign('search_text',$search_text); $map[]=['em.em_numb','like',"%$search_text%"]; $this->assign('search_type',$search_type); break; } }else{ $this->assign('search_type',''); $this->assign('search_text',''); } //缴费状态 if($payment_status !== '' || $settle_status !== ''){ $pstatus = $payment_status === '' ? '0' : $payment_status; $sstatus = $settle_status === '' ? '0' : $settle_status; $map[] = ['inv.status','=',$pstatus.$sstatus.'0']; $this->assign('payment_status', $payment_status); $this->assign('settle_status', $settle_status); } else { $this->assign('payment_status',''); $this->assign('settle_status',''); } //抄表时间查询条件 $dateStart = strtotime(Request::get('date_start')); $dateEnd = strtotime(Request::get('date_end')); //区间查询 if( !empty($dateStart) && !empty($dateEnd) ){ $map[] = ['eu.current_date','between',[$dateStart,$dateEnd]]; $this->assign('date_start',Request::get('date_start')); $this->assign('date_end',Request::get('date_end')); } elseif (!empty($dateStart) && empty($dateEnd)){ $map[] = ['eu.current_date','>',$dateStart]; $this->assign('date_start',Request::get('date_start')); $this->assign('date_end',''); } elseif (empty($dateStart) && !empty($dateEnd)){ $map[] = ['eu.current_date','<',$dateEnd]; $this->assign('date_end',Request::get('date_end')); $this->assign('date_start',''); }else{ $this->assign('date_start',''); $this->assign('date_end',''); } $page =Request::param('page')?Request::param('page'):1; $limit = Request::param('limit')?Request::param('limit'):10; $emInvModel = new EmInvoice; $data = $emInvModel->getInvoiceList($map,$page,$limit); foreach ( $data as $key => &$v) { $v['status']=parseStatus($v['status']); } $InvoiceCount = $emInvModel->getInvoiceCount($map); if(Request::param('page')){ return ['code'=>0,'msg'=>'','count'=>$InvoiceCount,'data'=>$data]; } return $this->fetch(); } //查看账单信息 public function detail(){ $inv_id = Request::param('id'); $invInfo = (new EmInvoice)->getInvoiceDetail($inv_id); $this->assign('inv',$invInfo); return $this->fetch(); } //创建一个账单 public function createInvoice($useage_id){ $um = (new \app\em\model\Useage)->getEmInfoByUseageId($useage_id)->toArray(); return $this->create($um); } //创建账单 public function create($um){ /// 如果是普通表 则 if($um['pricing_type'] == 1){ return $this->createInvoiceStdType($um); } else if($um['pricing_type'] == 2){ return $this->createInvoiceSpecialType($um); } } /** * 生成账单号 * @return string * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ private function getInvoiceId(){ $inv = EmInvoice::field('id')->order('id desc,create_time desc')->find(); if(!$inv) $id = 1; else $id = $inv->id + 1; return "ZD".date('Ymd').zero($id); } //普通读表生成账单 public function createInvoiceStdType($uData){ $inv = new EmInvoice(); $inv->type = 4; $inv->rate = $uData['rate']; $inv->repo_numb = round(($uData['current_sum_numb'] - $uData['last_sum_numb']) * $uData['rate'],3); $inv->payment_amount = $inv->payment_balance = $inv->repo_numb * $uData['pay_price']; //结算信息 $inv->settle_amount = $inv->settle_balance = $inv->repo_numb * $uData['settle_price']; $inv->status = '000'; $inv->invoice_id = $this->getInvoiceId(); //获取账户ID $inv->account_id = (new Account())->getAccountId($uData['em_id']); //保存 并且更新抄表单与账单关联表 if($inv->save()){ $eiu = new EmInvoiceUseage(); $eiu->invoice_id = $inv->invoice_id; $eiu->useage_id = $uData['useage_id']; $eiu->save(); } //更新电表账户 $useage = \app\em\model\Useage::get(['useage_id' => $uData['useage_id']]); $account = new Account(); $account->updateAmount($useage->em_id,$inv->payment_amount,0); return $inv; } //峰谷表生成账单 public function createInvoiceSpecialType($uData){ $inv = new EmInvoice(); $inv->type = 1; $inv->rate = $uData['rate']; //获取峰谷表抄表明细 $uds = UseageDetail::where(['useage_id'=>$uData['useage_id']])->select()->toArray(); //计算总价信息 //需要计算4个属性 各分段上一次 档次 repo amount $last_numb = 0; $curr_numb = 0; $amount = 0; $repo_numb = 0; foreach ($uds as $v){ $last_numb += $v['last_numb']; $curr_numb += $v['current_numb']; $amount += (int)($v['current_numb'] - $v['last_numb']) * $v['price']; $repo_numb += (int)($v['current_numb'] - $v['last_numb']); } //曝移动电量 $inv->repo_numb = ($curr_numb - $last_numb) * $uData['rate']; //缴费信息 $inv->payment_amount = $inv->payment_balance = $amount * $uData['rate']; //结算信息 $inv->settle_amount = $inv->settle_balance = $repo_numb * $uData['rate'] *$uData['settle_price']; $inv->status = '000'; $inv->invoice_id = $this->getInvoiceId(); $inv->account_id = (new Account())->getAccountId($uData['em_id']); //更新抄表单的status $useage = \app\em\model\Useage::get(['useage_id'=>$uData['useage_id']]); $useage->status = 2; $useage->save(); $inv->cert_id = $useage->photo_id; //保存 并且更新抄表单与账单关联表 if($inv->save()){ $eiu = new EmInvoiceUseage(); $eiu->invoice_id = $inv->invoice_id; $eiu->useage_id = $uData['useage_id']; $eiu->save(); } return $inv; } public function updatePayment(){ $data = Request::param(); $inv = EmInvoice::get(['id'=>$data['id']]); if(!$inv) return json(['status'=>0,'message'=>'不存在抄表单ID,无法更新缴费金额']); if($data['amount'] > 0 && $inv->is_add_condition != 1){ $inv->payment_amount = $data['amount']; $inv->payment_balance = $data['amount']; $inv->is_add_condition = 1; } if($inv->save()){ return json(['status'=>1,'message'=>'缴费金额已经更新']); } } //账单合并列表 public function mergeList(){ $ids = Request::param('ids'); $idsArr = []; if(!empty($ids)){ $idsArr= explode('_',$ids); } $data = (new EmInvoice)->getListByInvIds($idsArr); $payment_amount = 0; $settle_amount = 0; foreach ($data as $v){ $v->settle_amount = $v->settle_amount ?:0; $payment_amount += $v->payment_amount; $settle_amount += $v->settle_amount; } $this->assign('data',$data); $this->assign('payment_amount',$payment_amount); $this->assign('settle_amount',$settle_amount); return $this->fetch('merge_list'); } /** * 账单触发销账,invoice_id 1:n payment_id * @param $account_id * @param $invoice_id * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException * @return mixed */ public function writeOffFromInvoice($invoice_id,$account_id){ //获取账单对象 $invoice = EmInvoice::field('id,invoice_id,payment_amount,payment_balance') ->where('invoice_id','=',$invoice_id)->find(); //查询关系表中与当前invoice_id相关联的payment_id $model = new EmPaymentInvoice; $payments = $model->alias('epi')->field('epi.payment_id') ->leftJoin(['em_payment'=>'ep'],'epi.payment_id = ep.payment_id') ->leftJoin(['em_payment_invoice_balance'=>'epib'],'epib.invoice_id=epi.invoice_id') ->where('epib.balance','>',0) ->where('epi.invoice_id','=',$invoice_id)->select(); //如果没有找到记录 证明并没有形成对应关系 if($payments->isEmpty()) { //查询是否有未缴费的缴费单存在 $payments = EmPayment::field('payment_id')->where('account_id','=',$account_id) ->where('balance','neq',0) ->order('payment_id asc') ->select(); if($payments->isEmpty()) { return '没有销账的缴费单!'; } } $paymentIds = []; foreach ($payments as $payment){ $paymentIds[] = $payment->payment_id; } $invsIds = [ 'invoice_id' => $invoice->invoice_id ]; //开始销账 return $this->writeOff($paymentIds,$invsIds); } //从缴费单消账单 public function writeOffFromPayment($account_id,$payment_id){ //获取缴费单对象 $payment = EmPayment::where('payment_id','=',$payment_id)->find(); //获取关联的账单对象 $invs = (new EmInvoice())->alias('ei')->field('ei.invoice_id') ->leftJoin(['em_payment_invoice'=>'epi'],'epi.invoice_id = ei.invoice_id') ->where('epi.payment_id','=',$payment_id) ->where('ei.payment_balance','neq',0) ->order('ei.invoice_id asc') ->select(); $invsArr = []; //更新缴费单状态 if($invs->isEmpty()){ $payment->status = 4; $payment->save(); return '审核成功'; } else { foreach ($invs as $inv){ $invsArr[] = $inv->invoice_id; } } //查询可消的额度 $payments_balance = (new EmInvoice)->where('invoice_id','in',$invsArr)->sum('payment_balance'); //如果可以完全销账 则继续销账 if($payment->balance > $payments_balance){ $invs = (new EmInvoice())->field('invoice_id') ->where('account_id','=',$account_id) ->where('payment_balance','neq',0) ->order('invoice_id asc') ->select(); if(!$invs->isEmpty()) { foreach ($invs as $inv){ $invsArr[] = $inv->invoice_id; } } } $paymentIds[] = $payment->payment_id; //处理账户金额 return $this->writeOff($paymentIds,$invsArr); } /** * @param $account_id * @param $invoiceIds * @param $paymentIds * @return mixed */ private function writeOff($paymentIds,$invoiceIds){ //获取可销账缴费单 $payments = EmPayment::where('payment_id','in',$paymentIds)->select(); //获取可销账账单 $invs = EmInvoice::where('invoice_id','in',$invoiceIds)->select(); $result = 0; foreach ($payments as $key => $payment){ if($payment->balance == 0) continue; foreach ($invs as $index => $inv) { $balanceMode = new EmPaymentInvoiceBalance(); $balanceMode->payment_id = $payment->payment_id; if ($inv->payment_balance == 0) continue; $balanceMode->invoice_id = $inv->invoice_id; //如果该缴费单可以完全消除当前账单额度 if ($payment->balance >= $inv->payment_balance) { //单笔销账多少 $balanceMode->balance = $inv->payment_balance; //缴费额度变化 if(($payment->balance - $inv->payment_balance) == 0){ $payment->status = 4; } else { $payment->status = 4; //缴费部分销账 } $payment->balance = $payment->balance - $inv->payment_balance; //账单额度变化 $inv->payment_balance = 0; //更新账户status 首字母 = 2 $inv->status = setInvoiceStatus($inv->status, 2); } else { //单笔销账多少 $balanceMode->balance = $payment->balance; //账单额度变化 $inv->status = setInvoiceStatus($inv->status, 1); $inv->payment_balance = $inv->payment_balance - $payment->balance; //缴费额度变化 $payment->balance = 0; $payment->status = 4; //缴费已经完全销账 } $model = new EmPaymentInvoice(); if(!$model->where(['payment_id'=>$payment->payment_id,'invoice_id'=>$inv->invoice_id])->find()){ $model->payment_id = $payment->payment_id; $model->invoice_id = $inv->invoice_id; $model->save(); } $result++; //更新账单状态 $inv->save(); //todo::history; 保存历史记录 $invData = $inv->toArray(); $invData['id'] = null; $invData['create_time'] = strtotime($invData['create_time']); $invData['update_time'] = strtotime($invData['update_time']); //EmInvoiceHistory::create($invData); //unset($invs[$index]); //从结果集中去掉无效的数据 //更新状态 $payment->save(); //todo::history;保存历史记录 $payData = $payment->toArray(); $payData['id'] = null; $payData['create_time'] = strtotime($payData['create_time']); $payData['update_time'] = strtotime($payData['update_time']); $payData['pay_date'] = strtotime($payData['pay_date']); //EmPaymentHistory::create($payData); unset($payments[$key]); $balanceMode->isUpdate(false)->save(); } } $msg = $result == 0 ? '已审核,没有可销账的账单.' : '已审核,成功销账 '.$result.' 笔账单.'; return $msg; } public function writeOffFromSettle($account_id,$settle_id){ //获取缴费单对象 $settle = EmSettle::where('settle_id','=',$settle_id)->find(); //获取关联的账单对象 $invs = (new EmInvoice())->alias('ei')->field('ei.invoice_id') ->leftJoin(['em_settle_invoice'=>'esi'],'esi.invoice_id = ei.invoice_id') ->where('esi.settle_id','=',$settle_id) ->where('ei.settle_balance','neq',0) ->order('ei.invoice_id asc') ->select(); $invsArr = []; if(!$invs->isEmpty()) { foreach ($invs as $inv){ $invsArr[] = $inv->invoice_id; } } //查询可消的额度 $settles_balance = (new EmInvoice)->where('invoice_id','in',$invsArr)->sum('settle_balance'); //如果可以完全销账 则继续销账 if($settle->balance > $settles_balance){ $invs = (new EmInvoice())->field('invoice_id') ->where('account_id','=',$account_id) ->where('settle_balance','neq',0) ->order('invoice_id asc') ->select(); if(!$invs->isEmpty()) { foreach ($invs as $inv){ $invsArr[] = $inv->invoice_id; } } } $settleIds[] = $settle->settle_id; //处理账户金额 return $this->writeOffSettle($settleIds,$invsArr); } private function writeOffSettle($settleIds,$invoiceIds,$associate = false){ //获取可销账结算单 $settles = EmSettle::where('settle_id','in',$settleIds)->select(); //获取可销账账单 $invs = EmInvoice::where('invoice_id','in',$invoiceIds)->select(); $result = 0; foreach ($settles as $key => $settle){ if($settle->balance == 0) continue; foreach ($invs as $index => $inv) { $balanceMode = new EmSettleInvoiceBalance(); $balanceMode->settle_id = $settle->settle_id; if ($inv->settle_balance == 0) continue; $balanceMode->invoice_id = $inv->invoice_id; //如果该结算单可以完全消除当前账单额度 if ($settle->balance >= $inv->settle_balance) { //单笔销账多少 $balanceMode->balance = $inv->settle_balance; //结算额度变化 if(($settle->balance - $inv->settle_balance) == 0){ $settle->status = 4; } else { $settle->status = 4; //结算部分销账 } $settle->balance = $settle->balance - $inv->settle_balance; //账单额度变化 $inv->settle_balance = 0; //更新账户status 首字母 = 2 $inv->status = setInvoiceStatus($inv->status, 2,1); } else { //单笔销账多少 $balanceMode->balance = $settle->balance; //账单额度变化 $inv->status = setInvoiceStatus($inv->status, 1,1); $inv->settle_balance = $inv->settle_balance - $settle->balance; //结算额度变化 $settle->balance = 0; $settle->status = 3; //结算已经完全销账 } if($associate == true){ $model = new EmSettleInvoice(); $model->settle_id = $settle->settle_id; $model->invoice_id = $inv->invoice_id; $model->save(); } $result++; //更新账单状态 $inv->save(); //todo::history; 保存历史记录 $invData = $inv->toArray(); $invData['id'] = null; $invData['create_time'] = strtotime($invData['create_time']); $invData['update_time'] = strtotime($invData['update_time']); //EmInvoiceHistory::create($invData); unset($invs[$index]); //从结果集中去掉无效的数据 //更新状态 $settle->save(); //todo::history;保存历史记录 $payData = $settle->toArray(); $payData['id'] = null; $payData['create_time'] = strtotime($payData['create_time']); $payData['update_time'] = strtotime($payData['update_time']); $payData['settle_date'] = strtotime($payData['settle_date']); //EmSettleHistory::create($payData); unset($settles[$key]); $balanceMode->isUpdate(false)->save(); } } $msg = $result == 0 ? '没有结算成功' : '成功结算: '.$result.'笔'; return $msg; } }