mirror of
https://gitee.com/ShopeX/OMS
synced 2026-04-06 06:55:36 +08:00
418 lines
17 KiB
PHP
418 lines
17 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
|
||
class finance_monthly_report_items {
|
||
private $monthly_report;
|
||
private $gap_list;
|
||
|
||
/**
|
||
* 获取ItemId
|
||
* @param mixed $sdf sdf
|
||
* @param mixed $insert insert
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function getItemId($sdf, $insert = true) {
|
||
if(!$sdf['order_bn']) {
|
||
return 0;
|
||
}
|
||
$shop_id = $sdf['channel_id'];
|
||
$time = $sdf['trade_time'];
|
||
if(!isset($this->monthly_report[$shop_id]))
|
||
{
|
||
$mdlMonthlyReport = app::get('finance')->model('monthly_report');
|
||
$mr = $mdlMonthlyReport->getList('monthly_id,begin_time,end_time',array('shop_id'=>$shop_id,'status|lthan'=>2));
|
||
$this->monthly_report[$shop_id] = array_column($mr, null, 'monthly_id');
|
||
}
|
||
$mr = $this->monthly_report[$shop_id];
|
||
$oMRI = app::get('finance')->model('monthly_report_items');
|
||
$items = $oMRI->getList('id,monthly_id', ['order_bn'=>$sdf['order_bn']]);
|
||
if($items) {
|
||
foreach($items as $v) {
|
||
if($mr[$v['monthly_id']])
|
||
{
|
||
return $v['id'];
|
||
}
|
||
}
|
||
}
|
||
if(!$insert) {
|
||
return 0;
|
||
}
|
||
foreach ($mr as $v)
|
||
{
|
||
if($v['begin_time'] <= $time and $v['end_time'] >= $time )
|
||
{
|
||
$data = [
|
||
'order_bn' => $sdf['order_bn'],
|
||
'monthly_id' => $v['monthly_id'],
|
||
];
|
||
$rs = $oMRI->insert($data);
|
||
if($rs) {
|
||
return $data['id'];
|
||
}
|
||
return $oMRI->db_dump($data, 'id')['id'];
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* doAutoVerificate
|
||
* @param mixed $itemId ID
|
||
* @param mixed $shop_id ID
|
||
* @return mixed 返回值
|
||
*/
|
||
public function doAutoVerificate($itemId, $shop_id) {
|
||
if(empty($itemId)) {
|
||
return [false, ['msg'=>'缺少单据']];
|
||
}
|
||
list($rs, $rsData) = $this->doGapRule($itemId, $shop_id);
|
||
$oMRI = app::get('finance')->model('monthly_report_items');
|
||
if(app::get('finance')->model('bill')->db_dump(['status|noequal'=>'2', 'monthly_item_id'=>$itemId], 'bill_id')
|
||
|| app::get('finance')->model('ar')->db_dump(['status|noequal'=>'2', 'monthly_item_id'=>$itemId], 'ar_id')
|
||
) {
|
||
$oMRI->update(['gap_type'=>'', 'memo'=>$rsData['msg'], 'verification_status'=>'1'], ['id'=>$itemId]);
|
||
} else {
|
||
$upData = ['verification_status'=>'2', 'memo'=>'', 'gap_type'=>''];
|
||
if($rsData['msg']) {
|
||
$upData['memo'] = $rsData['msg'];
|
||
}
|
||
if($rsData['gap_type']) {
|
||
$upData['gap_type'] = $rsData['gap_type'];
|
||
}
|
||
$oMRI->update($upData, ['id'=>$itemId]);
|
||
}
|
||
|
||
$servicelist = kernel::servicelist('financebase.reportitem.doAutoVerificate.after');
|
||
foreach ($servicelist as $instance) {
|
||
if (method_exists($instance, 'after_verificate')){
|
||
$instance->after_verificate($itemId);
|
||
}
|
||
}
|
||
|
||
return [$rs, $rsData];
|
||
}
|
||
|
||
/**
|
||
* doGapRule
|
||
* @param mixed $itemId ID
|
||
* @param mixed $shop_id ID
|
||
* @return mixed 返回值
|
||
*/
|
||
public function doGapRule($itemId, $shop_id) {
|
||
if(!isset($this->gap_list)) {
|
||
$this->gap_list = array();
|
||
$mdlBillVerificationError = app::get('financebase')->model('bill_verification_error');
|
||
foreach ($mdlBillVerificationError->getList('rule,is_verify,verify_mode,shop_id,name', array(), 0, -1, 'priority desc') as $key => $value) {
|
||
$this->gap_list[$value['shop_id']][] = $value;
|
||
}
|
||
}
|
||
# 三位小数
|
||
$diff = $this->getDiffMoney($itemId);
|
||
$gap_list = $this->gap_list[$shop_id] ? : [];
|
||
$z = $p = $pz = true;
|
||
foreach ($gap_list as $gap) {
|
||
if($gap['verify_mode'] == '1') {
|
||
##收入
|
||
if($z) {
|
||
$diff_money = $diff['yingshou_money'] - $diff['shishou_money'];
|
||
$diff_money = sprintf('%.3f', $diff_money);
|
||
list($zrs, $zrsData) = $this->gapCalc($gap, $diff_money, $itemId, 'z');
|
||
if($zrsData['msg'] != '未匹配到核销规则') {
|
||
$z = false;
|
||
}
|
||
$zrsData['msg'] = '收入:'.$zrsData['msg'];
|
||
}
|
||
#退款
|
||
if($p) {
|
||
$diff_money = $diff['yingtui_money'] - $diff['shitui_money'];
|
||
$diff_money = sprintf('%.3f', $diff_money);
|
||
list($prs, $prsData) = $this->gapCalc($gap, $diff_money, $itemId, 'p');
|
||
if($prsData['msg'] != '未匹配到核销规则') {
|
||
$p = false;
|
||
}
|
||
$prsData['msg'] = '退款:'.$prsData['msg'];
|
||
}
|
||
#缺少实收实退
|
||
if($diff['shishou_money'] == 0 && $diff['shitui_money'] == 0 && $pz) {
|
||
$diff_money = $diff['yingtui_money'] + $diff['yingshou_money'];
|
||
$diff_money = sprintf('%.3f', $diff_money);
|
||
list($pzrs, $pzrsData) = $this->gapCalc($gap, $diff_money, $itemId, 'ying');
|
||
if($pzrsData['msg'] != '未匹配到核销规则') {
|
||
$pz = false;
|
||
}
|
||
$pzrsData['msg'] = '应收应退:'.$pzrsData['msg'];
|
||
}
|
||
if(!$z && !$p && !$pz) {
|
||
$rsData = $zrsData;
|
||
$rsData['msg'] .= $prsData['msg'];
|
||
$rsData['msg'] .= $pzrsData['msg'];
|
||
return [($zrs && $prs && $pzrs), $rsData];
|
||
}
|
||
} else {
|
||
$diff_money = $diff['gap'];
|
||
$diff_money = sprintf('%.3f', $diff_money);
|
||
list($rs, $rsData) = $this->gapCalc($gap, $diff_money, $itemId);
|
||
if($rsData['msg'] != '未匹配到核销规则') {
|
||
return [$rs, $rsData];
|
||
}
|
||
}
|
||
}
|
||
return [false, ['msg'=>$gap_list ? '未匹配到核销规则' : '未配置核销规则']];
|
||
}
|
||
|
||
/**
|
||
* gapCalc
|
||
* @param mixed $gap gap
|
||
* @param mixed $diff_money diff_money
|
||
* @param mixed $itemId ID
|
||
* @param mixed $compare compare
|
||
* @return mixed 返回值
|
||
*/
|
||
public function gapCalc($gap, $diff_money, $itemId, $compare = 'order') {
|
||
$expression = array();
|
||
foreach ($gap['rule'] as $rule) {
|
||
$expression[] = str_replace('{field}', $diff_money, $this->get_comp($rule['operator'], $rule['operand']));
|
||
}
|
||
|
||
$expression = implode(' && ', array_filter($expression));
|
||
$result = false;
|
||
eval("\$result=($expression);");
|
||
|
||
if ($result) {
|
||
|
||
// 强制核销
|
||
if ($gap['is_verify'] == 1) {
|
||
$sdf = [
|
||
'gap_type' => $gap['name'],
|
||
'verification_status' => $diff_money == 0 ? 1 : 2,
|
||
'compare' => $compare
|
||
];
|
||
list($verRs, $rsData) = $this->doVerificate($itemId, $sdf);
|
||
$rsData['gap_type'] = $sdf['gap_type'];
|
||
return [$verRs, $rsData];
|
||
}
|
||
|
||
return [false, ['msg'=>$gap['name'] . '未开启核销']];
|
||
}
|
||
return [false, ['msg' => '未匹配到核销规则']];
|
||
}
|
||
|
||
/**
|
||
* 获取DiffMoney
|
||
* @param mixed $itemId ID
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function getDiffMoney($itemId) {
|
||
$arlist = app::get('finance')->model('ar')->getList('money,type,trade_time', ['monthly_item_id' => $itemId]);
|
||
$upData = ['yingshou_money'=>0, 'yingtui_money'=>0, 'refund_only_money'=>0,'shishou_money'=>0,'shitui_money'=>0];
|
||
foreach ($arlist as $arRow) {
|
||
if($arRow['money'] > 0) {
|
||
$upData['ship_time'] = $arRow['trade_time'];
|
||
$upData['yingshou_money'] += $arRow['money'];
|
||
} else {
|
||
$upData['reship_time'] = $arRow['trade_time'];
|
||
$upData['yingtui_money'] += $arRow['money'];
|
||
if($arRow['type'] == kernel::single('finance_ar')->get_type_by_name('售后仅退款')) {
|
||
$upData['refund_only_money'] += $arRow['money'];
|
||
}
|
||
}
|
||
}
|
||
$upData['xiaotui_total'] = $upData['yingshou_money'] + $upData['yingtui_money'];
|
||
$billList = app::get('finance')->model('bill')->getList('money,trade_time', ['monthly_item_id' => $itemId]);
|
||
foreach ($billList as $billRow) {
|
||
if($billRow['money'] > 0) {
|
||
$upData['shishou_trade_time'] = $billRow['trade_time'];
|
||
$upData['shishou_money'] += $billRow['money'];
|
||
} else {
|
||
$upData['shitui_trade_time'] = $billRow['trade_time'];
|
||
$upData['shitui_money'] += $billRow['money'];
|
||
}
|
||
}
|
||
$upData['shouzhi_total'] = $upData['shishou_money'] + $upData['shitui_money'];
|
||
$upData['gap'] = $upData['xiaotui_total'] - $upData['shouzhi_total'];
|
||
app::get('finance')->model('monthly_report_items')->update($upData, ['id'=>$itemId]);
|
||
return $upData;
|
||
}
|
||
|
||
/**
|
||
* 获取_comp
|
||
* @param mixed $type type
|
||
* @param mixed $var var
|
||
* @return mixed 返回结果
|
||
*/
|
||
public function get_comp($type, $var)
|
||
{
|
||
$comp = array(
|
||
'nequal' => '{field}==' . $var,
|
||
'than' => '{field}> ' . $var,
|
||
'lthan' => '{field}< ' . $var,
|
||
'bthan' => '{field}>=' . $var,
|
||
'sthan' => '{field}<=' . $var,
|
||
'between' => '{field}>=' . $var[0] . ' && ' . ' {field}<=' . $var[1],
|
||
);
|
||
|
||
return $comp[$type];
|
||
}
|
||
|
||
/**
|
||
* doVerificate
|
||
* @param mixed $itemId ID
|
||
* @param mixed $sdf sdf
|
||
* @return mixed 返回值
|
||
*/
|
||
public function doVerificate($itemId, $sdf) {
|
||
$verification_time = time();
|
||
$filter = ['status|noequal'=>'2', 'monthly_item_id'=>$itemId];
|
||
if($sdf['compare'] == 'z') {
|
||
$filter['money|than'] = 0;
|
||
} elseif($sdf['compare'] == 'p') {
|
||
$filter['money|lthan'] = 0;
|
||
}
|
||
$mdlBill = app::get('finance')->model('bill');
|
||
if($sdf['compare'] == 'ying') {
|
||
$bill_data = [];
|
||
} else {
|
||
$bill_data = $mdlBill->getList('bill_id,bill_bn,money,memo', $filter);
|
||
}
|
||
foreach ($bill_data as $key => $value) {
|
||
// 更新核销流水表
|
||
$data = array();
|
||
$data['verification_time'] = $verification_time;
|
||
$data['status'] = 2;
|
||
$data['confirm_money'] = $value['money'];
|
||
$data['unconfirm_money'] = 0;
|
||
$data['verification_status'] = $sdf['verification_status'];
|
||
$data['gap_type'] = $sdf['gap_type'];
|
||
$data['memo'] = ($sdf['compare'] == 'z' ? '按收入核销' : ($sdf['compare'] == 'p' ? '按退款核销' : '按订单核销')) . ' ' . $value['memo'];
|
||
$data['auto_flag'] = 1;
|
||
|
||
$mdlBill->update($data,array('bill_id'=>$value['bill_id'],'status|noequal'=>'2'));
|
||
}
|
||
$mdlAr = app::get('finance')->model('ar');
|
||
$ar_data = $mdlAr->getList('ar_id, money', $filter);
|
||
foreach ($ar_data as $key => $value) {
|
||
$data = array();
|
||
if(in_array($sdf['compare'], ['order','ying']) && empty($bill_data)) {
|
||
$data['verification_flag'] = 1;
|
||
}
|
||
$data['verification_time'] = $verification_time;
|
||
$data['verification_status'] = $sdf['verification_status'];
|
||
$data['gap_type'] = $sdf['gap_type'];
|
||
$data['status'] = 2;
|
||
$data['confirm_money'] = $value['money'];
|
||
$data['unconfirm_money'] = 0;
|
||
$data['memo'] = ($sdf['compare'] == 'z' ? '按收入核销' : ($sdf['compare'] == 'p' ? '按退款核销' : '按订单核销')) . ' ' . '实收实退单据号:'. implode('|', array_column($bill_data,'bill_bn')) ;
|
||
$data['auto_flag'] = 1;
|
||
|
||
$mdlAr->update($data,array('ar_id'=>$value['ar_id'],'status|noequal'=>'2'));
|
||
}
|
||
return [true, ['msg'=>'核销成功']];
|
||
}
|
||
|
||
/**
|
||
* dealArMatchReport
|
||
* @param mixed $ar_id ID
|
||
* @return mixed 返回值
|
||
*/
|
||
public function dealArMatchReport($ar_id) {
|
||
$oMonthlyReportItems = kernel::single('finance_monthly_report_items');
|
||
$oAr = app::get('finance')->model('ar');
|
||
$arRow = $oAr->db_dump($ar_id, 'ar_id,ar_bn,order_bn,channel_id,trade_time,money,monthly_item_id,channel_id,ar_type');
|
||
if(empty($arRow)) {
|
||
return [false, ['msg'=>'缺少单据']];
|
||
}
|
||
if($arRow['monthly_item_id']) {
|
||
return [false, ['msg'=>$arRow['ar_bn'].'已经匹配账期']];
|
||
}
|
||
$init_time = app::get('finance')->getConf('finance_setting_init_time');
|
||
if($init_time['according'] == 'shi_shou') {
|
||
$itemId = $oMonthlyReportItems->getItemId($arRow, false);
|
||
if(empty($itemId) && $arRow['ar_type'] == 1) {
|
||
$order = app::get('ome')->model('orders')->db_dump(['order_bn'=>$arRow['order_bn']], 'source_status');
|
||
if($order['source_status'] == 'TRADE_CLOSED') {
|
||
$itemId = $oMonthlyReportItems->getItemId($arRow);
|
||
$arRows = $oAr->getList('ar_id',['order_bn'=>$arRow['order_bn'], 'monthly_item_id'=>0, 'ar_id|noequal'=>$arRow['ar_id']]);
|
||
if($arRows) {
|
||
foreach($arRows as $v) {
|
||
$this->dealArMatchReport($v['ar_id']);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
$itemId = $oMonthlyReportItems->getItemId($arRow);
|
||
$oBill = app::get('finance')->model('bill');
|
||
$billRows = $oBill->getList('bill_id',['order_bn'=>$arRow['order_bn'], 'monthly_item_id'=>0]);
|
||
if($billRows) {
|
||
foreach($billRows as $v) {
|
||
$this->dealBillMatchReport($v['bill_id']);
|
||
}
|
||
}
|
||
}
|
||
if($itemId) {
|
||
kernel::database()->beginTransaction();
|
||
$sql = 'select id, monthly_id, yingshou_money, yingtui_money, xiaotui_total, shouzhi_total
|
||
from sdb_finance_monthly_report_items
|
||
where id="'.$itemId.'" limit 1 for update';
|
||
$itemMRI = kernel::database()->select($sql);
|
||
$itemMRI = $itemMRI[0];
|
||
$main = [];
|
||
$main['monthly_id'] = $itemMRI['monthly_id'];
|
||
$main['monthly_item_id'] = $itemId;
|
||
$oAr->update($main, ['ar_id'=>$arRow['ar_id']]);
|
||
kernel::single('finance_monthly_report_items')->doAutoVerificate($itemId, $arRow['channel_id']);
|
||
kernel::database()->commit();
|
||
return [true, ['msg' => $arRow['ar_bn'].'匹配成功', 'monthly_id'=>$itemMRI['monthly_id']]];
|
||
}
|
||
return [false, ['msg' => $arRow['ar_bn'].'匹配失败']];
|
||
}
|
||
|
||
/**
|
||
* dealBillMatchReport
|
||
* @param mixed $bill_id ID
|
||
* @return mixed 返回值
|
||
*/
|
||
public function dealBillMatchReport($bill_id) {
|
||
$oMonthlyReportItems = kernel::single('finance_monthly_report_items');
|
||
$oBill = app::get('finance')->model('bill');
|
||
$billRow = $oBill->db_dump($bill_id, 'bill_id,bill_bn,order_bn,channel_id,trade_time,money,monthly_item_id,channel_id');
|
||
if(empty($billRow)) {
|
||
return [false, ['msg'=>'缺少单据']];
|
||
}
|
||
if($billRow['monthly_item_id']) {
|
||
return [false, ['msg'=>$billRow['bill_bn'].'已经匹配账期']];
|
||
}
|
||
$init_time = app::get('finance')->getConf('finance_setting_init_time');
|
||
if($init_time['according'] == 'shi_shou') {
|
||
$itemId = $oMonthlyReportItems->getItemId($billRow);
|
||
$oAr = app::get('finance')->model('ar');
|
||
$arRows = $oAr->getList('ar_id',['order_bn'=>$billRow['order_bn'], 'monthly_item_id'=>0]);
|
||
if($arRows) {
|
||
foreach($arRows as $v) {
|
||
$this->dealArMatchReport($v['ar_id']);
|
||
}
|
||
}
|
||
} else {
|
||
$itemId = $oMonthlyReportItems->getItemId($billRow, false);
|
||
}
|
||
if($itemId) {
|
||
kernel::database()->beginTransaction();
|
||
$sql = 'select id, monthly_id, xiaotui_total, shishou_money, shitui_money, shouzhi_total
|
||
from sdb_finance_monthly_report_items
|
||
where id="'.$itemId.'" limit 1 for update';
|
||
$itemMRI = kernel::database()->select($sql);
|
||
$itemMRI = $itemMRI[0];
|
||
$main = [];
|
||
$main['monthly_id'] = $itemMRI['monthly_id'];
|
||
$main['monthly_item_id'] = $itemId;
|
||
$oBill->update($main, ['bill_id'=>$billRow['bill_id']]);
|
||
kernel::single('finance_monthly_report_items')->doAutoVerificate($itemId, $billRow['channel_id']);
|
||
kernel::database()->commit();
|
||
return [true, ['msg' => $billRow['bill_bn'].'匹配成功', 'monthly_id'=>$itemMRI['monthly_id']]];
|
||
}
|
||
return [false, ['msg' => $billRow['bill_bn'].'匹配失败']];
|
||
}
|
||
} |