mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-23 02:45:33 +08:00
998 lines
45 KiB
PHP
998 lines
45 KiB
PHP
<?php
|
||
/**
|
||
* Copyright 2012-2026 ShopeX (https://www.shopex.cn)
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
/**
|
||
* 发票处理类
|
||
*/
|
||
class invoice_process
|
||
{
|
||
//当前方法废弃使用新方法
|
||
/**@used-by invoice_process::newCreate **/
|
||
/**
|
||
* 新增发票记录处理函数
|
||
*
|
||
* @param array $params 传入参数
|
||
*/
|
||
public function create($params, $type='order_create')
|
||
{
|
||
//order_id是必须的
|
||
$order_id = $params['order_id'];
|
||
if(!$order_id){
|
||
return false;
|
||
}
|
||
$check_create = kernel::single('invoice_check')->checkCreate($order_id);
|
||
#详情那里的可以点编辑
|
||
if(!$check_create && ($type !=='order_detail_basic')){
|
||
return false;
|
||
}
|
||
//获取order表信息
|
||
$mdlOmeOrders = app::get('ome')->model('orders');
|
||
$rs_orders = $mdlOmeOrders->dump(array("order_id"=>$order_id));
|
||
if (empty($rs_orders)){
|
||
$mdlOmeOrders = app::get('archive')->model('orders');
|
||
$rs_orders = $mdlOmeOrders->dump(array("order_id"=>$order_id));
|
||
if (empty($rs_orders)) {
|
||
return false;
|
||
}
|
||
}
|
||
//获取前端店铺发票配置信息
|
||
$shop_id = $rs_orders["shop_id"];
|
||
$mode = 1;
|
||
|
||
$rs = kernel::single('invoice_func')->get_order_setting($shop_id,$mode);
|
||
$rs_setting = $rs[0];
|
||
#电子发票,没有开票信息设置的,不创建
|
||
if($mode == 1 && empty($rs_setting)){
|
||
return true;
|
||
}
|
||
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
if($type == 'order_create'){
|
||
//前端店铺下单 和 手动新建订单
|
||
if($rs_orders['is_tax'] == 'false' && $params['source_from'] != 'xcxd'){
|
||
//手动新建订单 不选择开票
|
||
return false;
|
||
}
|
||
$invoice_mode = intval($params['invoice_kind']); //默认0纸质发票 电子发票为1
|
||
$order_bn = $params['order_bn'];
|
||
$tax_rate = $rs_setting["tax_rate"] ? $rs_setting["tax_rate"] : 0;//税率
|
||
$tax_title = strip_tags(trim($params['tax_title'])); //发票抬头
|
||
$content = '商品明细'; //发票内容 默认为 商品明细
|
||
$consignee_name = $params['consignee']['name']; //收货人名
|
||
$consignee_area = $params['consignee']['area']; //收货人地区
|
||
$consignee_addr = $params['consignee']['addr']; //收货人地址
|
||
|
||
$telphone = $params['consignee']['mobile'];
|
||
$register_no = $params['register_no'];
|
||
|
||
// 获取编辑表单其他的填写数据
|
||
$other_insert = array(
|
||
"ship_bank" => $params["invoice_bank_name"],
|
||
"ship_bank_no" => $params["invoice_bank_account"],
|
||
"ship_company_addr" => $params["invoice_address"], // 注册地址
|
||
"ship_company_tel" => $params['invoice_phone'], // 注册电话
|
||
"ship_name" => $params['invoice_receiver_name'],
|
||
"tax_company" => $params['invoice_receiver_name'],
|
||
);
|
||
|
||
if ($params['value_added_tax_invoice']) {
|
||
$other_insert['type_id'] = '1';
|
||
}else{
|
||
$invoice_mode = '1';
|
||
}
|
||
|
||
$msg_part = '新订单自动插入发票信息';
|
||
}else if($type == 'order_detail_basic'){
|
||
$tax_title = $params['tax_title']; //发票抬头
|
||
|
||
//订单明细里“开票”按钮 手动生成 没有发票的订单发票信息
|
||
if($rs_orders["is_tax"] == 'false'){
|
||
$invoice_mode = intval($params['invoice_mode']); //默认0纸质发票 电子发票为1
|
||
$order_bn = $rs_orders['order_bn']; //订单号
|
||
$tax_rate = $rs_setting["tax_rate"] ? $rs_setting["tax_rate"] : 0;//税率
|
||
|
||
$content = '商品明细'; //发票内容 默认为 商品明细
|
||
$consignee_name = $rs_orders['consignee']['name']; //收货人名
|
||
$consignee_area = $rs_orders['consignee']['area']; //收货人地区
|
||
$consignee_addr = $rs_orders['consignee']['addr']; //收货人地址
|
||
$telphone = $rs_orders['consignee']['mobile']; //用来发短信
|
||
$msg_part = '手动插入发票信息';
|
||
if ($invoice_mode == '0') {
|
||
$other_insert['type_id'] = '1';
|
||
}
|
||
if ($params['is_make_invoice']) {
|
||
$other_insert["is_make_invoice"] = $params['is_make_invoice'];
|
||
}
|
||
}else{
|
||
#获取没有作废的那条开票记录,更新发票抬头
|
||
$InOrder_info = $mdlInOrder->getList('id,is_status',array('order_id'=>$order_id,'is_status'=>'0'));
|
||
if(empty($InOrder_info)){
|
||
return true;
|
||
}
|
||
$_data['title'] = $tax_title;
|
||
$_data['id'] = $InOrder_info[0]['id'];
|
||
$result = $mdlInOrder->save($_data);
|
||
return true;
|
||
}
|
||
}elseif($type == 'batch_invoice_order'){
|
||
if($rs_orders['is_tax'] == 'false'){
|
||
//手动新建订单 不选择开票
|
||
return false;
|
||
}
|
||
$invoice_mode = $params['invoice_kind']?intval($params['invoice_kind']):0; //默认0纸质发票 电子发票为1
|
||
$order_bn = $rs_orders['order_bn']; //订单号
|
||
$tax_rate = $rs_setting["tax_rate"] ? $rs_setting["tax_rate"] : 0;//税率
|
||
$tax_title = $rs_orders['tax_title']; //发票抬头
|
||
$content = '商品明细'; //发票内容 默认为 商品明细
|
||
$consignee_name = $rs_orders['consignee']['name']; //收货人名
|
||
$consignee_area = $rs_orders['consignee']['area']; //收货人地区
|
||
$consignee_addr = $rs_orders['consignee']['addr']; //收货人地址
|
||
$telphone = $rs_orders['consignee']['mobile']; //用来发短信
|
||
$msg_part = '批量创建订单自动插入发票信息';
|
||
}else if($type == 'invoice_list_add_same'){
|
||
//获取编辑表单其他的填写数据
|
||
$other_insert = array(
|
||
"remarks" => $params["remarks"],
|
||
"ship_bank" => $params["ship_bank"],
|
||
"ship_bank_no" => $params["ship_bank_no"],
|
||
"ship_tax" => $params["ship_tax"],
|
||
"ship_company_addr" => $params["ship_company_addr"],
|
||
"ship_company_tel" => $params["ship_company_tel"],
|
||
);
|
||
//发票列表 新建发票信息
|
||
$invoice_mode = intval($params['mode']); //默认0纸质发票 电子发票为1
|
||
//获取原发票记录
|
||
$old_invoice_order = $mdlInOrder->dump(array("id"=>$params["id"]));
|
||
$order_bn = $old_invoice_order["order_bn"]; //订单号
|
||
$memoList = array();
|
||
$oldmemo = @unserialize($old_invoice_order['memo']);
|
||
if (end($oldmemo)['op_content'] != $params['memo']) {
|
||
$op_name = kernel::single('desktop_user')->get_name();
|
||
if ($oldmemo) {
|
||
foreach ($oldmemo as $k => $v) {
|
||
$memoList[] = $v;
|
||
}
|
||
}
|
||
$newmemo = htmlspecialchars($params['memo']);
|
||
$newmemo = array('op_name' => $op_name, 'op_time' => date('Y-m-d H:i:s', time()), 'op_content' => $newmemo);
|
||
$memoList[] = $newmemo;
|
||
|
||
}
|
||
$params['memo'] = @serialize($memoList);
|
||
//发票金额
|
||
$params['invoice_amount'] = number_format($params["amount"],2,".",""); //纸质发票直接取填的开票金额为开票金额
|
||
$other_insert["type_id"] = $params["type_id"]?:1;
|
||
|
||
$tax_rate = 0;
|
||
if(is_numeric($params["tax_rate"]) && intval($params["tax_rate"]) > 0 ){
|
||
$tax_rate = $params["tax_rate"];
|
||
}
|
||
$tax_title = $params["title"];
|
||
$content = $old_invoice_order['content'];
|
||
$params['invoice_receiver_name'] = $params["tax_company"];
|
||
$consignee_area = $params["ship_area"];
|
||
$consignee_addr = $params["ship_addr"];
|
||
$telphone = $params['ship_tel'];
|
||
|
||
//开票方信息取表单填写 重写rs_setting数组拿input框中的值
|
||
$rs_setting = array(
|
||
"payee_name" => $params['payee_name'],
|
||
"tax_no" => $params['tax_no'],#开票方税号
|
||
"address" => $params['address'],
|
||
"telphone" => $params['telephone'],
|
||
"payee_operator" => $params['payee_operator'],
|
||
"bank" => $params['bank'],
|
||
"bank_no" => $params['bank_no'],
|
||
'payee_receiver' => $params['payee_receiver'],
|
||
'payee_checker' => $params['payee_checker']
|
||
);
|
||
//新建相似是否可以开票根据原票状态
|
||
if ($old_invoice_order['is_make_invoice'] == '1') {
|
||
$other_insert["is_make_invoice"] = '1';
|
||
}
|
||
$msg_part = "新建类似发票信息";
|
||
if ($params['action_type'] && $params['action_type'] == 'doCheckChangeTicket') {
|
||
$msg_part = "使用改票信息新建发票";
|
||
//更新改票状态
|
||
$mdlInOrder->update(['change_status'=>'2'],array("id"=>$params["id"]));
|
||
//新发票设置为可操作状态
|
||
$other_insert["is_make_invoice"] = '1';
|
||
$rs = kernel::single('invoice_func')->get_order_setting($shop_id,$invoice_mode);
|
||
$rs_setting = $rs[0];
|
||
}
|
||
}
|
||
if ($params['source_status']) {
|
||
$other_insert['source_status'] = $params['source_status'];
|
||
}
|
||
$total_amount = number_format($rs_orders['total_amount'],2,".",""); //(含税)订单总金额
|
||
#京东的订单,优惠方案,是当支付金额来使用,相当于少付钱,因此开票金额需要从总额中减去优惠
|
||
// if(!empty($params['invoice_pmt_amount']) && in_array($params['shop_type'] ,array('360buy'))){
|
||
// $total_amount = $total_amount - $params['invoice_pmt_amount'];
|
||
// }
|
||
|
||
// 平台同步过来的开票金额
|
||
if ($params['invoice_amount']) $total_amount = $params['invoice_amount'];
|
||
|
||
|
||
#到达ERP的订单金额,实际都是已经含税了的,所以这里的税金,需要自行推算出来
|
||
$cost_tax = kernel::single('invoice_func')->get_invoice_cost_tax($total_amount,$tax_rate);
|
||
$tax_title = $tax_title ? $tax_title : '个人';//如抬头为空则用收货人名
|
||
$operator = kernel::single('desktop_user')->get_id();//操作人ID
|
||
$insert_arr = array(
|
||
'is_print' => '1',# 这个值对于openapi的用户有用
|
||
'order_id' => $order_id,
|
||
'order_bn' => $order_bn,
|
||
'mode' => 1,//这个key不存在就是0,1为电子发票
|
||
'amount' => $total_amount,#(含税)开票金额(在显示和调用的地方,允许客户按和甲方约定的开票金额,进行修改)
|
||
'cost_tax' => $cost_tax,
|
||
'tax_rate' => $tax_rate,
|
||
'title' => $tax_title,
|
||
'content' => $content,#新建发票时,发票内容默认是商品明细
|
||
'operator' => $operator,
|
||
'create_time' => time(),
|
||
'tax_company' => $params['invoice_receiver_name'],
|
||
'ship_name' => $params['invoice_receiver_name'],
|
||
'ship_area' => $consignee_area,
|
||
'ship_addr' => $consignee_addr,
|
||
'ship_tel' => $telphone,
|
||
'shop_id' => $shop_id,
|
||
'shop_type' => $rs_orders["shop_type"],
|
||
'payee_name' => $rs_setting["payee_name"] ? $rs_setting["payee_name"] : "",
|
||
'tax_no' => $rs_setting["tax_no"] ? $rs_setting["tax_no"] : "",
|
||
'address' => $rs_setting["address"] ? $rs_setting["address"] : "",
|
||
'telephone' => $rs_setting["telphone"] ? $rs_setting["telphone"] : "",
|
||
'payee_operator' => $rs_setting["payee_operator"] ? $rs_setting["payee_operator"] : "",
|
||
'bank' => $rs_setting["bank"] ? $rs_setting["bank"] : "",
|
||
'bank_no' => $rs_setting["bank_no"] ? $rs_setting["bank_no"] : "",
|
||
'payee_checker' => $rs_setting['payee_checker'] ? $rs_setting['payee_checker'] : '',
|
||
'payee_receiver' => $rs_setting['payee_receiver'] ? $rs_setting['payee_receiver'] : '',
|
||
'ship_email' => $params['receiver_email'] ? $params['receiver_email'] : '',
|
||
'invoice_apply_bn' => $this->getInvoiceApplyBn(),
|
||
);
|
||
//对pos判断btq trade 不在列表里显示
|
||
if($insert_arr['shop_type'] == 'pekon'){
|
||
$stores = app::get('o2o')->model('store')->db_dump(array('shop_id'=>$shop_id),'store_sort');
|
||
if(in_array($stores['store_sort'],array('BTQ','Trade'))){
|
||
$insert_arr['disabled'] = 'true';
|
||
}
|
||
if($params['is_status']){
|
||
$insert_arr['is_status'] = $params['is_status'];
|
||
}
|
||
}
|
||
|
||
|
||
if($other_insert){
|
||
$insert_arr = array_merge($insert_arr,$other_insert);
|
||
}
|
||
if($register_no) {
|
||
$insert_arr['ship_tax'] = $register_no;
|
||
}
|
||
|
||
//发票备注
|
||
if($params['memo']){
|
||
$insert_arr['memo'] = $params['memo'];
|
||
}
|
||
//新增发票
|
||
$result = $mdlInOrder->insert($insert_arr);
|
||
|
||
//新增发票日志
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
if($result){
|
||
$msg = $msg_part."成功。";
|
||
$opObj->write_log('invoice_create@invoice', $result, $msg);
|
||
//专票新建类似发票成功更新明细
|
||
if($type == 'invoice_list_add_same') {
|
||
if ($insert_arr['mode'] == '0' && $insert_arr['type_id'] == '1') {
|
||
$insert_arr['id'] = $result;
|
||
kernel::single('invoice_sales_data')->generate($insert_arr);
|
||
}
|
||
}
|
||
//生成的发票直接请求开票接口
|
||
$autoinvoice = app::get('ome')->getConf('ome.order.autoinvoice');
|
||
if ($params['action_type'] && in_array($params['action_type'],['doCheckChangeTicket','order_aftersale']) && $insert_arr['mode'] == '1' && $autoinvoice == 'on') {
|
||
$this->billing(['id'=>$result,'order_id'=>$order_id]);
|
||
}
|
||
return true;
|
||
}else{
|
||
$msg = $msg_part."失败。";
|
||
$opObj->write_log('invoice_create@invoice', $result, $msg);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建开票数据
|
||
* @Author: xueding
|
||
* @Vsersion: 2023/5/30 下午4:59
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function newCreate($params,$type = '')
|
||
{
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
$invoiceOrderItemMdl = app::get('invoice')->model('order_items');
|
||
$invoiceOrderLib = kernel::single('invoice_order');
|
||
if (!isset($params['items']) || empty($params['items'])) {
|
||
return [false, '缺少开票明细'];
|
||
}
|
||
|
||
list($check_create,$msg) = kernel::single('invoice_check')->checkInvoiceCreate(array_column($params['items'],'of_id'),$type);
|
||
//创建发票校验
|
||
if(!$check_create){
|
||
return [false, $msg];
|
||
}
|
||
|
||
$type_id = 0;
|
||
if (intval($params['mode']) != '1') {
|
||
$type_id = '1';
|
||
}
|
||
|
||
$shop_id = $params["shop_id"];
|
||
$shopInfo = app::get('ome')->model('shop')->getRow(['shop_id'=>$shop_id],'org_id');
|
||
$org_id = $shopInfo['org_id'];
|
||
//发票金额
|
||
$total_amount = number_format($params["amount"], 2, ".", ""); //纸质发票直接取填的开票金额为开票金额
|
||
$tax_rate = 0;//税率
|
||
|
||
#到达ERP的订单金额,实际都是已经含税了的,所以这里的税金,需要自行推算出来
|
||
$cost_tax = 0;
|
||
$tax_title = '个人';
|
||
if ($params['title']) {
|
||
$tax_title = strip_tags(trim($params['title']));
|
||
}
|
||
if ($params['tax_title']) {
|
||
$tax_title = strip_tags(trim($params['tax_title']));//如抬头为空则用收货人名
|
||
}
|
||
|
||
$operator = kernel::single('desktop_user')->get_id();//操作人ID
|
||
$orderBn = $params['order_bn'];
|
||
if ($params['source_bn']) {
|
||
$orderBn = $params['source_bn'];
|
||
}
|
||
if (is_array($orderBn)) {
|
||
$orderBn = implode(',',$orderBn);
|
||
}
|
||
$insert_arr = array(
|
||
'is_print' => '1',# 这个值对于openapi的用户有用
|
||
'order_id' => '',
|
||
'order_bn' => $orderBn,
|
||
'mode' => 1,//这个key不存在就是0,1为电子发票
|
||
'type_id' => $type_id,//0普通发票,1专用发票
|
||
'amount' => $total_amount,#(含税)开票金额(在显示和调用的地方,允许客户按和甲方约定的开票金额,进行修改)
|
||
'cost_tax' => $cost_tax,
|
||
'tax_rate' => $tax_rate,
|
||
'title' => $tax_title,
|
||
'content' => $params['content'] ? $params['content'] : '商品明细', //发票内容默认是商品明细
|
||
'operator' => $operator,
|
||
'create_time' => time(),
|
||
'tax_company' => $params['invoice_receiver_name'] ?: $params['ship_name'],
|
||
'ship_name' => $params['invoice_receiver_name'] ?: $params['ship_name'],
|
||
'ship_area' => $params["ship_area"],
|
||
'ship_addr' => $params["ship_addr"],
|
||
'ship_tel' => $params['ship_tel'],
|
||
'shop_id' => $shop_id,
|
||
'shop_type' => $params["shop_type"],
|
||
'ship_email' => $params['receiver_email'] ? $params['receiver_email'] : $params['ship_email'],
|
||
'ship_tax' => $params['ship_tax'] ? $params['ship_tax'] : '',
|
||
'cost_freight' => $params['cost_freight'] ? $params['cost_freight'] : '0',
|
||
'invoice_type' => $params['invoice_type'] ? $params['invoice_type'] : 'normal',
|
||
"remarks" => $params["remarks"],
|
||
"ship_bank" => $params["ship_bank"],
|
||
"ship_bank_no" => $params["ship_bank_no"],
|
||
"ship_company_addr" => $params["ship_company_addr"],
|
||
"ship_company_tel" => $params["ship_company_tel"],
|
||
"org_id" => $org_id,
|
||
'invoice_apply_bn' => $this->getInvoiceApplyBn(),
|
||
);
|
||
//对pos判断btq trade 不在列表里显示
|
||
if ($insert_arr['shop_type'] == 'pekon') {
|
||
$stores = app::get('o2o')->model('store')->db_dump(array('shop_id' => $shop_id), 'store_sort');
|
||
if (in_array($stores['store_sort'], array('BTQ', 'Trade'))) {
|
||
$insert_arr['disabled'] = 'true';
|
||
}
|
||
}
|
||
if ($params['is_status']) {
|
||
$insert_arr['is_status'] = $params['is_status'];
|
||
}
|
||
if ($params['source_status']) {
|
||
$insert_arr['source_status'] = $params['source_status'];
|
||
}
|
||
//发票备注
|
||
if ($params['memo']) {
|
||
$insert_arr['memo'] = $params['memo'];
|
||
}
|
||
|
||
if (strpos($orderBn,',')) {
|
||
$insert_arr['invoice_type'] = 'merge';
|
||
}
|
||
|
||
if (isset($params['is_make_invoice']) && in_array($params['is_make_invoice'],['0','1','2'])) {
|
||
//新发票设置为可操作状态
|
||
$insert_arr['is_make_invoice'] = $params['is_make_invoice'];
|
||
}
|
||
|
||
//改票创建的发票直接可以进行开票
|
||
if ($type == 'change_ticket') {
|
||
$insert_arr['is_make_invoice'] = '1';//改票新建发票直接设置为可开票
|
||
//更新老发票改票状态
|
||
$mdlInOrder->update(['change_status'=>'2'],array("id"=>$params["id"]));
|
||
}
|
||
|
||
kernel::database()->beginTransaction();
|
||
//新增发票
|
||
$result = $mdlInOrder->insert($insert_arr);
|
||
|
||
switch ($type){
|
||
case "add_new_same":
|
||
$msg_part = "新建类似发票信息";
|
||
break;
|
||
case "change_ticket":
|
||
$msg_part = "使用改票信息新建发票";
|
||
break;
|
||
case "add_merge_invoice":
|
||
$msg_part = "使用合并发票新建发票";
|
||
break;
|
||
default:
|
||
$msg_part = '创建';
|
||
}
|
||
//新增发票日志
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
if ($result) {
|
||
//组织明细数据
|
||
$items = $invoiceOrderLib->getAddItemsData($params,$result,$type);
|
||
$sql = ome_func::get_insert_sql($invoiceOrderItemMdl, $items);
|
||
$insertItemsRs = $invoiceOrderItemMdl->db->exec($sql);
|
||
if (!empty($type)) {
|
||
$invoiceOrderLib->updateInvoiceItems(['id'=>$result,'amount'=>$total_amount]);
|
||
}
|
||
if (!$insertItemsRs['rs']) {
|
||
kernel::database()->rollBack();
|
||
$msg = $msg_part . "明细失败。";
|
||
return [false, $msg];
|
||
}
|
||
//创建如果是完成订单设置为完成
|
||
kernel::database()->commit();
|
||
$msg = $msg_part . "成功。";
|
||
$opObj->write_log('invoice_create@invoice', $result, $msg);
|
||
//查询是否发票是否可以直接操作
|
||
kernel::single('invoice_func')->getInvoiceMakeStatus($result);
|
||
|
||
//更新税金
|
||
$invoiceOrderLib->updateInvoice($result,['invoice_amount'=>$total_amount,'is_status'=>$params['is_status']]);
|
||
//生成的发票直接请求开票接口
|
||
// $autoinvoice = app::get('ome')->getConf('ome.order.autoinvoice');
|
||
// if ($params['action_type'] && in_array($params['action_type'],['doCheckChangeTicket','order_aftersale']) && $insert_arr['mode'] == '1' && $autoinvoice == 'on') {
|
||
// $this->billing(['id'=>$result,'order_id'=>$order_id]);
|
||
// }
|
||
return [true, $msg];
|
||
} else {
|
||
kernel::database()->rollBack();
|
||
$msg = $msg_part . "失败。";
|
||
return [false, $msg];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 作废处理函数
|
||
* @param array $params 传入参数
|
||
*/
|
||
public function cancel($params,$type='order_cancel')
|
||
{
|
||
$rs_invoice = kernel::single('invoice_check')->checkInvoiceCancel($params['id']);
|
||
if(!$rs_invoice){
|
||
return false;
|
||
}
|
||
//电子发票列表 操作项里的 作废link 必须是同一个id记录 否则返回false
|
||
if($type == 'invoice_list' && intval($rs_invoice["id"]) != intval($params["id"])){
|
||
return false;
|
||
}
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
|
||
$operator = kernel::single('ome_func')->getDesktopUser();
|
||
$update_arr = array("is_status"=>2,"update_time"=>time(),"operator"=>$operator['op_id']);
|
||
$filter_arr = array("id"=>$rs_invoice["id"]);
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
|
||
|
||
if(intval($rs_invoice['mode']) == 1){
|
||
//未开票 并且同步状态是 0(未同步) 和 2(开蓝失败)
|
||
if(intval($rs_invoice['is_status']) == 0 && in_array(intval($rs_invoice['sync']), array(0,2))){
|
||
//直接更新开票金额
|
||
if ($type == 'order_aftersale') {
|
||
$orderInfo = app::get('ome')->model('orders')->db_dump(['order_id' => $params['order_id']], 'payed');
|
||
$amount = $orderInfo['payed'];
|
||
list($rs, $rsData) = kernel::single('invoice_order')->getInvoiceMoney($rs_invoice);
|
||
if ($rs) {
|
||
$amount = $rsData['amount'];
|
||
}
|
||
$cost_tax = kernel::single('invoice_func')->get_invoice_cost_tax($amount, $rs_invoice["tax_rate"]);
|
||
if ($rs_invoice['amount'] != $amount && $amount > 0) {
|
||
$update_arr = array ("amount" => $amount, "update_time" => time(), "cost_tax" => $cost_tax);
|
||
$result = $mdlInOrder->update($update_arr, $filter_arr);
|
||
$msg_part = '部分退款更新发票金额,原发票金额:' . $rs_invoice['amount'] . ',修改后金额:' . $amount;
|
||
}
|
||
}else{
|
||
$result = $mdlInOrder->update($update_arr,$filter_arr);
|
||
$msg_part = "作废未开票电子发票成功。";
|
||
|
||
// 作废ITEM数据
|
||
$eInvoidItemMdl = app::get('invoice')->model('order_electronic_items');
|
||
$eInvoidItemMdl->update(['invoice_status' => '2'],[
|
||
'id' => $rs_invoice["id"],
|
||
'invoice_status' => ['99','10']
|
||
]);
|
||
}
|
||
}
|
||
//已开票 并且同步状态是 3(开蓝成功) 4(开红票中) 和 5(冲红失败)
|
||
if(intval($rs_invoice['is_status']) == 1 && in_array(intval($rs_invoice['sync']), array(3,4,5,8,9))){
|
||
//电子发票冲红
|
||
$checkEinvoiceCreate = kernel::single('invoice_check')->checkEinvoiceCreate($rs_invoice,"2");
|
||
if(!$checkEinvoiceCreate){
|
||
return false;
|
||
}
|
||
|
||
$rs_invoice['invoice_action_type'] = $params['invoice_action_type'];
|
||
$rs_invoice = kernel::single('invoice_electronic')->getEinvoiceSerialNo($rs_invoice,"2");
|
||
if(!$rs_invoice){
|
||
return false;
|
||
}
|
||
//检查必要条件
|
||
$check_do_einvoice = kernel::single('invoice_check')->checkDoEinvoice($rs_invoice);
|
||
if(!empty($check_do_einvoice["arr_hint"])){
|
||
$opObj->write_log('invoice_cancel@invoice', $rs_invoice['id'], '冲红失败:'.(implode(',', $check_do_einvoice['arr_hint'])));
|
||
return false;
|
||
}
|
||
|
||
kernel::single('invoice_electronic')->do_einvoice_create_limit($rs_invoice["id"],"red"); //做冲红点击动作缓存 防止连续点击
|
||
$rs = kernel::single('invoice_event_trigger_einvoice')->cancel($rs_invoice['shop_id'],$rs_invoice);
|
||
if ($type == 'merge_order') {
|
||
$opObj->write_log('invoice_cancel@invoice', $rs_invoice['id'], '合并开票冲红原票');
|
||
}
|
||
$opObj->write_log('invoice_cancel@invoice', $rs_invoice['id'], $rs['msg']);
|
||
return $rs_invoice;
|
||
}
|
||
}else if(intval($rs_invoice['mode']) == 0){
|
||
// 纸质售后不自动作废,需要发票追回的
|
||
if ($type == 'order_aftersale') {
|
||
return false;
|
||
}
|
||
|
||
if ($rs_invoice['is_status'] == '1') {
|
||
$update_arr['is_make_invoice'] = '2';
|
||
unset($update_arr['is_status']);
|
||
}
|
||
|
||
//纸质发票 直接标记作废
|
||
$result = $mdlInOrder->update($update_arr,$filter_arr);
|
||
$msg_part = "作废纸质发票成功。";
|
||
}
|
||
|
||
switch ($type){
|
||
case "order_cancel":
|
||
$msg = "订单取消处,".$msg_part;
|
||
break;
|
||
case "order_detail_basic":
|
||
$msg = "订单详情处取消处,".$msg_part;
|
||
break;
|
||
case "invoice_list":
|
||
$msg = "发票列表处,".$msg_part;
|
||
break;
|
||
case "order_detail":
|
||
$msg = "发票详细处是否开票选择否,".$msg_part;
|
||
break;
|
||
case "batch_invoice_order":
|
||
$msg = "批量设置不开票,".$msg_part;
|
||
break;
|
||
case "order_aftersale":
|
||
$msg = "订单售后完成," . $msg_part;
|
||
break;
|
||
case "merge_order":
|
||
$msg = "合并开票," . $msg_part;
|
||
break;
|
||
case "content_update":
|
||
$msg = "开票内容更新," . $msg_part;
|
||
break;
|
||
}
|
||
|
||
//记录日志
|
||
if($result){
|
||
$opObj->write_log('invoice_cancel@invoice', $rs_invoice['id'], $msg);
|
||
return $rs_invoice;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 开票处理
|
||
*
|
||
* @param array $params 传入参数
|
||
* @param string $event 事件触发,['man'=>'手动','consign' => '发货']
|
||
* @param string $error_msg
|
||
* @return array
|
||
*/
|
||
function billing($params, $event='man', &$error_msg=null)
|
||
{
|
||
try {
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
$invOrderMdl = app::get('invoice')->model('order');
|
||
if ($oldInvoice = $invOrderMdl->db_dump(['id'=>$params['id']])) {
|
||
if ($oldInvoice['sync'] == '0') {
|
||
$invOrderMdl->update(['sync'=>'1'],['id'=>$params['id']]);
|
||
}
|
||
}
|
||
|
||
$checkLib = kernel::single('invoice_check');
|
||
$electLib = kernel::single('invoice_electronic');
|
||
|
||
//开票触发点 在发票列表操作区域
|
||
$rs_invoice = $checkLib->checkMakeInvoice($params, $error_msg);
|
||
if(!$rs_invoice){
|
||
throw new Exception($error_msg);
|
||
}
|
||
|
||
$rs_invoice['mode'] = intval($rs_invoice['mode']);
|
||
|
||
$result = array('rsp'=>'fail', 'error_msg'=>'', 'mode'=>$rs_invoice['mode']);
|
||
|
||
if($rs_invoice['mode'] == 1){
|
||
|
||
if ($event != 'man') {
|
||
if ($rs_invoice['einvoice_operating_conditions'] == '3' && $event != 'sign') {
|
||
$error_msg = '只允许签收触发开票';
|
||
throw new Exception($error_msg);
|
||
}
|
||
}
|
||
|
||
//电子发票开蓝
|
||
$checkEinvoiceCreate = $checkLib->checkEinvoiceCreate($rs_invoice, $error_msg);
|
||
if(!$checkEinvoiceCreate){
|
||
throw new Exception($error_msg);
|
||
}
|
||
|
||
$isCheck = $electLib->getEinvoiceSerialNo($rs_invoice);
|
||
if(!$isCheck || !$rs_invoice['serial_no']){
|
||
$error_msg = '没有开票流水号';
|
||
throw new Exception($error_msg);
|
||
}
|
||
|
||
//操作日志
|
||
$msg = !isset($params['msg']) ? '点击开票' : $params['msg'];
|
||
$opObj->write_log('invoice_billing@invoice', $rs_invoice['id'], $msg);
|
||
|
||
//开票点击动作缓存,防止连续点击
|
||
$electLib->do_einvoice_create_limit($rs_invoice["id"]);
|
||
|
||
//request
|
||
$rs = kernel::single('invoice_event_trigger_einvoice')->create($rs_invoice['shop_id'], $rs_invoice, $error_msg);
|
||
if($rs['rsp'] == 'fail' || !$rs){
|
||
$error_msg = '开蓝失败:'. $rs['msg'] .'('.$rs['msg_id'].')';
|
||
throw new Exception($error_msg);
|
||
}
|
||
|
||
//log
|
||
$log_msg = '开蓝中('.$rs['msg_id'].')';
|
||
$opObj->write_log('invoice_billing@invoice', $rs_invoice['id'], $log_msg);
|
||
|
||
//返回成功
|
||
$result['rsp'] = 'succ';
|
||
|
||
return $result;
|
||
} elseif ($event == 'man') {
|
||
//纸质发票开票
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
|
||
$cur_time = time();
|
||
$operator = kernel::single('desktop_user')->get_id();
|
||
|
||
$update_arr = array("is_status"=>1,"update_time"=>$cur_time,"dateline"=>$cur_time,"operator"=>$operator);
|
||
$filter_arr = array("id"=>$rs_invoice["id"]);
|
||
$rs = $mdlInOrder->update($update_arr, $filter_arr);
|
||
|
||
//log
|
||
$log_msg = '纸质发票开票成功。';
|
||
$opObj->write_log('invoice_billing@invoice', $rs_invoice['id'], $log_msg);
|
||
|
||
$result['rsp'] = 'succ';
|
||
return $result;
|
||
}
|
||
} catch (Exception $e){
|
||
$msg = $e->getMessage();
|
||
if ($oldInvoice = $invOrderMdl->db_dump(['id'=>$params['id']])) {
|
||
if ($oldInvoice['sync'] == '1') {
|
||
$updateData['sync'] = '2';
|
||
if ($msg == '请求开票失败:没有发票明细') {
|
||
$updateData['is_status'] = '2';
|
||
}
|
||
$invOrderMdl->update($updateData,['id'=>$params['id']]);
|
||
}
|
||
}
|
||
$opObj->write_log('invoice_billing@invoice', $params['id'], $msg);
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 编辑处理函数
|
||
* @param array $params 传入参数
|
||
*/
|
||
public function edit($params){
|
||
|
||
if(!$params["id"]){
|
||
return [false,'缺少必要参数'];
|
||
}
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
$invoiceItemMdl = app::get('invoice')->model('order_items');
|
||
$invoiceOrderLib = kernel::single('invoice_order');
|
||
|
||
//条件
|
||
$filter_arr = array("id"=>$params["id"],"is_status"=>"0");
|
||
$rs_invoice_order = $mdlInOrder->dump($filter_arr,"*");
|
||
$invoice_order_items = $invoiceItemMdl->getList('*',array('id'=>$params["id"],'is_delete'=>'false'));
|
||
//编辑合并发票明细处理
|
||
if ($rs_invoice_order['invoice_type'] == 'merge') {
|
||
$invoiceOrderLib->updateMergeInvoiceItems($params,$invoice_order_items);
|
||
}
|
||
//更新内容
|
||
$operator = kernel::single('desktop_user')->get_id();
|
||
$cur_time = time();
|
||
$update_arr = array (
|
||
"mode" => 1,
|
||
"title" => $params["title"],
|
||
"content" => $params["content"],
|
||
"remarks" => $params["remarks"],
|
||
"operator" => $operator,
|
||
"update_time" => $cur_time,
|
||
"bank" => $params["bank"],
|
||
"bank_no" => $params["bank_no"],
|
||
"tax_company" => $params["tax_company"],
|
||
"ship_name" => $params["tax_company"],
|
||
"ship_tel" => $params["ship_tel"],
|
||
"ship_tax" => $params["ship_tax"],
|
||
"ship_area" => $params["ship_area"],
|
||
"ship_addr" => $params["ship_addr"],
|
||
'ship_company_addr' => $params['ship_company_addr'],
|
||
'hsbz' => $params['hsbz'],#含税标志
|
||
'lslbs' => $params['lslbs'],#零税率标示
|
||
'yhzcbs' => $params['yhzcbs'],#是有优惠
|
||
'zzstsgl' => $params['zzstsgl'],#增值税特殊管理
|
||
'payee_receiver' => $params['payee_receiver'],
|
||
'payee_checker' => $params['payee_checker'],
|
||
'ship_company_tel' => $params['ship_company_tel'],
|
||
'is_edit' => 'true',
|
||
"ship_email" => $params["ship_email"],
|
||
"amount" => $params["amount"],
|
||
"ship_bank" =>$params["ship_bank"],
|
||
"ship_bank_no" =>$params["ship_bank_no"],
|
||
);
|
||
|
||
$mode = intval($params["mode"]);
|
||
//纸质发票
|
||
if ($mode == 0) {
|
||
$update_arr["type_id"] = '1';
|
||
} else {
|
||
$update_arr['type_id'] = '0';
|
||
}
|
||
|
||
//备注
|
||
$oldmemo = @unserialize($rs_invoice_order['memo']);
|
||
if ($oldmemo) {
|
||
if ($oldmemo && end($oldmemo)['op_content'] != $params['memo']) {
|
||
$op_name = kernel::single('desktop_user')->get_name();
|
||
if ($oldmemo) {
|
||
foreach ($oldmemo as $k => $v) {
|
||
$memoList[] = $v;
|
||
}
|
||
}
|
||
$newmemo = htmlspecialchars($params['memo']);
|
||
$newmemo = array('op_name' => $op_name, 'op_time' => date('Y-m-d H:i:s', time()), 'op_content' => $newmemo);
|
||
$memoList[] = $newmemo;
|
||
$update_arr['memo'] = @serialize($memoList);
|
||
}
|
||
}
|
||
|
||
kernel::database()->beginTransaction();
|
||
|
||
$result = $mdlInOrder->update($update_arr,$filter_arr);
|
||
|
||
$msg_part = "编辑发票";
|
||
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
if($result){
|
||
if ($params['item_id']) {
|
||
//更新发票明细
|
||
list($updateItemRes,$msg_part) = $invoiceOrderLib->updateInvoiceItems($params,$invoice_order_items);
|
||
if (!$updateItemRes) {
|
||
kernel::database()->rollBack();
|
||
$msg = $msg_part;
|
||
$opObj->write_log('invoice_edit@invoice', $params["id"], $msg);
|
||
return [false,$msg];
|
||
}
|
||
$invoiceOrderLib->updateInvoice($params["id"],['invoice_amount'=>$params["amount"]]);
|
||
}
|
||
kernel::database()->commit();
|
||
//编辑快照
|
||
$log_memo = serialize(['invoice'=>$rs_invoice_order,'invoice_order_items'=>$invoice_order_items]);
|
||
$opObj->write_log('invoice_edit@invoice', $params["id"], $log_memo);
|
||
return [true];
|
||
}else{
|
||
kernel::database()->rollBack();
|
||
$msg = $msg_part.'失败。';
|
||
$opObj->write_log('invoice_edit@invoice', $params["id"], $msg);
|
||
return [false,$msg];
|
||
}
|
||
|
||
}
|
||
|
||
#发货后的操作,自动开发票
|
||
# 20230206要签收后开票 发货后开票暂时屏蔽
|
||
public function after_consign_autoinvoice($delivery_id){
|
||
// 发货后自动开票
|
||
return true;
|
||
$autoinvoice = app::get('ome')->getConf('ome.order.autoinvoice');
|
||
if ($autoinvoice != 'on') {
|
||
return true;
|
||
}
|
||
|
||
$deliveryOrderModel = app::get('ome')->model('delivery_order');
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
$deliveryOrderList = $deliveryOrderModel->getList('order_id',array('delivery_id'=>$delivery_id));
|
||
$orderIds = array_map('current', $deliveryOrderList);
|
||
if(!$orderIds)return true;
|
||
foreach($orderIds as $order_id){
|
||
#获取订单未开票的发票记录
|
||
$arr_filter = array('order_id' => $order_id,'is_status' => '0');
|
||
$rs_invoice = $mdlInOrder->getList('*', $arr_filter, 0, 1, 'id DESC');
|
||
if(!$rs_invoice)continue;
|
||
$arr_billing = array(
|
||
"id" => $rs_invoice[0]['id'],
|
||
"order_id" => $order_id,
|
||
);
|
||
#调开票的公用方法
|
||
$this->billing($arr_billing, 'consign');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 保存改票信息内容
|
||
* @Author: xueding
|
||
* @Vsersion: 2022/10/25 下午4:51
|
||
* @param $data
|
||
* @return array
|
||
*/
|
||
public function addChangeTicketData($data)
|
||
{
|
||
$mdlInOrder = app::get('invoice')->model('order');
|
||
if ($data) {
|
||
if ($invoiceInfo = $mdlInOrder->db_dump($data['id'])) {
|
||
$memoList = array();
|
||
$oldmemo = @unserialize($invoiceInfo['memo']);
|
||
if (is_array($oldmemo) && end($oldmemo)['op_content'] != $data['memo']) {
|
||
$op_name = kernel::single('desktop_user')->get_name();
|
||
if ($oldmemo) {
|
||
foreach ($oldmemo as $k => $v) {
|
||
$memoList[] = $v;
|
||
}
|
||
}
|
||
$newmemo = htmlspecialchars($data['memo']);
|
||
$newmemo = array('op_name' => $op_name, 'op_time' => date('Y-m-d H:i:s', time()), 'op_content' => $newmemo);
|
||
$memoList[] = $newmemo;
|
||
|
||
}
|
||
$data['memo'] = @serialize($memoList);
|
||
$updateData = ['changesdf' => json_encode($data), 'change_status' => '1'];
|
||
//电票改票自动冲红
|
||
if ($invoiceInfo['mode'] == '1') {
|
||
$result = $mdlInOrder->update($updateData, ['id' => $data['id']]);
|
||
} else {
|
||
//纸票改票改为待冲红
|
||
$updateData['is_make_invoice'] = '2';
|
||
$result = $mdlInOrder->update($updateData, ['id' => $data['id']]);
|
||
}
|
||
}
|
||
|
||
$opObj = app::get('ome')->model('operation_log');
|
||
if ($result) {
|
||
$msg = '专票保存改票信息成功。';
|
||
if ($invoiceInfo['mode'] == '1') {
|
||
$msg = '电票保存改票信息成功。';
|
||
$param = array(
|
||
'id' => $data['id'],
|
||
'order_id' => $data['order_id'],
|
||
'invoice_action_type' => $_POST['invoice_action_type']
|
||
);
|
||
$cancelRes = $this->cancel($param, 'invoice_list');
|
||
if (!$cancelRes) {
|
||
return [false, '原票冲红失败'];
|
||
}
|
||
}
|
||
$opObj->write_log('invoice_edit@invoice', $data["id"], $msg);
|
||
|
||
return [true, $msg];
|
||
} else {
|
||
$msg = '保存改票信息失败。';
|
||
$opObj->write_log('invoice_edit@invoice', $data["id"], $msg);
|
||
return [false, $msg];
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建合并发票
|
||
* @Author: xueding
|
||
* @Vsersion: 2023/6/2 下午3:52
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function addMergeInvoice($params)
|
||
{
|
||
$id = explode(',',$params['item']['id']);
|
||
$invoiceOrderLib = kernel::single('invoice_order');
|
||
$invoiceMdl = app::get('invoice')->model('order');
|
||
$invoiceList = $invoiceMdl->getList('*',['id'=>$id]);
|
||
$invoiceList = array_column($invoiceList,null,'id');
|
||
//作废或者冲红原发票
|
||
$invoiceOrderLib->cancelOldInvoiceOrder($id);
|
||
|
||
$invoiceItemMdl = app::get('invoice')->model('order_items');
|
||
$data = $invoiceOrderLib->formatAddData($params['item']);
|
||
|
||
$items = $invoiceItemMdl->getList('*', ['id' => $id,'is_delete'=>'false']);
|
||
$bns = [];
|
||
foreach ($params['item']['bn'] as $item_id => $bn) {
|
||
$bns[$bn]['spec'] = $params['item']['specification'][$item_id];
|
||
$bns[$bn]['unit'] = $params['item']['unit'][$item_id];
|
||
$bns[$bn]['item_name'] = $params['item']['item_name'][$item_id];
|
||
$bns[$bn]['tax_code'] = $params['item']['tax_code'][$item_id];
|
||
}
|
||
foreach ($items as $key => $val) {
|
||
if (isset($bns[$val['bn']])) {
|
||
$items[$key]['specification'] = $bns[$val['bn']]['spec'];
|
||
$items[$key]['unit'] = $bns[$val['bn']]['unit'];
|
||
$items[$key]['item_name'] = $bns[$val['bn']]['item_name'];
|
||
$items[$key]['tax_code'] = $bns[$val['bn']]['tax_code'];
|
||
}
|
||
$items[$key]['original_id'] = $val['id'];
|
||
$items[$key]['original_item_id'] = $val['item_id'];
|
||
|
||
if ($invoiceList[$val['id']]['is_status'] == '1') {
|
||
$items[$key]['item_is_make_invoice'] = '0';
|
||
$items[$key]['inoperable_reason'] = '发票冲红中,暂不可操作';
|
||
}else{
|
||
$items[$key]['item_is_make_invoice'] = $val['item_is_make_invoice'];
|
||
}
|
||
}
|
||
$data['is_edit'] = 'true';
|
||
$data['org_id'] = 'true';
|
||
$data['items'] = $items;
|
||
if ($data['mode'] != '1') {
|
||
$data['mode'] = '3';
|
||
}
|
||
return $this->newCreate($data,'add_merge_invoice');
|
||
}
|
||
|
||
/**
|
||
* 生成开票申请单号
|
||
*/
|
||
public function getInvoiceApplyBn($source = 'b2c')
|
||
{
|
||
$type = 'INVOICE';
|
||
$prefix = 'INV' . date('Ymd');
|
||
$sign = kernel::single('eccommon_guid')->incId($type, $prefix, 6, true);
|
||
return $sign;
|
||
}
|
||
}
|