qinzexin 3a92a48b3a 抬头管理增删改查 列表
发票申请
订单详情发票信息
可开发票的订单列表
2025-06-19 14:03:29 +08:00

406 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common\model\user\invoice;
use app\common\model\BaseModel;
use app\common\model\school\activity\order\Order;
use app\common\model\school\activity\order\OrderLog;
use think\Model;
class Apply extends BaseModel
{
// 表名
protected $name = 'user_invoice_apply';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = false;
// 追加属性
protected $append = [
'status_text',
'apply_type_text',
'head_type_text',
'invoice_type_text',
'invoicingtime_text'
];
public function getStatusList()
{
return ['1' => __('Status 1'), '2' => __('Status 2'), '-3' => __('Status -3')];
}
public function getApplyTypeList()
{
return ['1' => __('Apply_type 1'), '2' => __('Apply_type 2')];
}
public function getHeadTypeList()
{
return ['personal' => __('Head_type personal'), 'corporate' => __('Head_type corporate')];
}
public function getInvoiceTypeList()
{
return ['ordinary' => __('Invoice_type ordinary'), 'special' => __('Invoice_type special')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getApplyTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['apply_type']) ? $data['apply_type'] : '');
$list = $this->getApplyTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getHeadTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['head_type']) ? $data['head_type'] : '');
$list = $this->getHeadTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getInvoiceTypeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['invoice_type']) ? $data['invoice_type'] : '');
$list = $this->getInvoiceTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getInvoicingtimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['invoicingtime']) ? $data['invoicingtime'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
protected function setInvoicingtimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
public function getImagesAttr($value, $data)
{
$imagesArray = [];
if (!empty($value)) {
$imagesArray = explode(',', $value);
foreach ($imagesArray as &$v) {
$v = cdnurl($v, true);
}
return $imagesArray;
}
return $imagesArray;
}
public function setImagesAttr($value, $data)
{
$imagesArray = $value;
if (!empty($value) && is_array($value)) {
//转成逗号拼接字符串
$imagesArray = implode(',', $value);
}
return $imagesArray;
}
public function user()
{
return $this->belongsTo('app\admin\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function activityorders()
{
return $this->hasMany(Order::class, 'user_invoice_apply_id', 'id');
}
/** 申请发票
* @param $order_no 申请发票的订单号
* @param
* @param $trans
* @throws \Exception
*/
public function add($order_no,$params,$oper_id = 0,$oper_type='user',$check=true,$trans=false){
if (empty($params)) {
throw new \Exception(__('Parameter %s can not be empty', ''));
}
$params['type'] = $params['type'] ?? '1'; //默认新开
$rule = [
// 'user_id'=>'require',
'head_type'=>'require',
'invoice_type'=>'require',
'invoice_header' => 'require',
'invoice_reservation_phone' => 'require',
'invoice_reservation_email' => 'require',
];
$rule_msg = [
// "user_id.require"=>'提交用户必填',
"head_type.require"=>'抬头类型必填',
"invoice_type.require"=>'发票类型必填',
'invoice_header.require' => '发票抬头必填',
'invoice_reservation_phone.require' => '发票预留电话必填',
'invoice_reservation_email.require' => '发票预留邮箱必填',
];
self::check($params,$rule,$rule_msg);
//个人无法开专用发票
if($params['head_type']=='personal' && $params['invoice_type']=='special'){
throw new \Exception('个人用户无法开专用发票');
}
//企业需要填写纳税人识别号等信息
if($params['head_type']=='corporate'){
$rule = [
'tax_id'=>'require',
'type'=>'require',
'bank_deposit'=>'require',
'bank_number'=>'require',
'enterprise_address'=>'require',
'enterprise_phone'=>'require',
];
$rule_msg = [
'tax_id.require' => '纳税人识别号必填',
'type.require' => '开票类型必填',
'bank_deposit.require' => '开户银行必填',
'bank_number.require' => '银行账号必填',
'enterprise_address.require' => '企业地址必填',
'enterprise_phone.require' => '企业电话必填',
];
self::check($params,$rule,$rule_msg);
}
//是否存在逗号隔开
$order_nos = explode(',',$order_no);
$order_ids = [];
$orders = [];
foreach ($order_nos as $orderno){
$order = Order::getHaveInvoiceApplyOrder($orderno);
if($check){
//用户操作权限检测
Order::checkOptionAuth($order['id'],$oper_id ,$oper_type);
}
$order_ids[] = $order->id;
$orders[] = $order;
$params['user_id'] = $order->user_id;
}
if(empty($order_ids)){
throw new \Exception('订单不存在或已开过发票');
}
//是单开还是连开
if(count($order_ids) >1){
$params['apply_type'] = '2';
$typeinfo = "(联合开票)";
}else{
$params['apply_type'] = '1';
$typeinfo = "(单独开票)";
}
//计算合开金额
//用户支付金额
$params['price'] = Order::where( "id","in",$order_ids)->sum("sub_refundprice");
//平台手续费
$params['fee_price'] = Order::where( "id","in",$order_ids)->sum("fee_price");
if(!$params['price']) throw new \Exception('订单金额异常,该订单无可申请发票金额');
//$order_ids 按字典序排序后重新合并成字符串再保存
//int数组字典序排序
sort($order_ids,SORT_NUMERIC);
$order_ids = implode(',',$order_ids);
//如果是换开orderIds不能变
if($params['type']=='2'){
$invoiceaplpy = self::where( "order_ids",$order_ids)->find();
if(!$invoiceaplpy){
throw new \Exception('换开失败,请选择已经开票的记录操作换开');
}
}
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
//是否采用模型验证
// if ($this->modelValidate) {
// $name = str_replace("\\model\\", "\\validate\\", get_class($this));
// $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
// $this->validateFailException()->validate($validate);
// }
$params["order_ids"] = $order_ids;
//添加发票申请
$self = new self;
$result = $self->allowField(true)->save($params);
//更新订单发票申请状态
Order::where( "id","in",$order_ids)->update([
'invoice_status'=>'1',
'user_invoice_apply_id'=> $self->id,
]);
//逐个发订单日志
foreach ($orders as $order){
$invoiceaplpy = $order->invoiceaplpy;
if($invoiceaplpy){
$invoiceaplpy["status"] = '-3';
$invoiceaplpy->save();
//换开
OrderLog::log($order['id'],"活动订单重新发起了发票申请{$typeinfo},等待发票换开",$oper_id ,$oper_type);
}else{
//新开
OrderLog::log($order['id'],"活动订单发起了发票申请{$typeinfo},等待系统开票",$oper_id ,$oper_type);
}
}
//合并调用开发票事件
$data = [
'orders' => Order::where( "id","in",$order_ids)->select(),
'invoice_apply' => $self,
'oper_id' => $oper_id,
'oper_type' => $oper_type,
];
\think\Hook::listen('activity_order_invoice_apply_after', $data);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $self;
}
/** 发票开票(线下)
* @param $id 申请的发票id
* @param $images 发票展示
* @param $desc 开票备注
* @param $trans
* @throws \Exception
*/
public function examine($id,$images,$desc,$oper_id = 0,$oper_type='user',$check=true,$trans=false)
{
$self = self::get($id);
if(!$self) throw new \Exception('发票申请不存在');
//已开票则直接返回
if($self["status"] == '2'){
return $self;
}
if(! $desc) throw new \Exception('请填写开票备注');
if(! $images) throw new \Exception( '请上传发票图片');
//
$params = [
'status' => '2',
'desc' => $desc,
'images' => $images,
'invoicingtime' => time(),
];
if($check){
}
if($trans){
self::beginTrans();
}
$res = true;
try{
//是否采用模型验证
// if ($this->modelValidate) {
// $name = str_replace("\\model\\", "\\validate\\", get_class($this));
// $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
// $this->validateFailException()->validate($validate);
// }
//更新发票状态
$self->allowField(true)->save($params);
$activityorders = $self->activityorders;
foreach ($activityorders as $order){
//更新订单发票申请状态
$order["invoice_status"] = '2';
$order->save();
//发订单日志
OrderLog::log($order['id'],"活动订单已开票",$oper_id ,$oper_type);
}
//调用开发票事件
$data = [
'orders' => $activityorders,
'invoice_apply' => $self,
'oper_id' => $oper_id,
'oper_type' => $oper_type,
];
//开票成功事件
\think\Hook::listen('activity_order_invoice_success_after', $data);
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $self;
}
}