mirror of
https://gitee.com/ShopeX/OMS
synced 2026-04-19 19:55:28 +08:00
1. 【新增】售后单售后原因类型支持搜索
2. 【新增】手工创建订单折扣可输入正数 3. 【优化】盘点申请单确认 4. 【修复】采购退货单模拟出库失败问题 5. 【新增】订单金额客户实付与结算金额 6. 【优化】仓库发货统计报表物料名称显示 7. 【优化】自有仓储虚拟发货逻辑 8. 【修复】基础物料分类管理问题
This commit is contained in:
@@ -330,11 +330,11 @@ class financebase_data_bill_alipay extends financebase_abstract_bill
|
||||
$title = array_values($this->getTitle());
|
||||
sort($title);
|
||||
|
||||
$aliTitle = $row[1];
|
||||
/* $aliTitle = $row[1];
|
||||
sort($aliTitle);
|
||||
if ($title == $aliTitle) {
|
||||
return array(true, '文件模板匹配', $row[1]);
|
||||
}
|
||||
} */
|
||||
|
||||
$aliTitle = $row[4];
|
||||
sort($aliTitle);
|
||||
|
||||
251
app/financebase/lib/data/bill/guobu.php
Normal file
251
app/financebase/lib/data/bill/guobu.php
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
/**
|
||||
* 处理国补金额导入
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
class financebase_data_bill_guobu extends financebase_abstract_bill
|
||||
{
|
||||
public $column_num = 5; // 5个字段:订单号、国补金额、SKU、数量、账单日期
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
private static $shop_type_cache = array(); // 静态变量缓存店铺类型数据
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
$title = array(
|
||||
'order_bn' => '订单号',
|
||||
'amount' => '国补金额',
|
||||
'sku' => 'SKU',
|
||||
'quantity' => '数量',
|
||||
'trade_time' => '账单日期'
|
||||
);
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getSdf($row, $offset = 1, $title)
|
||||
{
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
if (!$this->ioTitle) {
|
||||
$this->ioTitle = $this->getTitle();
|
||||
$this->ioTitleKey = array_keys($this->ioTitle);
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $this->getTitle());
|
||||
if ($titleKey[$k] === false) {
|
||||
return array('status' => false, 'msg' => '未定义字段`' . $t . '`');
|
||||
}
|
||||
}
|
||||
|
||||
$res = array('status' => true, 'data' => array(), 'msg' => '');
|
||||
|
||||
if ($this->column_num <= count($row) && $row[0] != '订单号') {
|
||||
$tmp = array_combine($titleKey, $row);
|
||||
|
||||
// 必填字段验证
|
||||
$required_fields = array('order_bn', 'amount', 'sku', 'quantity', 'trade_time');
|
||||
foreach ($required_fields as $field) {
|
||||
if (empty($tmp[$field])) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, $this->ioTitle[$field]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 金额格式验证
|
||||
if (!is_numeric($tmp['amount'])) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 金额(%s)格式错误!", $offset, $this->ioTitle['amount'], $tmp['amount']);
|
||||
return $res;
|
||||
}
|
||||
|
||||
// 数量格式验证
|
||||
if (!is_numeric($tmp['quantity']) || $tmp['quantity'] <= 0) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 数量(%s)必须为正数!", $offset, $this->ioTitle['quantity'], $tmp['quantity']);
|
||||
return $res;
|
||||
}
|
||||
|
||||
// 日期格式验证
|
||||
if (!strtotime($tmp['trade_time'])) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 日期(%s)格式错误!", $offset, $this->ioTitle['trade_time'], $tmp['trade_time']);
|
||||
return $res;
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function _filterData($data)
|
||||
{
|
||||
$new_data = array();
|
||||
|
||||
$new_data['order_bn'] = $this->_getOrderBn($data);
|
||||
$new_data['trade_no'] = '';
|
||||
$new_data['financial_no'] = $data['order_bn'];
|
||||
$new_data['out_trade_no'] = '';
|
||||
$new_data['trade_time'] = strtotime($data['trade_time']);
|
||||
$new_data['trade_type'] = '国补金额';
|
||||
$new_data['money'] = $data['amount'];
|
||||
$new_data['member'] = '';
|
||||
|
||||
// unique_id 生成规则:shop_id + 订单号 + SKU + 国补金额的MD5
|
||||
$shop_id = $data['shop_id'] ?: $this->getCurrentShopId();
|
||||
$new_data['unique_id'] = md5($shop_id . '-' . $data['order_bn'] . '-' . $data['sku'] . '-' . $data['amount']);
|
||||
|
||||
$shop_info = $this->getShopInfoByShopId($shop_id);
|
||||
$new_data['platform_type'] = $shop_info ? $shop_info['shop_type'] : '';
|
||||
$new_data['remarks'] = '国补金额导入-SKU:' . $data['sku'] . ' 数量:' . $data['quantity'];
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
return $params['order_bn'];
|
||||
}
|
||||
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
// 国补金额固定类别
|
||||
return '国补金额';
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
* @param string $file_name 文件名
|
||||
* @param string $file_type 文件类型
|
||||
* @return array [是否有效, 错误信息, 标题]
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
$row = $ioType->getData($file_name, 0, 1);
|
||||
$title = array_values($this->getTitle());
|
||||
sort($title);
|
||||
|
||||
$guobuTitle = $row[0];
|
||||
sort($guobuTitle);
|
||||
if ($title == $guobuTitle) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
if (!array_diff($guobuTitle, $title)) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
return array(false, '文件模板错误:' . var_export($row[0], true) . ',正确的为:' . var_export($title, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入日期列配置
|
||||
* @param array $title 标题数组
|
||||
* @return array
|
||||
*/
|
||||
public function getImportDateColunm($title = null)
|
||||
{
|
||||
// 国补导入的日期字段配置
|
||||
$timeColumn = ['账单日期'];
|
||||
$timeCol = array();
|
||||
foreach ($timeColumn as $v) {
|
||||
if($k = array_search($v, $title)) {
|
||||
$timeCol[] = $k+1;
|
||||
}
|
||||
}
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
|
||||
public function syncToBill($data, $bill_category = '')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if (!$data['content']) return false;
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
$oMonthlyReport = kernel::single('finance_monthly_report');
|
||||
|
||||
$tmp['fee_obj'] = '国补';
|
||||
$tmp['fee_item'] = '国补金额';
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if (!$res['status']) return false;
|
||||
|
||||
if (!$data['shop_name']) {
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $tmp['order_bn'],
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => strtotime($tmp['trade_time']),
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($tmp['amount'], 2),
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => $tmp['order_bn'],
|
||||
'member' => '',
|
||||
'memo' => $tmp['remarks'],
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => $tmp['fee_item'],
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1,
|
||||
'charge_time' => time(),
|
||||
'monthly_id' => 0,
|
||||
'monthly_item_id' => 0,
|
||||
'monthly_status' => 0,
|
||||
'crc32_order_bn' => sprintf('%u', crc32($tmp['order_bn'])),
|
||||
'bill_bn' => $mdlBill->gen_bill_bn(),
|
||||
'unconfirm_money' => round($tmp['money'], 2),
|
||||
);
|
||||
|
||||
if ($mdlBill->insert($base_sdf)) {
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getShopInfoByShopId($shop_id)
|
||||
{
|
||||
if (!$shop_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果缓存为空,一次性查询所有店铺数据
|
||||
if (empty(self::$shop_type_cache)) {
|
||||
$mdlShop = app::get('ome')->model('shop');
|
||||
$shop_list = $mdlShop->getList('shop_id,shop_type');
|
||||
|
||||
// 将数据存入静态缓存,key为shop_id,value为shop数组
|
||||
foreach ($shop_list as $shop) {
|
||||
self::$shop_type_cache[$shop['shop_id']] = $shop;
|
||||
}
|
||||
}
|
||||
|
||||
// 从缓存中获取shop信息
|
||||
if (isset(self::$shop_type_cache[$shop_id])) {
|
||||
return self::$shop_type_cache[$shop_id];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getCurrentShopId()
|
||||
{
|
||||
// 从当前请求中获取shop_id
|
||||
return $_POST['shop_id'] ?? '';
|
||||
}
|
||||
}
|
||||
352
app/financebase/lib/data/bill/jdecard.php
Normal file
352
app/financebase/lib/data/bill/jdecard.php
Normal file
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
/**
|
||||
* 处理京东E卡结算单导入
|
||||
*
|
||||
* @author 334395174@qq.com
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
class financebase_data_bill_jdecard extends financebase_abstract_bill
|
||||
{
|
||||
public $order_bn_prefix = '';
|
||||
|
||||
public $column_num = 11;
|
||||
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
public $verified_data = array();
|
||||
public $shop_list_by_name = array();
|
||||
|
||||
// 处理数据
|
||||
public function getSdf($row, $offset=1, $title)
|
||||
{
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
if(!$this->ioTitle){
|
||||
$this->ioTitle = $this->getTitle();
|
||||
$this->ioTitleKey = array_keys($this->ioTitle);
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $this->getTitle());
|
||||
|
||||
if ($titleKey[$k] === false) {
|
||||
return array('status' => false, 'msg' => '未定义字段`' . $t . '`');
|
||||
}
|
||||
}
|
||||
|
||||
$res = array('status'=>true, 'data'=>array(), 'msg'=>'');
|
||||
|
||||
if($this->column_num <= count($row) and $row[0] != '订单编号')
|
||||
{
|
||||
$tmp = array_combine($titleKey, $row);
|
||||
|
||||
// 判断必填参数不能为空
|
||||
foreach ($tmp as $k => $v) {
|
||||
// 必填字段验证:订单编号、费用项、金额
|
||||
if(in_array($k, array('order_no', 'trade_type', 'amount')))
|
||||
{
|
||||
if(!$v)
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, $this->ioTitle[$k]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 时间格式验证
|
||||
if(in_array($k, array('order_create_time', 'order_complete_time')))
|
||||
{
|
||||
if($v) {
|
||||
$result = finance_io_bill_verify::isDate($v);
|
||||
if ($result['status'] == 'fail')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 时间(%s)格式错误!", $offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 金额格式验证
|
||||
if(in_array($k, array('amount')))
|
||||
{
|
||||
$result = finance_io_bill_verify::isPrice($v);
|
||||
if ($result['status'] == 'fail')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 金额(%s)格式错误!", $offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 清理特殊字符(订单编号、商品编号等)
|
||||
if(in_array($k, array('order_no', 'goods_bn', 'branch_id', 'store_bn'))){
|
||||
$tmp[$k] = trim($v, '=\"');
|
||||
}
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
$title = array(
|
||||
'order_no' => '订单编号',
|
||||
'goods_bn' => '商品编号',
|
||||
'goods_number' => 'SKU数量',
|
||||
'goods_name' => '商品名称',
|
||||
'order_create_time' => '下单时间',
|
||||
'order_complete_time' => '完成时间',
|
||||
'trade_type' => '费用项',
|
||||
'amount' => '金额',
|
||||
'branch_id' => '分公司id',
|
||||
'store_bn' => '门店编号',
|
||||
'tax_rate' => '税率',
|
||||
);
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
// 获取订单号
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
// 直接返回订单编号
|
||||
if (isset($params['order_no']) && $params['order_no']) {
|
||||
return $params['order_no'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取具体类别
|
||||
* @Author YangYiChao
|
||||
* @Date 2019-06-03
|
||||
* @param [Array] $params 参数
|
||||
* @return [String] 具体类别
|
||||
*/
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
if(!$this->rules) {
|
||||
$this->getRules('360buy'); // 使用360buy的规则
|
||||
}
|
||||
|
||||
$this->verified_data = $params;
|
||||
|
||||
if($this->rules)
|
||||
{
|
||||
foreach ($this->rules as $item)
|
||||
{
|
||||
foreach ($item['rule_content'] as $rule) {
|
||||
if($this->checkRule($rule)) {
|
||||
return $item['bill_category'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
* @Author YangYiChao
|
||||
* @Date 2019-06-25
|
||||
* @param String $file_name 文件名
|
||||
* @param String $file_type 文件类型
|
||||
* @return Boolean
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
if ($file_type !== 'xlsx') {
|
||||
return array(false, '京东E卡导入只支持.xlsx格式的Excel文件');
|
||||
}
|
||||
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
$row = $ioType->getData($file_name, 0, 1, 0); // 读取第一个工作表
|
||||
|
||||
if (empty($row) || !isset($row[0])) {
|
||||
return array(false, '文件没有数据');
|
||||
}
|
||||
|
||||
$title = array_values($this->getTitle());
|
||||
sort($title);
|
||||
|
||||
$jdecardTitle = $row[0];
|
||||
sort($jdecardTitle);
|
||||
|
||||
// 完全匹配
|
||||
if ($title == $jdecardTitle) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
// 包含所有必需列
|
||||
if (!array_diff($jdecardTitle, $title)) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
return array(false, '文件模板错误:' . var_export($row[0], true) . ',正确的为:' . var_export($title, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步到对账表
|
||||
* @Author YangYiChao
|
||||
* @Date 2019-06-25
|
||||
* @param Array 原始数据 $data
|
||||
* @param String 具体类别 $bill_category
|
||||
* @return Boolean
|
||||
*/
|
||||
public function syncToBill($data, $bill_category='')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if(!$data['content']) return false;
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
$oMonthlyReport = kernel::single('finance_monthly_report');
|
||||
|
||||
$tmp['fee_obj'] = '京东E卡';
|
||||
$tmp['fee_item'] = $bill_category;
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if(!$res['status']) return false;
|
||||
|
||||
if(!$data['shop_name']){
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $this->_getOrderBn($tmp),
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => isset($tmp['order_complete_time']) ? strtotime($tmp['order_complete_time']) : 0,
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($tmp['amount'], 2), // 保留正负
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => isset($tmp['financial_no']) ? $tmp['financial_no'] : '', // 使用生成的唯一编码
|
||||
'member' => '',
|
||||
'memo' => isset($tmp['goods_name']) ? $tmp['goods_name'] : '', // 备注保存商品名称
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => isset($tmp['trade_type']) ? $tmp['trade_type'] : '',
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1, // 流水直接设置记账成功
|
||||
'charge_time' => time(),
|
||||
);
|
||||
|
||||
$base_sdf['monthly_id'] = 0;
|
||||
$base_sdf['monthly_item_id'] = 0;
|
||||
$base_sdf['monthly_status'] = 0;
|
||||
|
||||
$base_sdf['crc32_order_bn'] = sprintf('%u', crc32($base_sdf['order_bn']));
|
||||
$base_sdf['bill_bn'] = $mdlBill->gen_bill_bn();
|
||||
$base_sdf['unconfirm_money'] = $base_sdf['money'];
|
||||
|
||||
if($mdlBill->insert($base_sdf)){
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新订单号
|
||||
public function updateOrderBn($data)
|
||||
{
|
||||
$this->_formatData($data);
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
|
||||
if(!$this->shop_list_by_name)
|
||||
{
|
||||
$this->shop_list_by_name = financebase_func::getShopList(financebase_func::getShopType());
|
||||
$this->shop_list_by_name = array_column($this->shop_list_by_name, null, 'name');
|
||||
}
|
||||
|
||||
foreach ($data as $v)
|
||||
{
|
||||
if('订单编号' == $v[0]) continue;
|
||||
|
||||
// 假设最后3列是:店铺名称、账单号、订单号
|
||||
if(!isset($v[11]) || !isset($v[12]) || !isset($v[13])) continue;
|
||||
if(!$v[11] || !$v[12] || !$v[13]) continue;
|
||||
|
||||
$shop_id = isset($this->shop_list_by_name[$v[11]]) ? $this->shop_list_by_name[$v[11]]['shop_id'] : 0;
|
||||
if(!$shop_id) continue;
|
||||
|
||||
$filter = array('bill_bn' => $v[12], 'shop_id' => $shop_id);
|
||||
|
||||
// 找到unique_id
|
||||
$bill_info = $mdlBill->getList('unique_id,bill_id', $filter, 0, 1);
|
||||
if(!$bill_info) continue;
|
||||
$bill_info = $bill_info[0];
|
||||
|
||||
if($mdlBill->update(array('order_bn' => $v[13]), array('bill_id' => $bill_info['bill_id'])))
|
||||
{
|
||||
app::get('financebase')->model('bill')->update(array('order_bn' => $v[13]), array('unique_id' => $bill_info['unique_id'], 'shop_id' => $shop_id));
|
||||
$op_name = kernel::single('desktop_user')->get_name();
|
||||
$content = sprintf("订单号改成:%s", $v[13]);
|
||||
finance_func::addOpLog($v[12], $op_name, $content, '更新订单号');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function _filterData($data)
|
||||
{
|
||||
$new_data = array();
|
||||
|
||||
$new_data['order_bn'] = $this->_getOrderBn($data);
|
||||
$new_data['trade_no'] = isset($data['order_no']) ? $data['order_no'] : ''; // 使用订单编号
|
||||
|
||||
// 生成唯一编码:order_no + goods_bn + goods_number + trade_type + amount 的 MD5
|
||||
// 必须加入金额,因为同一订单同一商品可能既有正金额(货款)又有负金额(价保扣款)
|
||||
$unique_str = sprintf(
|
||||
'%s_%s_%s_%s_%s',
|
||||
isset($data['order_no']) ? $data['order_no'] : '',
|
||||
isset($data['goods_bn']) ? $data['goods_bn'] : '',
|
||||
isset($data['goods_number']) ? $data['goods_number'] : '',
|
||||
isset($data['trade_type']) ? $data['trade_type'] : '',
|
||||
isset($data['amount']) ? $data['amount'] : ''
|
||||
);
|
||||
$unique_code = md5($unique_str);
|
||||
|
||||
$new_data['financial_no'] = $unique_code; // 使用生成的唯一编码
|
||||
$new_data['out_trade_no'] = isset($data['goods_bn']) ? $data['goods_bn'] : ''; // 使用商品编号
|
||||
$new_data['trade_time'] = isset($data['order_complete_time']) ? strtotime($data['order_complete_time']) : 0;
|
||||
$new_data['trade_type'] = isset($data['trade_type']) ? $data['trade_type'] : '';
|
||||
$new_data['money'] = isset($data['amount']) ? floatval($data['amount']) : 0; // 保留正负
|
||||
$new_data['member'] = '';
|
||||
|
||||
// 使用生成的唯一编码作为唯一标识
|
||||
$new_data['unique_id'] = $unique_code;
|
||||
$new_data['platform_type'] = 'jdecard';
|
||||
$new_data['remarks'] = ''; // 备注为空
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
public function getImportDateColunm($title=null)
|
||||
{
|
||||
$timeColumn = array('下单时间', '完成时间');
|
||||
$timeCol = array();
|
||||
|
||||
if ($title) {
|
||||
foreach ($timeColumn as $v) {
|
||||
$k = array_search($v, $title);
|
||||
if ($k !== false) {
|
||||
$timeCol[] = $k + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
}
|
||||
|
||||
427
app/financebase/lib/data/bill/jdguobu.php
Normal file
427
app/financebase/lib/data/bill/jdguobu.php
Normal file
@@ -0,0 +1,427 @@
|
||||
<?php
|
||||
/**
|
||||
* 处理京东国补结算单导入
|
||||
* 多个金额列转换为多行数据(类似抖音处理逻辑)
|
||||
*
|
||||
* @author 334395174@qq.com
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
class financebase_data_bill_jdguobu extends financebase_abstract_bill
|
||||
{
|
||||
public $order_bn_prefix = '';
|
||||
public $column_num = 19; // 19个字段
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
public $verified_data = array();
|
||||
public $shop_list_by_name = array();
|
||||
|
||||
// 需要转换为行的金额列(金额不为0时才处理)
|
||||
public $column_to_row = [
|
||||
'commission', // 佣金
|
||||
'sop_amount', // SOP采购货款
|
||||
'service_fee', // 交易服务费
|
||||
'guobu_amount', // 国补采购款
|
||||
'large_store_amount', // 大店业务采购货款
|
||||
'promotion_service_fee', // 促销服务费
|
||||
'ad_commission', // 广告联合活动降扣佣金
|
||||
'link_service_fee', // 超链3.0服务费
|
||||
'final_amount', // 应结货款
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取标题映射
|
||||
* @return array
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
$title = array(
|
||||
'billing_time' => '计费时间',
|
||||
'complete_time' => '完成时间',
|
||||
'order_no' => '订单编号',
|
||||
'order_total_amount' => '订单总金额',
|
||||
'merchant_promotion' => '商家促销金额',
|
||||
'full_reduction' => '满减优惠金额',
|
||||
'shop_jingquan' => '店铺京券金额',
|
||||
'shop_dongquan' => '店铺东券金额',
|
||||
'payment' => '货款',
|
||||
'commission' => '佣金',
|
||||
'sop_amount' => 'SOP采购货款',
|
||||
'service_fee' => '交易服务费',
|
||||
'guobu_amount' => '国补采购款',
|
||||
'large_store_amount' => '大店业务采购货款',
|
||||
'promotion_service_fee' => '促销服务费',
|
||||
'ad_commission' => '广告联合活动降扣佣金',
|
||||
'link_service_fee' => '超链3.0服务费',
|
||||
'final_amount' => '应结货款',
|
||||
'remarks' => '备注',
|
||||
);
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量转换数据(列转行)
|
||||
* @param array $data 原始数据
|
||||
* @param array $title 标题行
|
||||
* @return array
|
||||
*/
|
||||
public function batchTransferData($data, $title)
|
||||
{
|
||||
if (!$this->ioTitle) {
|
||||
$this->ioTitle = $this->getTitle();
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $this->getTitle());
|
||||
}
|
||||
|
||||
$reData = [];
|
||||
foreach($data as $row) {
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
// 跳过标题行
|
||||
if($row[0] == '计费时间') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 过滤"合计"行:订单编号为空 或 包含"合计"字样
|
||||
$order_no_index = array_search('order_no', $titleKey);
|
||||
if($order_no_index !== false) {
|
||||
$order_no_value = isset($row[$order_no_index]) ? trim($row[$order_no_index]) : '';
|
||||
|
||||
// 如果订单号为空,或者整行数据中包含"合计",则跳过
|
||||
if(empty($order_no_value) || $this->containsTotal($row)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$tmpRow = [];
|
||||
foreach($row as $k => $v) {
|
||||
if(isset($titleKey[$k]) && $titleKey[$k]) {
|
||||
$tmpRow[$titleKey[$k]] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
// 将每个金额列转换为单独的一行数据(忽略金额为0的数据)
|
||||
foreach($this->column_to_row as $col) {
|
||||
// 检查金额是否存在、不为空、不为0(包括 '0'、'0.00'、0、0.0 等)
|
||||
if(isset($tmpRow[$col]) && $tmpRow[$col] !== '' && floatval($tmpRow[$col]) != 0) {
|
||||
$tmp = $tmpRow;
|
||||
$tmp['amount'] = $tmpRow[$col];
|
||||
$tmp['trade_type'] = $this->ioTitle[$col];
|
||||
$reData[] = $tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $reData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查行数据是否包含"合计"
|
||||
* @param array $row
|
||||
* @return bool
|
||||
*/
|
||||
private function containsTotal($row)
|
||||
{
|
||||
foreach($row as $cell) {
|
||||
if(strpos($cell, '合计') !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据(核心方法)
|
||||
* @param array $row 数据行
|
||||
* @param int $offset 行偏移量
|
||||
* @param array $title 标题行
|
||||
* @return array
|
||||
*/
|
||||
public function getSdf($row, $offset=1, $title)
|
||||
{
|
||||
$res = array('status'=>true, 'data'=>array(), 'msg'=>'');
|
||||
$tmp = [];
|
||||
|
||||
// 判断参数不能为空
|
||||
foreach ($row as $k => $v) {
|
||||
$tmp[$k] = trim($v, '\'');
|
||||
|
||||
// 必填字段验证:订单编号、费用类型
|
||||
if(in_array($k, array('order_no', 'trade_type')))
|
||||
{
|
||||
if(!$v)
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("%s : %s 不能为空!", isset($row['order_no']) ? $row['order_no'] : 'LINE '.$offset, $this->ioTitle[$k]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 时间格式验证
|
||||
if(in_array($k, array('billing_time', 'complete_time')))
|
||||
{
|
||||
if($v) {
|
||||
$result = finance_io_bill_verify::isDate($v);
|
||||
if ($result['status'] == 'fail')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("%s : %s 时间(%s)格式错误!", isset($row['order_no']) ? $row['order_no'] : 'LINE '.$offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 金额格式验证
|
||||
if(in_array($k, array('amount')))
|
||||
{
|
||||
if($v) {
|
||||
$result = finance_io_bill_verify::isPrice($v);
|
||||
if ($result['status'] == 'fail')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("%s : %s 金额(%s)格式错误!", isset($row['order_no']) ? $row['order_no'] : 'LINE '.$offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单编号
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
if (isset($params['order_no']) && $params['order_no']) {
|
||||
return $params['order_no'];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤数据
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function _filterData($data)
|
||||
{
|
||||
$new_data = array();
|
||||
|
||||
$new_data['order_bn'] = $this->_getOrderBn($data);
|
||||
$new_data['trade_no'] = isset($data['order_no']) ? $data['order_no'] : '';
|
||||
$new_data['financial_no'] = isset($data['order_no']) ? $data['order_no'] : '';
|
||||
$new_data['out_trade_no'] = '';
|
||||
$new_data['trade_time'] = isset($data['billing_time']) ? strtotime($data['billing_time']) : 0;
|
||||
$new_data['trade_type'] = isset($data['trade_type']) ? $data['trade_type'] : '';
|
||||
$new_data['money'] = isset($data['amount']) ? floatval($data['amount']) : 0; // 保留正负
|
||||
$new_data['member'] = '';
|
||||
|
||||
// 使用订单号+费用类型组合作为唯一标识
|
||||
$unique_str = sprintf('%s-%s',
|
||||
isset($data['order_no']) ? $data['order_no'] : '',
|
||||
isset($data['trade_type']) ? $data['trade_type'] : ''
|
||||
);
|
||||
$new_data['unique_id'] = md5($unique_str);
|
||||
|
||||
$new_data['platform_type'] = 'jdguobu';
|
||||
$new_data['remarks'] = isset($data['remarks']) ? $data['remarks'] : '';
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取账单分类
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
if (!$this->rules) {
|
||||
$this->getRules('360buy'); // 使用360buy的规则
|
||||
}
|
||||
|
||||
$this->verified_data = $params;
|
||||
|
||||
if ($this->rules) {
|
||||
foreach ($this->rules as $item) {
|
||||
foreach ($item['rule_content'] as $rule) {
|
||||
if ($this->checkRule($rule)) {
|
||||
return $item['bill_category'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
* @param string $file_name 文件名
|
||||
* @param string $file_type 文件类型
|
||||
* @return array
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
if ($file_type !== 'xlsx') {
|
||||
return array(false, '京东国补导入只支持.xlsx格式的Excel文件');
|
||||
}
|
||||
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
$row = $ioType->getData($file_name, 0, 5, 0);
|
||||
|
||||
if (empty($row) || !isset($row[0])) {
|
||||
return array(false, '文件没有数据');
|
||||
}
|
||||
|
||||
$title = array_values($this->getTitle());
|
||||
$plateTitle = $row[0];
|
||||
|
||||
// 检查是否包含所有必需的列
|
||||
foreach($title as $v) {
|
||||
if(array_search($v, $plateTitle) === false) {
|
||||
return array(false, '文件模板错误:列【'.$v.'】未包含在导入文件中');
|
||||
}
|
||||
}
|
||||
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步到对账表(finance.bill)
|
||||
* @param array $data 原始数据
|
||||
* @param string $bill_category 具体类别
|
||||
* @return bool
|
||||
*/
|
||||
public function syncToBill($data, $bill_category='')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if(!$data['content']) return false;
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
$oMonthlyReport = kernel::single('finance_monthly_report');
|
||||
|
||||
$tmp['fee_obj'] = '京东国补';
|
||||
$tmp['fee_item'] = $bill_category;
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if(!$res['status']) return false;
|
||||
|
||||
if(!$data['shop_name']){
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $this->_getOrderBn($tmp),
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => isset($tmp['billing_time']) ? strtotime($tmp['billing_time']) : 0,
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($tmp['amount'], 2), // 保留正负
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => isset($tmp['financial_no']) ? $tmp['financial_no'] : '',
|
||||
'member' => '',
|
||||
'memo' => isset($tmp['remarks']) ? $tmp['remarks'] : '',
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => isset($tmp['trade_type']) ? $tmp['trade_type'] : '',
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1, // 流水直接设置记账成功
|
||||
'charge_time' => time(),
|
||||
);
|
||||
|
||||
$base_sdf['monthly_id'] = 0;
|
||||
$base_sdf['monthly_item_id'] = 0;
|
||||
$base_sdf['monthly_status'] = 0;
|
||||
|
||||
$base_sdf['crc32_order_bn'] = sprintf('%u', crc32($base_sdf['order_bn']));
|
||||
$base_sdf['bill_bn'] = $mdlBill->gen_bill_bn();
|
||||
$base_sdf['unconfirm_money'] = $base_sdf['money'];
|
||||
|
||||
if($mdlBill->insert($base_sdf)){
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单号
|
||||
* @param array $data 数据
|
||||
* @return void
|
||||
*/
|
||||
public function updateOrderBn($data)
|
||||
{
|
||||
$this->_formatData($data);
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
|
||||
if(!$this->shop_list_by_name)
|
||||
{
|
||||
$this->shop_list_by_name = financebase_func::getShopList(financebase_func::getShopType());
|
||||
$this->shop_list_by_name = array_column($this->shop_list_by_name, null, 'name');
|
||||
}
|
||||
|
||||
foreach ($data as $v)
|
||||
{
|
||||
if('计费时间' == $v[0]) continue;
|
||||
|
||||
// 需要有店铺名称、账单号、订单号才能更新
|
||||
if(!isset($v[19]) || !isset($v[20]) || !isset($v[21])) continue;
|
||||
if(!$v[19] || !$v[20] || !$v[21]) continue;
|
||||
|
||||
$shop_id = isset($this->shop_list_by_name[$v[19]]) ? $this->shop_list_by_name[$v[19]]['shop_id'] : 0;
|
||||
if(!$shop_id) continue;
|
||||
|
||||
$filter = array('bill_bn' => $v[20], 'shop_id' => $shop_id);
|
||||
|
||||
// 找到unique_id
|
||||
$bill_info = $mdlBill->getList('unique_id,bill_id', $filter, 0, 1);
|
||||
if(!$bill_info) continue;
|
||||
$bill_info = $bill_info[0];
|
||||
|
||||
if($mdlBill->update(array('order_bn' => $v[21]), array('bill_id' => $bill_info['bill_id'])))
|
||||
{
|
||||
app::get('financebase')->model('bill')->update(array('order_bn' => $v[21]), array('unique_id' => $bill_info['unique_id'], 'shop_id' => $shop_id));
|
||||
$op_name = kernel::single('desktop_user')->get_name();
|
||||
$content = sprintf("订单号改成:%s", $v[21]);
|
||||
finance_func::addOpLog($v[20], $op_name, $content, '更新订单号');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入日期列
|
||||
* @param array|null $title
|
||||
* @return array
|
||||
*/
|
||||
public function getImportDateColunm($title=null)
|
||||
{
|
||||
$timeColumn = array('计费时间', '完成时间');
|
||||
$timeCol = array();
|
||||
|
||||
if ($title) {
|
||||
foreach ($timeColumn as $v) {
|
||||
$k = array_search($v, $title);
|
||||
if ($k !== false) {
|
||||
$timeCol[] = $k + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
$fund_sheet = $workbook['fund'];
|
||||
$fund_headers = $this->getSheetHeaders($fund_sheet);
|
||||
|
||||
$required_fund_fields = array('商户号', '日期', '商户订单号');
|
||||
$required_fund_fields = array('创建时间', '商户订单号');
|
||||
foreach ($required_fund_fields as $field) {
|
||||
if (!in_array($field, $fund_headers)) {
|
||||
return array(false, '资金表缺少必填字段:' . $field, array());
|
||||
@@ -157,7 +157,7 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
if ($sheet_name === '结算表') {
|
||||
$timeColumn = array('费用结算时间', '费用计费时间', '费用发生时间');
|
||||
} else if ($sheet_name === '资金表') {
|
||||
$timeColumn = array('日期', '账单日期');
|
||||
$timeColumn = array('创建时间');
|
||||
} else {
|
||||
$timeColumn = array();
|
||||
}
|
||||
@@ -333,16 +333,18 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
public function getFundTitle()
|
||||
{
|
||||
$title = array(
|
||||
'merchant_no' => '商户号',
|
||||
'create_time' => '创建时间',
|
||||
'account_code' => '账户代码',
|
||||
'account_name' => '账户名称',
|
||||
'date' => '日期',
|
||||
'merchant_order_no' => '商户订单号',
|
||||
'account_balance' => '账户余额(元)',
|
||||
'currency' => '币种',
|
||||
'income_amount' => '收入金额(元)',
|
||||
'expense_amount' => '支出金额(元)',
|
||||
'transaction_remark' => '交易备注',
|
||||
'bill_date' => '账单日期',
|
||||
'account_balance' => '账户余额(元)',
|
||||
'trade_type' => '交易类型',
|
||||
'out_trade_no' => '商户订单号',
|
||||
'trade_order_no' => '交易订单号',
|
||||
'original_merchant_order_no' => '原商户订单号',
|
||||
'remarks' => '资金动账备注',
|
||||
);
|
||||
|
||||
return $title;
|
||||
@@ -396,11 +398,11 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
|
||||
$res = array('status' => true, 'data' => array(), 'msg' => '');
|
||||
|
||||
if (count($row) >= 10 && $row[0] != '商户号') {
|
||||
if (count($row) >= 12 && $row[0] != '创建时间') {
|
||||
$tmp = array_combine($titleKey, $row);
|
||||
|
||||
// 转换Excel日期字段(Excel序列号转换为日期字符串)
|
||||
$timeColumn = array('date', 'bill_date');
|
||||
$timeColumn = array('create_time');
|
||||
foreach ($timeColumn as $k) {
|
||||
if (isset($tmp[$k]) && is_numeric($tmp[$k]) && $tmp[$k] > 0) {
|
||||
$timestamp = ($tmp[$k] - 25569) * 86400; // Excel基准日期是1900-01-01,Unix基准是1970-01-01
|
||||
@@ -410,7 +412,7 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
|
||||
// 判断必填字段不能为空
|
||||
foreach ($tmp as $k => $v) {
|
||||
if (in_array($k, array('merchant_no', 'date', 'merchant_order_no'))) {
|
||||
if (in_array($k, array('create_time', 'out_trade_no'))) {
|
||||
if (!$v) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, $this->ioTitle[$k]);
|
||||
@@ -419,6 +421,12 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
}
|
||||
}
|
||||
|
||||
// 计算money字段(收入金额 - 支出金额)
|
||||
$tmp['money'] = floatval($tmp['income_amount'] ?? 0) - floatval($tmp['expense_amount'] ?? 0);
|
||||
|
||||
// 设置financial_no字段
|
||||
$tmp['financial_no'] = $tmp['trade_order_no'] ?? '';
|
||||
|
||||
// 直接返回原始数据,父类process会调用_filterData
|
||||
$res['data'] = $tmp;
|
||||
}
|
||||
@@ -591,22 +599,23 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
{
|
||||
$new_data = array();
|
||||
|
||||
// 从交易备注中提取订单号
|
||||
$order_bn = $this->_extractOrderBnFromRemark($data['transaction_remark'] ?? '');
|
||||
// 从资金动账备注中提取订单号
|
||||
$order_bn = $this->_extractOrderBnFromRemark($data['remarks'] ?? '');
|
||||
|
||||
// 资金表数据转换为标准账单格式(与结算表保持一致)
|
||||
$new_data['order_bn'] = $order_bn;
|
||||
$new_data['trade_no'] = '';
|
||||
$new_data['financial_no'] = $data['merchant_no'] ?? ''; // 使用商户号作为财务流水号
|
||||
$new_data['out_trade_no'] = $data['merchant_order_no'] ?? '';
|
||||
$new_data['trade_time'] = $data['date'] ? strtotime($data['date']) : 0;
|
||||
$new_data['trade_type'] = '资金流水';
|
||||
$new_data['money'] = floatval($data['income_amount'] ?? 0) - floatval($data['expense_amount'] ?? 0);
|
||||
$new_data['financial_no'] = $data['financial_no'] ?? ''; // 使用财务流水号
|
||||
$new_data['out_trade_no'] = $data['out_trade_no'] ?? '';
|
||||
$new_data['trade_time'] = $data['create_time'] ? strtotime($data['create_time']) : 0;
|
||||
$new_data['trade_type'] = !empty($data['trade_type']) ? $data['trade_type'] : '资金流水';
|
||||
$new_data['money'] = $data['money'] ?? 0;
|
||||
$new_data['member'] = '';
|
||||
$new_data['unique_id'] = md5($data['merchant_no'] . '_' . $data['merchant_order_no'] . '_' . $data['date']);
|
||||
// $new_data['unique_id'] = md5($data['account_code'] . '_' . $data['out_trade_no'] . '_' . $data['create_time']);
|
||||
$new_data['unique_id'] = $data['financial_no'] ?? '';
|
||||
|
||||
$new_data['platform_type'] = 'jdwallet_fund';
|
||||
$new_data['remarks'] = $data['transaction_remark'] ?? '';
|
||||
$new_data['remarks'] = $data['remarks'] ?? '';
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
@@ -759,12 +768,12 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
'order_bn' => $this->_getOrderBn($tmp),
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => strtotime($tmp['date']), // 资金表使用date字段
|
||||
'trade_time' => strtotime($tmp['create_time']), // 资金表使用create_time字段
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($tmp['money'], 2), // 资金表使用money字段(已计算好的净额)
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => $tmp['financial_no'],// 使用商户号作为单据编号
|
||||
'credential_number' => $tmp['financial_no'],// 使用账户代码作为单据编号
|
||||
'member' => '',
|
||||
'memo' => $tmp['remarks'],
|
||||
'unique_id' => $data['unique_id'],
|
||||
@@ -790,4 +799,59 @@ class financebase_data_bill_jdwallet extends financebase_abstract_bill
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新订单号
|
||||
public function updateOrderBn($data)
|
||||
{
|
||||
$this->_formatData($data);
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
if(!$this->shop_list_by_name)
|
||||
{
|
||||
$this->shop_list_by_name = financebase_func::getShopList(financebase_func::getShopType());
|
||||
$this->shop_list_by_name = array_column($this->shop_list_by_name,null,'name');
|
||||
}
|
||||
|
||||
foreach ($data as $v)
|
||||
{
|
||||
if('订单编号' == $v[0]) continue;
|
||||
|
||||
if(!$v[21] || !$v[22] || !$v[23]) continue;
|
||||
|
||||
$shop_id = isset($this->shop_list_by_name[$v[21]]) ? $this->shop_list_by_name[$v[21]]['shop_id'] : 0;
|
||||
if(!$shop_id) continue;
|
||||
|
||||
$filter = array('bill_bn'=>$v[22],'shop_id'=>$shop_id);
|
||||
|
||||
|
||||
// 找到unique_id
|
||||
$bill_info = $mdlBill->getList('unique_id,bill_id',$filter,0,1);
|
||||
if(!$bill_info) continue;
|
||||
$bill_info = $bill_info[0];
|
||||
|
||||
|
||||
if($mdlBill->update(array('order_bn'=>$v[23]),array('bill_id'=>$bill_info['bill_id'])))
|
||||
{
|
||||
app::get('financebase')->model('bill')->update(array('order_bn'=>$v[23]),array('unique_id'=>$bill_info['unique_id'],'shop_id'=>$shop_id));
|
||||
$op_name = kernel::single('desktop_user')->get_name();
|
||||
$content = sprintf("订单号改成:%s",$v[23]);
|
||||
finance_func::addOpLog($v[22],$op_name,$content,'更新订单号');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function getImportDateColunm($title=null)
|
||||
{
|
||||
$timeColumn = ['费用结算时间','费用计费时间','费用发生时间'];
|
||||
$timeCol = [];
|
||||
foreach ($timeColumn as $v) {
|
||||
if($k = array_search($v, $title)) {
|
||||
$timeCol[] = $k+1;
|
||||
}
|
||||
}
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column'=>$timeCol,'time_diff'=>$timezone * 3600 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
21
app/financebase/lib/data/bill/jdwallet/fund.php
Normal file
21
app/financebase/lib/data/bill/jdwallet/fund.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* 处理京东钱包导入
|
||||
* 支持多工作表Excel文件(结算表和资金表)
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
class financebase_data_bill_jdwallet_fund extends financebase_data_bill_jdwallet
|
||||
{
|
||||
/**
|
||||
* 获取资金表标题定义(与京东日账单基本一致,但缺少结算状态字段)
|
||||
* @return array
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return parent::getFundTitle();
|
||||
}
|
||||
|
||||
}
|
||||
322
app/financebase/lib/data/bill/miaosuda.php
Normal file
322
app/financebase/lib/data/bill/miaosuda.php
Normal file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
/**
|
||||
* 处理喵速达账单导入
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @version 1.0
|
||||
*/
|
||||
class financebase_data_bill_miaosuda extends financebase_abstract_bill
|
||||
{
|
||||
public $order_bn_prefix = '';
|
||||
public $column_num = 34; // 喵速达账单有34列
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
public $verified_data = array();
|
||||
|
||||
/**
|
||||
* 处理数据
|
||||
*/
|
||||
public function getSdf($row, $offset = 1, $title)
|
||||
{
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
if (!$this->ioTitle) {
|
||||
$this->ioTitle = $this->getTitle();
|
||||
$this->ioTitleKey = array_keys($this->ioTitle);
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $this->getTitle());
|
||||
|
||||
if ($titleKey[$k] === false) {
|
||||
return array('status' => false, 'msg' => '未定义字段`' . $t . '`');
|
||||
}
|
||||
}
|
||||
|
||||
$res = array('status' => true, 'data' => array(), 'msg' => '');
|
||||
|
||||
if ($this->column_num <= count($row) && $row[0] != '对账单编码') {
|
||||
|
||||
$tmp = array_combine($titleKey, $row);
|
||||
|
||||
// 验证必填字段
|
||||
foreach ($tmp as $k => $v) {
|
||||
// 必填字段验证(核心字段)
|
||||
if (in_array($k, array('bill_code', 'main_order_no', 'business_time', 'amount'))) {
|
||||
if (!$v && $v !== '0' && $v !== 0) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, $this->ioTitle[$k]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 时间格式验证
|
||||
if (in_array($k, array('bill_create_time', 'business_time', 'trade_pay_time'))) {
|
||||
if ($v && trim($v) !== '') {
|
||||
$result = finance_io_bill_verify::isDate($v);
|
||||
if ($result['status'] == 'fail' || strtotime($v) <= 0) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 时间格式错误!取值是:%s", $offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 金额格式验证(喵速达支持多位小数,如未税金额可能有6位小数)
|
||||
if (in_array($k, array('amount', 'amount_without_tax', 'tax_amount', 'unit_price_with_tax'))) {
|
||||
if ($v && trim($v) !== '') {
|
||||
// 自定义金额验证:支持多位小数的正负数
|
||||
if (!preg_match('/^-?\d+(\.\d+)?$/', $v)) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 金额格式错误!取值是:%s", $offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理订单号(去除Excel的="xxx"格式)
|
||||
if (in_array($k, array('bill_code', 'main_order_no', 'sub_order_no', 'purchase_order_no', 'financial_no', 'order_no'))) {
|
||||
$tmp[$k] = trim($v, '=\"');
|
||||
}
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段定义
|
||||
*
|
||||
* 根据喵速达Excel模板的实际列名定义(共34列)
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
$title = array(
|
||||
'bill_code' => '对账单编码', // S2025102032246311035
|
||||
'bill_create_time' => '账单创建时间', // 2025-10-20 14:00:17
|
||||
'main_order_no' => '业务主单据编码', // PO036125100821303611874066166
|
||||
'sub_order_no' => '业务子单据编码', // IO25100821303611874066166252507
|
||||
'business_time' => '业务时间', // 2025-10-08 21:30:36
|
||||
'source_doc_type' => '来源单据类型', // 采购入库
|
||||
'fee_code' => '费用项编码', // HM_PAYMENT_GOODS
|
||||
'trade_type' => '结算方式', // 货款
|
||||
'supplier_code' => '供应商编码', // 488675267
|
||||
'supplier_name' => '供应商名称', // 美诺电器有限公司冰洗厨热商家仓配
|
||||
'currency' => '结算币种', // CNY
|
||||
'amount' => '含税金额', // 11770.56 (主要金额字段)
|
||||
'amount_without_tax' => '未税金额', // 10416.424779
|
||||
'tax_amount' => '税额', // 1354.135221
|
||||
'tax_rate' => '税率', // 0.13
|
||||
'goods_code' => '货品编码', // 898392380713
|
||||
'goods_name' => '货品名称', // TCH797WP C 莲花白
|
||||
'billing_quantity' => '计费数量', // 1.000000
|
||||
'unit_price_with_tax' => '含税单价', // 11770.560000
|
||||
'is_recalculate' => '是否重算', // 计算数据
|
||||
'financial_no' => '唯一编码', // KLZYS202510086465904920660
|
||||
'purchase_order_no' => '采购单编码', // PO036125100821303611874066166
|
||||
'settlement_mode' => '结算模式', // PURCHASE
|
||||
'industry_name' => '行业名称', // 数码家电
|
||||
'order_no' => '二段LP单号', // LP00738139484471
|
||||
'trade_sub_order_no' => '交易子单编码', // 2591505374260069772
|
||||
'trade_main_order_no' => '交易主单编码', // 2591505374260069772
|
||||
'refund_quantity' => '原子货品退款数量', // 空
|
||||
'refund_amount' => '原子货品消费者退款金额', // 空
|
||||
'goods_unit' => '货品单位', // 空
|
||||
'trade_pay_time' => '交易支付时间', // 空
|
||||
'refund_order_no' => '退款单号', // 空
|
||||
'sales_quantity' => '销售数量(退款数量)', // 1.000000
|
||||
'billing_formula' => '计费公式', // 长文本
|
||||
);
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单号
|
||||
*/
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
// 直接使用二段LP单号
|
||||
if (isset($params['order_no']) && $params['order_no']) {
|
||||
return $params['order_no'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取具体类别
|
||||
*/
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
if (!$this->rules) {
|
||||
$this->getRules('miaosuda');
|
||||
}
|
||||
|
||||
$this->verified_data = $params;
|
||||
|
||||
if ($this->rules) {
|
||||
foreach ($this->rules as $item) {
|
||||
foreach ($item['rule_content'] as $rule) {
|
||||
if ($this->checkRule($rule)) {
|
||||
return $item['bill_category'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
$row = $ioType->getData($file_name, 0, 3);
|
||||
|
||||
// 检查第一行是否包含"对账单编码"
|
||||
if (!isset($row[0][0]) || $row[0][0] != '对账单编码') {
|
||||
return array(false, '文件模板错误:第一列应该是"对账单编码"');
|
||||
}
|
||||
|
||||
$title = array_values($this->getTitle());
|
||||
sort($title);
|
||||
|
||||
$fileTitle = $row[0];
|
||||
sort($fileTitle);
|
||||
|
||||
if (!array_diff($fileTitle, $title)) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
return array(false, '文件模板错误:列名不匹配');
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步到对账表
|
||||
*/
|
||||
public function syncToBill($data, $bill_category = '')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if (!$data['content']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
|
||||
$tmp['fee_obj'] = '喵速达';
|
||||
$tmp['fee_item'] = $bill_category;
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if (!$res['status']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$data['shop_name']) {
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
// 使用含税金额作为主要金额(保留正负,负数表示支出/退款)
|
||||
$amount = isset($tmp['amount']) ? floatval($tmp['amount']) : 0;
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $this->_getOrderBn($tmp),
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => strtotime($tmp['business_time']), // 使用业务时间
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($amount, 2), // 保留正负
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => isset($tmp['financial_no']) ? $tmp['financial_no'] : '', // 使用唯一编码(财务流水号)
|
||||
'member' => isset($tmp['supplier_name']) ? $tmp['supplier_name'] : '',
|
||||
'memo' => isset($tmp['source_doc_type']) ? $tmp['source_doc_type'] : '', // 来源单据类型
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => isset($tmp['trade_type']) ? $tmp['trade_type'] : '', // 结算方式
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1,
|
||||
'charge_time' => time(),
|
||||
);
|
||||
|
||||
$base_sdf['monthly_id'] = 0;
|
||||
$base_sdf['monthly_item_id'] = 0;
|
||||
$base_sdf['monthly_status'] = 0;
|
||||
|
||||
$base_sdf['crc32_order_bn'] = sprintf('%u', crc32($base_sdf['order_bn']));
|
||||
$base_sdf['bill_bn'] = $mdlBill->gen_bill_bn();
|
||||
$base_sdf['unconfirm_money'] = $base_sdf['money'];
|
||||
|
||||
if ($mdlBill->insert($base_sdf)) {
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取关键字段
|
||||
*/
|
||||
public function _filterData($data)
|
||||
{
|
||||
$new_data = array();
|
||||
|
||||
$new_data['order_bn'] = $this->_getOrderBn($data);
|
||||
$new_data['trade_no'] = isset($data['main_order_no']) ? $data['main_order_no'] : ''; // 业务主单据编码
|
||||
$new_data['financial_no'] = isset($data['financial_no']) ? $data['financial_no'] : ''; // 唯一编码
|
||||
$new_data['out_trade_no'] = isset($data['order_no']) ? $data['order_no'] : ''; // 二段LP单号
|
||||
$new_data['trade_time'] = isset($data['business_time']) ? strtotime($data['business_time']) : 0;
|
||||
$new_data['trade_type'] = isset($data['trade_type']) ? $data['trade_type'] : ''; // 结算方式
|
||||
$new_data['money'] = isset($data['amount']) ? floatval($data['amount']) : 0; // 含税金额(保留正负)
|
||||
$new_data['member'] = isset($data['supplier_name']) ? $data['supplier_name'] : '';
|
||||
|
||||
// 直接使用唯一编码作为唯一标识
|
||||
$new_data['unique_id'] = isset($data['financial_no']) ? $data['financial_no'] : '';
|
||||
|
||||
$new_data['platform_type'] = 'miaosuda';
|
||||
$new_data['remarks'] = isset($data['source_doc_type']) ? $data['source_doc_type'] : ''; // 来源单据类型
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入日期列
|
||||
*/
|
||||
public function getImportDateColunm($title = null)
|
||||
{
|
||||
// 找到时间列的位置
|
||||
$timeColumn = array('账单创建时间', '业务时间', '交易支付时间');
|
||||
$timeCol = array();
|
||||
|
||||
if ($title) {
|
||||
foreach ($timeColumn as $v) {
|
||||
$k = array_search($v, $title);
|
||||
if ($k !== false) {
|
||||
$timeCol[] = $k + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量转换数据(可选,用于特殊数据处理)
|
||||
*/
|
||||
public function batchTransferData($data, $title) {
|
||||
// 如果需要对整批数据进行预处理,可以在这里实现
|
||||
// 例如:处理金额格式、清理特殊字符等
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
460
app/financebase/lib/data/bill/tmyp.php
Normal file
460
app/financebase/lib/data/bill/tmyp.php
Normal file
@@ -0,0 +1,460 @@
|
||||
<?php
|
||||
/**
|
||||
* 天猫优品账单导入处理类
|
||||
* 处理第一个工作表
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
class financebase_data_bill_tmyp extends financebase_abstract_bill
|
||||
{
|
||||
public $order_bn_prefix = '';
|
||||
public $column_num = 33; // 33个字段(新增优品红包字段)
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
public $verified_data = array();
|
||||
public $shop_list_by_name = array(); // 店铺列表(按名称索引)
|
||||
|
||||
// 需要转换为行的金额列(列转行)
|
||||
public $column_to_row = [
|
||||
'amount', // 含税金额
|
||||
'yp_red_packet', // 优品红包
|
||||
];
|
||||
|
||||
// 指定要读取的工作表名称(已注释:现在只读取第一个工作表)
|
||||
// public $sheet_name = '账单明细-寄售';
|
||||
|
||||
/**
|
||||
* 获取标题映射
|
||||
* @return array
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
$title = array(
|
||||
'bill_no' => '对账单号',
|
||||
'settlement_company' => '结算公司主体',
|
||||
'bill_create_time' => '账单生成时间',
|
||||
'order_no' => '交易主单',
|
||||
'trade_sub_order' => '交易子单',
|
||||
'business_main_no' => '业务主单据编码',
|
||||
'business_sub_no' => '业务子单据编码',
|
||||
'pay_time' => '支付时间',
|
||||
'business_time' => '业务时间',
|
||||
'business_doc_type' => '业务单据类型',
|
||||
'fee_type' => '费用类型',
|
||||
'business_attr' => '经营属性',
|
||||
'trade_type' => '结算方式',
|
||||
'supplier_code' => '供应商编码',
|
||||
'supplier_name' => '供应商名称',
|
||||
'currency' => '结算币种',
|
||||
'amount' => '含税金额',
|
||||
'amount_without_tax' => '未税金额',
|
||||
'tax_amount' => '税额',
|
||||
'tax_rate' => '税率',
|
||||
'goods_code' => '后端商品编码',
|
||||
'goods_name' => '后端商品名称',
|
||||
'unit' => '存储单位',
|
||||
'quantity' => '商品数量',
|
||||
'price_with_tax' => '含税单价',
|
||||
'price_without_tax' => '未税单价',
|
||||
'is_recalculate' => '是否重算',
|
||||
'reference' => '参考',
|
||||
'financial_no' => '唯一ID',
|
||||
'settlement_no' => '结算流水编号',
|
||||
'diff_type' => '差异判责类型',
|
||||
'bill_category' => '账单分类',
|
||||
'yp_red_packet' => '优品红包',
|
||||
);
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量转换数据(列转行)
|
||||
* 将含税金额和优品红包转换为两行数据
|
||||
* @param array $data 原始数据
|
||||
* @param array $title 标题行
|
||||
* @return array
|
||||
*/
|
||||
public function batchTransferData($data, $title)
|
||||
{
|
||||
if (!$this->ioTitle) {
|
||||
$this->ioTitle = $this->getTitle();
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $this->getTitle());
|
||||
}
|
||||
|
||||
$reData = [];
|
||||
foreach($data as $row) {
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
// 跳过标题行
|
||||
if($row[0] == '对账单号') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 过滤"票扣"数据:如果结算方式是"票扣",则忽略此行数据
|
||||
$trade_type_index = array_search('trade_type', $titleKey);
|
||||
if($trade_type_index !== false) {
|
||||
$trade_type_value = isset($row[$trade_type_index]) ? trim($row[$trade_type_index]) : '';
|
||||
if($trade_type_value == '票扣') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$tmpRow = [];
|
||||
foreach($row as $k => $v) {
|
||||
if(isset($titleKey[$k]) && $titleKey[$k]) {
|
||||
$tmpRow[$titleKey[$k]] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
// 将含税金额和优品红包转换为单独的行数据
|
||||
foreach($this->column_to_row as $col) {
|
||||
// 检查金额是否存在、不为空、不为0(包括 '0'、'0.00'、0、0.0 等)
|
||||
if(isset($tmpRow[$col]) && $tmpRow[$col] !== '' && floatval($tmpRow[$col]) != 0) {
|
||||
$tmp = $tmpRow;
|
||||
$tmp['amount'] = $tmpRow[$col];
|
||||
|
||||
// 设置 trade_type
|
||||
if($col == 'yp_red_packet') {
|
||||
// 优品红包的 trade_type 就是"优品红包"
|
||||
$tmp['trade_type'] = '优品红包';
|
||||
// 优品红包需要重新生成 financial_no,在原值基础上加 "-1"
|
||||
if(isset($tmpRow['financial_no']) && $tmpRow['financial_no']) {
|
||||
$tmp['financial_no'] = $tmpRow['financial_no'] . '-1';
|
||||
}
|
||||
} else {
|
||||
// 含税金额的 trade_type 保持原来的结算方式
|
||||
$tmp['trade_type'] = isset($tmpRow['trade_type']) ? $tmpRow['trade_type'] : '';
|
||||
}
|
||||
|
||||
$reData[] = $tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $reData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据(核心方法)
|
||||
* @param array $row 数据行(batchTransferData 返回的关联数组)
|
||||
* @param int $offset 行偏移量
|
||||
* @param array $title 标题行
|
||||
* @return array
|
||||
*/
|
||||
public function getSdf($row, $offset=1, $title)
|
||||
{
|
||||
if(!$this->ioTitle){
|
||||
$this->ioTitle = $this->getTitle();
|
||||
$this->ioTitleKey = array_keys($this->ioTitle);
|
||||
}
|
||||
|
||||
$res = array('status'=>true, 'data'=>array(), 'msg'=>'');
|
||||
|
||||
// batchTransferData 返回的是关联数组,直接处理
|
||||
$tmp = array();
|
||||
foreach($row as $k => $v) {
|
||||
$tmp[$k] = trim($v, '\'');
|
||||
}
|
||||
|
||||
// 过滤"票扣"数据:如果结算方式是"票扣",则忽略此行数据
|
||||
if(isset($tmp['trade_type']) && $tmp['trade_type'] == '票扣') {
|
||||
// 返回成功状态但不处理数据(data为空)
|
||||
return array('status' => true, 'data' => array(), 'msg' => '');
|
||||
}
|
||||
|
||||
// 验证必填字段
|
||||
foreach ($tmp as $k => $v) {
|
||||
// 必填字段:交易主单、结算方式、金额
|
||||
if(in_array($k, array('order_no', 'trade_type', 'amount')))
|
||||
{
|
||||
if(!$v)
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, isset($this->ioTitle[$k]) ? $this->ioTitle[$k] : $k);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 时间格式验证
|
||||
if(in_array($k, array('bill_create_time', 'pay_time', 'business_time')))
|
||||
{
|
||||
if($v && $v != '--') {
|
||||
$result = finance_io_bill_verify::isDate($v);
|
||||
if ($result['status'] == 'fail')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 时间(%s)格式错误!", $offset, isset($this->ioTitle[$k]) ? $this->ioTitle[$k] : $k, $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 金额格式验证(天猫优品支持多位小数,如含税金额可能有6位小数)
|
||||
// 包含优品红包字段
|
||||
if(in_array($k, array('amount', 'amount_without_tax', 'tax_amount', 'price_with_tax', 'price_without_tax', 'yp_red_packet')))
|
||||
{
|
||||
if($v) {
|
||||
// 自定义金额验证:支持多位小数的正负数
|
||||
if (!preg_match('/^-?\d+(\.\d+)?$/', $v)) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 金额(%s)格式错误!", $offset, isset($this->ioTitle[$k]) ? $this->ioTitle[$k] : $k, $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 特殊字段处理:去除Excel导出的 ="" 包裹
|
||||
if(in_array($k, array('order_no', 'business_main_no', 'business_sub_no', 'financial_no', 'settlement_no', 'goods_code'))){
|
||||
$tmp[$k] = trim($v, '=\"');
|
||||
}
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单编号
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
// 直接返回交易主单(order_no)
|
||||
if (isset($params['order_no']) && $params['order_no']) {
|
||||
return $params['order_no'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤数据
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function _filterData($data)
|
||||
{
|
||||
$new_data = array();
|
||||
$new_data['order_bn'] = $this->_getOrderBn($data);
|
||||
$new_data['trade_no'] = isset($data['order_no']) ? $data['order_no'] : ''; // 交易主单
|
||||
$new_data['financial_no'] = isset($data['financial_no']) ? $data['financial_no'] : ''; // 唯一ID
|
||||
$new_data['out_trade_no'] = isset($data['business_main_no']) ? $data['business_main_no'] : ''; // 业务主单据编码
|
||||
$new_data['trade_time'] = isset($data['business_time']) ? strtotime($data['business_time']) : 0;
|
||||
$new_data['trade_type'] = isset($data['trade_type']) ? $data['trade_type'] : ''; // 结算方式
|
||||
$new_data['money'] = isset($data['amount']) ? floatval($data['amount']) : 0; // 含税金额(保留正负)
|
||||
$new_data['member'] = ''; // 会员信息为空
|
||||
|
||||
// 使用唯一ID作为唯一标识
|
||||
$new_data['unique_id'] = isset($data['financial_no']) ? $data['financial_no'] : '';
|
||||
$new_data['platform_type'] = 'tmyp';
|
||||
$new_data['remarks'] = isset($data['business_doc_type']) ? $data['business_doc_type'] : ''; // 业务单据类型
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取账单分类
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
if (!$this->rules) {
|
||||
$this->getRules('alipay'); // 使用alipay的规则
|
||||
}
|
||||
|
||||
$this->verified_data = $params;
|
||||
|
||||
if ($this->rules) {
|
||||
foreach ($this->rules as $item) {
|
||||
foreach ($item['rule_content'] as $rule) {
|
||||
if ($this->checkRule($rule)) {
|
||||
return $item['bill_category'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步到对账表(finance.bill)
|
||||
* @param array $data 原始数据
|
||||
* @param string $bill_category 具体类别
|
||||
* @return bool
|
||||
*/
|
||||
public function syncToBill($data, $bill_category='')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if(!$data['content']) return false;
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
$oMonthlyReport = kernel::single('finance_monthly_report');
|
||||
|
||||
$tmp['fee_obj'] = '天猫优品';
|
||||
$tmp['fee_item'] = $bill_category;
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if(!$res['status']) return false;
|
||||
|
||||
if(!$data['shop_name']){
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $this->_getOrderBn($tmp),
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => isset($tmp['business_time']) ? strtotime($tmp['business_time']) : 0,
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($tmp['amount'], 2), // 保留正负
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => isset($tmp['financial_no']) ? $tmp['financial_no'] : '', // 唯一ID
|
||||
'member' => '', // 会员信息为空
|
||||
'memo' => isset($tmp['remarks']) ? $tmp['remarks'] : '',
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => isset($tmp['trade_type']) ? $tmp['trade_type'] : '',
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1, // 流水直接设置记账成功
|
||||
'charge_time' => time(),
|
||||
);
|
||||
|
||||
$base_sdf['monthly_id'] = 0;
|
||||
$base_sdf['monthly_item_id'] = 0;
|
||||
$base_sdf['monthly_status'] = 0;
|
||||
|
||||
$base_sdf['crc32_order_bn'] = sprintf('%u', crc32($base_sdf['order_bn']));
|
||||
$base_sdf['bill_bn'] = $mdlBill->gen_bill_bn();
|
||||
$base_sdf['unconfirm_money'] = $base_sdf['money'];
|
||||
|
||||
if($mdlBill->insert($base_sdf)){
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入日期列
|
||||
* @param array|null $title
|
||||
* @return array
|
||||
*/
|
||||
public function getImportDateColunm($title = null)
|
||||
{
|
||||
// 找到时间列的位置
|
||||
$timeColumn = array('账单生成时间', '支付时间', '业务时间');
|
||||
$timeCol = array();
|
||||
if ($title) {
|
||||
foreach ($timeColumn as $v) {
|
||||
$k = array_search($v, $title);
|
||||
if ($k !== false) {
|
||||
$timeCol[] = $k + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单号
|
||||
* @param array $data 数据
|
||||
* @return void
|
||||
*/
|
||||
public function updateOrderBn($data)
|
||||
{
|
||||
$this->_formatData($data);
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
|
||||
if(!$this->shop_list_by_name)
|
||||
{
|
||||
$this->shop_list_by_name = financebase_func::getShopList(financebase_func::getShopType());
|
||||
$this->shop_list_by_name = array_column($this->shop_list_by_name, null, 'name');
|
||||
}
|
||||
|
||||
foreach ($data as $v)
|
||||
{
|
||||
// 跳过标题行
|
||||
if('对账单号' == $v[0]) continue;
|
||||
|
||||
// 需要有店铺名称、账单号、订单号才能更新
|
||||
// 假设最后3列是:店铺名称、账单号、订单号(需要根据实际情况调整)
|
||||
// 注意:由于新增了优品红包字段,列索引需要相应调整
|
||||
if(!isset($v[33]) || !isset($v[34]) || !isset($v[35])) continue;
|
||||
if(!$v[33] || !$v[34] || !$v[35]) continue;
|
||||
|
||||
$shop_id = isset($this->shop_list_by_name[$v[33]]) ? $this->shop_list_by_name[$v[33]]['shop_id'] : 0;
|
||||
if(!$shop_id) continue;
|
||||
|
||||
$filter = array('bill_bn' => $v[34], 'shop_id' => $shop_id);
|
||||
|
||||
// 找到unique_id
|
||||
$bill_info = $mdlBill->getList('unique_id,bill_id', $filter, 0, 1);
|
||||
if(!$bill_info) continue;
|
||||
$bill_info = $bill_info[0];
|
||||
|
||||
if($mdlBill->update(array('order_bn' => $v[35]), array('bill_id' => $bill_info['bill_id'])))
|
||||
{
|
||||
app::get('financebase')->model('bill')->update(array('order_bn' => $v[35]), array('unique_id' => $bill_info['unique_id'], 'shop_id' => $shop_id));
|
||||
$op_name = kernel::single('desktop_user')->get_name();
|
||||
$content = sprintf("订单号改成:%s", $v[35]);
|
||||
finance_func::addOpLog($v[34], $op_name, $content, '更新订单号');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
* @param string $file_name 文件名
|
||||
* @param string $file_type 文件类型
|
||||
* @return array
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
if ($file_type !== 'xlsx') {
|
||||
return array(false, '天猫优品导入只支持.xlsx格式的Excel文件');
|
||||
}
|
||||
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
|
||||
// 读取第一个工作表(不再限制特定工作表名称)
|
||||
$row = $ioType->getData($file_name, 0, 1, 0);
|
||||
|
||||
if (empty($row) || !isset($row[0])) {
|
||||
return array(false, '文件没有数据');
|
||||
}
|
||||
|
||||
// 完整验证所有列名
|
||||
$title = array_values($this->getTitle());
|
||||
sort($title);
|
||||
|
||||
$tmypTitle = $row[0];
|
||||
sort($tmypTitle);
|
||||
|
||||
// 完全匹配
|
||||
if ($title == $tmypTitle) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
// 包含关系匹配
|
||||
if (!array_diff($tmypTitle, $title)) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
return array(false, '文件模板错误:' . var_export($row[0], true) . ',正确的为:' . var_export($title, 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
512
app/financebase/lib/data/bill/weimobr.php
Normal file
512
app/financebase/lib/data/bill/weimobr.php
Normal file
@@ -0,0 +1,512 @@
|
||||
<?php
|
||||
/**
|
||||
* 微盟零售账单导入处理类
|
||||
* 支持正向(销售)和逆向(退款)两种模板
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
class financebase_data_bill_weimobr extends financebase_abstract_bill
|
||||
{
|
||||
public $order_bn_prefix = '';
|
||||
public $column_num = 0; // 动态字段数
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
public $verified_data = array();
|
||||
public $shop_list_by_name = array(); // 店铺列表(按名称索引)
|
||||
|
||||
// 标记当前处理的是正向还是逆向
|
||||
private $is_forward = null;
|
||||
|
||||
// 正向表头(销售)
|
||||
private $title_forward = null;
|
||||
|
||||
// 逆向表头(退款)
|
||||
private $title_reverse = null;
|
||||
|
||||
/**
|
||||
* 获取正向表头(销售)
|
||||
* @return array
|
||||
*/
|
||||
private function getTitleForward()
|
||||
{
|
||||
if ($this->title_forward === null) {
|
||||
$this->title_forward = array(
|
||||
'trade_time' => '交易时间',
|
||||
'amount' => '交易金额',
|
||||
'settlement_amount' => '应结订单金额',
|
||||
'fee_amount' => '手续费金额',
|
||||
'income_amount' => '入账金额',
|
||||
'wechat_coupon' => '微信代金券金额',
|
||||
'unionpay_coupon' => '云闪付优惠券金额',
|
||||
'alipay_coupon' => '支付宝代金券商家优惠金额',
|
||||
'alipay_amount' => '支付宝实收金额',
|
||||
'reconciliation_status' => '对账状态',
|
||||
'bill_date' => '账单日期',
|
||||
'trade_type' => '交易类型',
|
||||
'split_status' => '分账状态',
|
||||
'unfreeze_time' => '解冻时间',
|
||||
'settlement_status' => '结算状态',
|
||||
'settlement_time' => '结算时间',
|
||||
'shop_name' => '店铺名称',
|
||||
'org_id' => '组织ID',
|
||||
'parent_order_no' => '父单号',
|
||||
'order_no' => '订单编号',
|
||||
'trade_no' => '交易单号',
|
||||
'channel_trade_no' => '通道交互单号',
|
||||
'refund_amount' => '退款金额',
|
||||
'fee_return' => '手续费返还',
|
||||
'pay_mode' => '支付模式',
|
||||
'merchant_no' => '支付商户号',
|
||||
'currency' => '币种',
|
||||
'business_type' => '业务类型',
|
||||
'channel_type' => '渠道类型',
|
||||
'remark1' => '备注1',
|
||||
'payer_info' => '付款人信息',
|
||||
);
|
||||
}
|
||||
return $this->title_forward;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取逆向表头(退款)
|
||||
* @return array
|
||||
*/
|
||||
private function getTitleReverse()
|
||||
{
|
||||
if ($this->title_reverse === null) {
|
||||
$this->title_reverse = array(
|
||||
'refund_time' => '退款时间',
|
||||
'amount' => '退款金额',
|
||||
'actual_refund' => '实退金额',
|
||||
'fee_return' => '手续费返还',
|
||||
'wechat_coupon_refund' => '微信代金券金额退款',
|
||||
'unionpay_coupon_refund' => '云闪付优惠券退款金额',
|
||||
'refund_status' => '退款状态',
|
||||
'remark' => '备注',
|
||||
'reconciliation_status' => '对账状态',
|
||||
'bill_date' => '账单日期',
|
||||
'shop_name' => '店铺名称',
|
||||
'org_id' => '组织ID',
|
||||
'dispute_no' => '维权单号',
|
||||
'channel_refund_no' => '通道退款单号',
|
||||
'channel_trade_no' => '通道交互单号',
|
||||
'original_trade_time' => '原交易时间',
|
||||
'original_trade_amount' => '原交易金额',
|
||||
'original_unfreeze_time' => '原交易解冻时间',
|
||||
'original_parent_order' => '原父单号',
|
||||
'order_no' => '原订单编号', // 统一使用 order_no,Excel表头是"原订单编号"
|
||||
'original_trade_no' => '原交易单号',
|
||||
'pay_mode' => '支付模式',
|
||||
'merchant_no' => '支付商户号',
|
||||
'currency' => '币种',
|
||||
'business_type' => '业务类型',
|
||||
'channel_type' => '渠道类型',
|
||||
);
|
||||
}
|
||||
return $this->title_reverse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标题映射(支持正向和逆向两种表头)
|
||||
* @return array
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
// 合并正向和逆向表头,支持两种模板
|
||||
return array_merge($this->getTitleForward(), $this->getTitleReverse());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据(核心方法)
|
||||
* @param array $row 数据行
|
||||
* @param int $offset 行偏移量
|
||||
* @param array $title 标题行
|
||||
* @return array
|
||||
*/
|
||||
public function getSdf($row, $offset=1, $title)
|
||||
{
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
// 判断是正向还是逆向(根据表头第一个字段)
|
||||
if ($this->is_forward === null && !empty($title)) {
|
||||
$first_title = trim($title[0]);
|
||||
if ($first_title == '退款时间') {
|
||||
$this->is_forward = false; // 逆向(退款)
|
||||
} else {
|
||||
$this->is_forward = true; // 正向(销售)
|
||||
}
|
||||
}
|
||||
|
||||
// 根据正向/逆向获取对应的表头
|
||||
if ($this->is_forward) {
|
||||
$current_title = $this->getTitleForward();
|
||||
} else {
|
||||
$current_title = $this->getTitleReverse();
|
||||
}
|
||||
|
||||
if(!$this->ioTitle){
|
||||
$this->ioTitle = $current_title;
|
||||
$this->ioTitleKey = array_keys($this->ioTitle);
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $current_title);
|
||||
|
||||
if ($titleKey[$k] === false) {
|
||||
return array('status' => false, 'msg' => '未定义字段`' . $t . '`');
|
||||
}
|
||||
}
|
||||
|
||||
$res = array('status'=>true, 'data'=>array(), 'msg'=>'');
|
||||
|
||||
// 正向:跳过表头行(交易时间)
|
||||
// 逆向:跳过表头行(退款时间)
|
||||
$first_field = $this->is_forward ? '交易时间' : '退款时间';
|
||||
if(count($row) > 0 && $row[0] != $first_field)
|
||||
{
|
||||
$tmp = array_combine($titleKey, $row);
|
||||
|
||||
// 验证必填字段
|
||||
// 正向必填:交易时间、交易金额、订单编号
|
||||
// 逆向必填:退款时间、退款金额、订单编号(原订单编号)
|
||||
if($this->is_forward) {
|
||||
$required_fields = array('trade_time', 'amount', 'order_no');
|
||||
} else {
|
||||
$required_fields = array('refund_time', 'amount', 'order_no');
|
||||
}
|
||||
|
||||
foreach ($tmp as $k => $v) {
|
||||
// 只验证必填字段
|
||||
if(in_array($k, $required_fields))
|
||||
{
|
||||
if(!$v || $v == '--')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, $this->ioTitle[$k]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
// 必填字段的格式验证
|
||||
// 时间字段格式验证
|
||||
if(in_array($k, array('trade_time', 'refund_time')))
|
||||
{
|
||||
$result = finance_io_bill_verify::isDate($v);
|
||||
if ($result['status'] == 'fail')
|
||||
{
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 时间(%s)格式错误!", $offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 金额字段格式验证
|
||||
if($k == 'amount')
|
||||
{
|
||||
// 自定义金额验证:支持多位小数的正负数
|
||||
if (!preg_match('/^-?\d+(\.\d+)?$/', $v)) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 金额(%s)格式错误!", $offset, $this->ioTitle[$k], $v);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 特殊字段处理:去除Excel导出的 ="" 包裹
|
||||
if(in_array($k, array('order_no', 'trade_no', 'channel_trade_no', 'original_trade_no', 'parent_order_no', 'original_parent_order'))){
|
||||
$tmp[$k] = trim($v, '=\"');
|
||||
}
|
||||
}
|
||||
|
||||
// 标记数据类型(正向或逆向)
|
||||
$tmp['_is_forward'] = $this->is_forward;
|
||||
|
||||
// 处理 trade_type:正向为"交易金额",逆向为"退款金额"
|
||||
if ($this->is_forward) {
|
||||
$tmp['trade_type'] = '交易金额';
|
||||
} else {
|
||||
$tmp['trade_type'] = '退款金额';
|
||||
}
|
||||
|
||||
// 处理 amount:如果是逆向,转为负数
|
||||
if (isset($tmp['amount']) && !$this->is_forward) {
|
||||
$tmp['amount'] = -abs(floatval($tmp['amount'])); // 逆向金额转为负数
|
||||
} elseif (isset($tmp['amount'])) {
|
||||
$tmp['amount'] = floatval($tmp['amount']); // 正向金额保持正数
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单编号
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
// 正向和逆向都使用 order_no
|
||||
if (isset($params['order_no']) && $params['order_no']) {
|
||||
return $params['order_no'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤数据
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function _filterData($data)
|
||||
{
|
||||
$order_bn = $this->_getOrderBn($data);
|
||||
|
||||
$is_forward = isset($data['_is_forward']) ? $data['_is_forward'] : true;
|
||||
|
||||
// 正逆向共用的字段
|
||||
$new_data = array(
|
||||
'order_bn' => $order_bn,
|
||||
'trade_no' => $order_bn, // trade_no 都使用订单号
|
||||
'financial_no' => isset($data['channel_trade_no']) ? $data['channel_trade_no'] : '', // financial_no 都使用 channel_trade_no
|
||||
'member' => '', // member 都为空
|
||||
'remarks' => '', // remarks 都为空
|
||||
'trade_type' => isset($data['trade_type']) ? $data['trade_type'] : '', // trade_type 已经在 getSdf 中处理
|
||||
'money' => isset($data['amount']) ? floatval($data['amount']) : 0, // amount 已经在 getSdf 中处理(逆向已转为负数)
|
||||
);
|
||||
|
||||
// 正逆向不同的字段
|
||||
if ($is_forward) {
|
||||
// 正向(销售)
|
||||
$new_data['out_trade_no'] = isset($data['trade_no']) ? $data['trade_no'] : '';
|
||||
$new_data['trade_time'] = isset($data['trade_time']) ? strtotime($data['trade_time']) : 0;
|
||||
} else {
|
||||
// 逆向(退款)
|
||||
$new_data['out_trade_no'] = isset($data['original_trade_no']) ? $data['original_trade_no'] : '';
|
||||
$new_data['trade_time'] = isset($data['refund_time']) ? strtotime($data['refund_time']) : 0;
|
||||
}
|
||||
|
||||
// 生成唯一ID:使用 trade_no + financial_no + trade_time + money 的 MD5
|
||||
$unique_str = sprintf(
|
||||
'%s_%s_%s_%s',
|
||||
$new_data['trade_no'],
|
||||
$new_data['financial_no'],
|
||||
$new_data['trade_time'],
|
||||
$new_data['money']
|
||||
);
|
||||
$new_data['unique_id'] = md5($unique_str);
|
||||
$new_data['platform_type'] = 'weimobr';
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取账单分类
|
||||
* @param array $params
|
||||
* @return string
|
||||
*/
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
if (!$this->rules) {
|
||||
$this->getRules('weimobr'); // 使用微信支付的规则
|
||||
}
|
||||
|
||||
$this->verified_data = $params;
|
||||
|
||||
if ($this->rules) {
|
||||
foreach ($this->rules as $item) {
|
||||
foreach ($item['rule_content'] as $rule) {
|
||||
if ($this->checkRule($rule)) {
|
||||
return $item['bill_category'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步到对账表(finance.bill)
|
||||
* @param array $data 原始数据
|
||||
* @param string $bill_category 具体类别
|
||||
* @return bool
|
||||
*/
|
||||
public function syncToBill($data, $bill_category='')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if(!$data['content']) return false;
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
$oMonthlyReport = kernel::single('finance_monthly_report');
|
||||
|
||||
// 判断是正向还是逆向
|
||||
$is_forward = isset($tmp['_is_forward']) ? $tmp['_is_forward'] : true;
|
||||
|
||||
$tmp['fee_obj'] = '微盟零售';
|
||||
$tmp['fee_item'] = $bill_category;
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if(!$res['status']) return false;
|
||||
|
||||
if(!$data['shop_name']){
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
// 根据正向/逆向获取时间(字符串转时间戳)
|
||||
if ($is_forward) {
|
||||
$trade_time = isset($tmp['trade_time']) ? strtotime($tmp['trade_time']) : 0;
|
||||
} else {
|
||||
$trade_time = isset($tmp['refund_time']) ? strtotime($tmp['refund_time']) : 0;
|
||||
}
|
||||
|
||||
// amount 已经在 getSdf 中处理(逆向已转为负数)
|
||||
$money = isset($tmp['amount']) ? floatval($tmp['amount']) : 0;
|
||||
$credential_number = isset($tmp['channel_trade_no']) ? $tmp['channel_trade_no'] : '';
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $this->_getOrderBn($tmp),
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => $trade_time,
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($money, 2), // 保留正负
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => $credential_number,
|
||||
'member' => '', // member 都为空
|
||||
'memo' => '', // remarks 都为空
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => $is_forward ? '交易金额' : '退款金额',
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1, // 流水直接设置记账成功
|
||||
'charge_time' => time(),
|
||||
);
|
||||
|
||||
$base_sdf['monthly_id'] = 0;
|
||||
$base_sdf['monthly_item_id'] = 0;
|
||||
$base_sdf['monthly_status'] = 0;
|
||||
|
||||
$base_sdf['crc32_order_bn'] = sprintf('%u', crc32($base_sdf['order_bn']));
|
||||
$base_sdf['bill_bn'] = $mdlBill->gen_bill_bn();
|
||||
$base_sdf['unconfirm_money'] = $base_sdf['money'];
|
||||
|
||||
if($mdlBill->insert($base_sdf)){
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入日期列
|
||||
* @param array|null $title
|
||||
* @return array
|
||||
*/
|
||||
public function getImportDateColunm($title = null)
|
||||
{
|
||||
// 找到时间列的位置
|
||||
// 正向使用"交易时间",逆向使用"退款时间"
|
||||
$timeColumn = array();
|
||||
if ($this->is_forward === false) {
|
||||
$timeColumn = array('退款时间');
|
||||
} else {
|
||||
$timeColumn = array('交易时间');
|
||||
}
|
||||
|
||||
$timeCol = array();
|
||||
if ($title) {
|
||||
foreach ($timeColumn as $v) {
|
||||
$k = array_search($v, $title);
|
||||
if ($k !== false) {
|
||||
$timeCol[] = $k + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单编号
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public function updateOrderBn($data)
|
||||
{
|
||||
$mdlBill = app::get('financebase')->model('bill');
|
||||
|
||||
foreach($data as $row) {
|
||||
$order_bn = $this->_getOrderBn($row);
|
||||
if($order_bn) {
|
||||
$is_forward = isset($row['_is_forward']) ? $row['_is_forward'] : true;
|
||||
$filter = array(
|
||||
'unique_id' => md5(sprintf(
|
||||
'%s_%s',
|
||||
isset($row['order_no']) ? $row['order_no'] : '',
|
||||
$is_forward ? (isset($row['channel_trade_no']) ? $row['channel_trade_no'] : '') : (isset($row['channel_refund_no']) ? $row['channel_refund_no'] : '')
|
||||
))
|
||||
);
|
||||
$mdlBill->update(array('order_bn' => $order_bn), $filter);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
* @param string $file_name 文件名
|
||||
* @param string $file_type 文件类型
|
||||
* @return array
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
|
||||
// 读取第一个工作表的第一行(表头)
|
||||
$row = $ioType->getData($file_name, 0, 1, 0);
|
||||
|
||||
if (empty($row) || !isset($row[0])) {
|
||||
return array(false, '文件没有数据');
|
||||
}
|
||||
|
||||
// 判断是正向还是逆向(根据表头第一个字段)
|
||||
$first_title = trim($row[0][0]);
|
||||
$is_forward = ($first_title != '退款时间');
|
||||
|
||||
// 根据正向/逆向获取对应的表头进行验证
|
||||
if ($is_forward) {
|
||||
$title = array_values($this->getTitleForward());
|
||||
} else {
|
||||
$title = array_values($this->getTitleReverse());
|
||||
}
|
||||
sort($title);
|
||||
|
||||
$fileTitle = $row[0];
|
||||
sort($fileTitle);
|
||||
|
||||
// 完全匹配
|
||||
if ($title == $fileTitle) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
// 包含关系匹配
|
||||
if (!array_diff($fileTitle, $title)) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
return array(false, '文件模板错误:' . var_export($row[0], true) . ',正确的为:' . var_export($title, 1));
|
||||
}
|
||||
}
|
||||
|
||||
251
app/financebase/lib/data/bill/xhs.php
Normal file
251
app/financebase/lib/data/bill/xhs.php
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
/**
|
||||
* 处理小红书账单导入
|
||||
*
|
||||
* @author AI Assistant
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
class financebase_data_bill_xhs extends financebase_abstract_bill
|
||||
{
|
||||
public $column_num = 5; // 5个字段:订单号、国补金额、SKU、数量、账单日期
|
||||
public $ioTitle = array();
|
||||
public $ioTitleKey = array();
|
||||
private static $shop_type_cache = array(); // 静态变量缓存店铺类型数据
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
$title = array(
|
||||
'order_bn' => '订单号',
|
||||
'amount' => '国补金额',
|
||||
'sku' => 'SKU',
|
||||
'quantity' => '数量',
|
||||
'trade_time' => '账单日期'
|
||||
);
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getSdf($row, $offset = 1, $title)
|
||||
{
|
||||
$row = array_map('trim', $row);
|
||||
|
||||
if (!$this->ioTitle) {
|
||||
$this->ioTitle = $this->getTitle();
|
||||
$this->ioTitleKey = array_keys($this->ioTitle);
|
||||
}
|
||||
|
||||
$titleKey = array();
|
||||
foreach ($title as $k => $t) {
|
||||
$titleKey[$k] = array_search($t, $this->getTitle());
|
||||
if ($titleKey[$k] === false) {
|
||||
return array('status' => false, 'msg' => '未定义字段`' . $t . '`');
|
||||
}
|
||||
}
|
||||
|
||||
$res = array('status' => true, 'data' => array(), 'msg' => '');
|
||||
|
||||
if ($this->column_num <= count($row) && $row[0] != '订单号') {
|
||||
$tmp = array_combine($titleKey, $row);
|
||||
|
||||
// 必填字段验证
|
||||
$required_fields = array('order_bn', 'amount', 'sku', 'quantity', 'trade_time');
|
||||
foreach ($required_fields as $field) {
|
||||
if (empty($tmp[$field])) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 不能为空!", $offset, $this->ioTitle[$field]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
// 金额格式验证
|
||||
if (!is_numeric($tmp['amount'])) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 金额(%s)格式错误!", $offset, $this->ioTitle['amount'], $tmp['amount']);
|
||||
return $res;
|
||||
}
|
||||
|
||||
// 数量格式验证
|
||||
if (!is_numeric($tmp['quantity']) || $tmp['quantity'] <= 0) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 数量(%s)必须为正数!", $offset, $this->ioTitle['quantity'], $tmp['quantity']);
|
||||
return $res;
|
||||
}
|
||||
|
||||
// 日期格式验证
|
||||
if (!strtotime($tmp['trade_time'])) {
|
||||
$res['status'] = false;
|
||||
$res['msg'] = sprintf("LINE %d : %s 日期(%s)格式错误!", $offset, $this->ioTitle['trade_time'], $tmp['trade_time']);
|
||||
return $res;
|
||||
}
|
||||
|
||||
$res['data'] = $tmp;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function _filterData($data)
|
||||
{
|
||||
$new_data = array();
|
||||
|
||||
$new_data['order_bn'] = $this->_getOrderBn($data);
|
||||
$new_data['trade_no'] = '';
|
||||
$new_data['financial_no'] = $data['order_bn'];
|
||||
$new_data['out_trade_no'] = '';
|
||||
$new_data['trade_time'] = strtotime($data['trade_time']);
|
||||
$new_data['trade_type'] = '小红书账单';
|
||||
$new_data['money'] = $data['amount'];
|
||||
$new_data['member'] = '';
|
||||
|
||||
// unique_id 生成规则:shop_id + 订单号 + SKU + 国补金额的MD5
|
||||
$shop_id = $data['shop_id'] ?: $this->getCurrentShopId();
|
||||
$new_data['unique_id'] = md5($shop_id . '-' . $data['order_bn'] . '-' . $data['sku'] . '-' . $data['amount']);
|
||||
|
||||
$shop_info = $this->getShopInfoByShopId($shop_id);
|
||||
$new_data['platform_type'] = 'xhs'; // 小红书固定平台类型
|
||||
$new_data['remarks'] = '小红书账单导入-SKU:' . $data['sku'] . ' 数量:' . $data['quantity'];
|
||||
|
||||
return $new_data;
|
||||
}
|
||||
|
||||
public function _getOrderBn($params)
|
||||
{
|
||||
return $params['order_bn'];
|
||||
}
|
||||
|
||||
public function getBillCategory($params)
|
||||
{
|
||||
// 小红书账单固定类别
|
||||
return '小红书账单';
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否有效
|
||||
* @param string $file_name 文件名
|
||||
* @param string $file_type 文件类型
|
||||
* @return array [是否有效, 错误信息, 标题]
|
||||
*/
|
||||
public function checkFile($file_name, $file_type)
|
||||
{
|
||||
$ioType = kernel::single('financebase_io_' . $file_type);
|
||||
$row = $ioType->getData($file_name, 0, 1);
|
||||
$title = array_values($this->getTitle());
|
||||
sort($title);
|
||||
|
||||
$xhsTitle = $row[0];
|
||||
sort($xhsTitle);
|
||||
if ($title == $xhsTitle) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
if (!array_diff($xhsTitle, $title)) {
|
||||
return array(true, '文件模板匹配', $row[0]);
|
||||
}
|
||||
|
||||
return array(false, '文件模板错误:' . var_export($row[0], true) . ',正确的为:' . var_export($title, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入日期列配置
|
||||
* @param array $title 标题数组
|
||||
* @return array
|
||||
*/
|
||||
public function getImportDateColunm($title = null)
|
||||
{
|
||||
// 小红书导入的日期字段配置
|
||||
$timeColumn = ['账单日期'];
|
||||
$timeCol = array();
|
||||
foreach ($timeColumn as $v) {
|
||||
if($k = array_search($v, $title)) {
|
||||
$timeCol[] = $k+1;
|
||||
}
|
||||
}
|
||||
$timezone = defined('DEFAULT_TIMEZONE') ? DEFAULT_TIMEZONE : 0;
|
||||
return array('column' => $timeCol, 'time_diff' => $timezone * 3600);
|
||||
}
|
||||
|
||||
public function syncToBill($data, $bill_category = '')
|
||||
{
|
||||
$data['content'] = json_decode(stripslashes($data['content']), 1);
|
||||
if (!$data['content']) return false;
|
||||
|
||||
$tmp = $data['content'];
|
||||
$shop_id = $data['shop_id'];
|
||||
|
||||
$mdlBill = app::get('finance')->model('bill');
|
||||
$oMonthlyReport = kernel::single('finance_monthly_report');
|
||||
|
||||
$tmp['fee_obj'] = '小红书';
|
||||
$tmp['fee_item'] = '小红书账单';
|
||||
|
||||
$res = $this->getBillType($tmp, $shop_id);
|
||||
if (!$res['status']) return false;
|
||||
|
||||
if (!$data['shop_name']) {
|
||||
$data['shop_name'] = isset($this->shop_list[$data['shop_id']]) ? $this->shop_list[$data['shop_id']]['name'] : '';
|
||||
}
|
||||
|
||||
$base_sdf = array(
|
||||
'order_bn' => $tmp['order_bn'],
|
||||
'channel_id' => $data['shop_id'],
|
||||
'channel_name' => $data['shop_name'],
|
||||
'trade_time' => strtotime($tmp['trade_time']),
|
||||
'fee_obj' => $tmp['fee_obj'],
|
||||
'money' => round($tmp['money'], 2),
|
||||
'fee_item' => $tmp['fee_item'],
|
||||
'fee_item_id' => isset($this->fee_item_rules[$tmp['fee_item']]) ? $this->fee_item_rules[$tmp['fee_item']] : 0,
|
||||
'credential_number' => $tmp['financial_no'],
|
||||
'member' => '',
|
||||
'memo' => $tmp['remarks'],
|
||||
'unique_id' => $data['unique_id'],
|
||||
'create_time' => time(),
|
||||
'fee_type' => $tmp['trade_type'],
|
||||
'fee_type_id' => $res['fee_type_id'],
|
||||
'bill_type' => $res['bill_type'],
|
||||
'charge_status' => 1,
|
||||
'charge_time' => time(),
|
||||
'monthly_id' => 0,
|
||||
'monthly_item_id' => 0,
|
||||
'monthly_status' => 0,
|
||||
'crc32_order_bn' => sprintf('%u', crc32($tmp['order_bn'])),
|
||||
'bill_bn' => $mdlBill->gen_bill_bn(),
|
||||
'unconfirm_money' => round($tmp['money'], 2),
|
||||
);
|
||||
|
||||
if ($mdlBill->insert($base_sdf)) {
|
||||
kernel::single('finance_monthly_report_items')->dealBillMatchReport($base_sdf['bill_id']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getShopInfoByShopId($shop_id)
|
||||
{
|
||||
if (!$shop_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果缓存为空,一次性查询所有店铺数据
|
||||
if (empty(self::$shop_type_cache)) {
|
||||
$mdlShop = app::get('ome')->model('shop');
|
||||
$shop_list = $mdlShop->getList('shop_id,shop_type');
|
||||
|
||||
// 将数据存入静态缓存,key为shop_id,value为shop数组
|
||||
foreach ($shop_list as $shop) {
|
||||
self::$shop_type_cache[$shop['shop_id']] = $shop;
|
||||
}
|
||||
}
|
||||
|
||||
// 从缓存中获取shop信息
|
||||
if (isset(self::$shop_type_cache[$shop_id])) {
|
||||
return self::$shop_type_cache[$shop_id];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getCurrentShopId()
|
||||
{
|
||||
// 从当前请求中获取shop_id
|
||||
return $_POST['shop_id'] ?? '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user