|
|
@@ -4,8 +4,10 @@ namespace App\Service;
|
|
|
|
|
|
use App\Exports\TableHeadExport;
|
|
|
use App\Import\ImportAll;
|
|
|
+use App\Model\Depart;
|
|
|
use App\Model\Device;
|
|
|
use App\Model\Employee;
|
|
|
+use App\Model\EmployeeDepartPermission;
|
|
|
use App\Model\Fee;
|
|
|
use App\Model\Item;
|
|
|
use App\Model\ItemDetails;
|
|
|
@@ -21,6 +23,8 @@ use PhpOffice\PhpSpreadsheet\Shared\Date;
|
|
|
class ImportService extends Service
|
|
|
{
|
|
|
public static $type = [
|
|
|
+ 'depart', // 部门
|
|
|
+ 'employee', // 用户
|
|
|
'device', // 设备
|
|
|
'item', // 项目
|
|
|
'fee', // 费用
|
|
|
@@ -32,11 +36,10 @@ class ImportService extends Service
|
|
|
|
|
|
public function getTableTitleXls($data,$user){
|
|
|
if(empty($data['type'])) return [false,'缺少类型'];
|
|
|
- if(! in_array($data['type'],self::$type)) return [false,'类型不存在'];
|
|
|
|
|
|
//获取配置文件
|
|
|
$fuc = $data['type'];
|
|
|
- if (! method_exists(self::class, $fuc)) return [false, "导入文件获取不存在,请联系开发"];
|
|
|
+ if (! method_exists(self::class, $fuc)) return [false, "导入文件方法获取不存在,请联系开发"];
|
|
|
list($status,$return) = $this->$fuc($data,$user);
|
|
|
list($msg,$filename) = $return;
|
|
|
if(! $status) return [false, $msg];
|
|
|
@@ -59,6 +62,28 @@ class ImportService extends Service
|
|
|
return config($config) ?? [];
|
|
|
}
|
|
|
|
|
|
+ private function depart($data,$user){
|
|
|
+ $config = $this->getTableConfig($data['type']);
|
|
|
+ if(empty($config)) return [false, ['导入配置表头文件不存在','']];
|
|
|
+
|
|
|
+ $config_array = $config['array'] ?? [];
|
|
|
+ //生成下载文件
|
|
|
+ $filename = $config['name'] . "导入模板_" . time() . '.' . 'xlsx';
|
|
|
+
|
|
|
+ return [true, [$config_array, $filename]];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function employee($data,$user){
|
|
|
+ $config = $this->getTableConfig($data['type']);
|
|
|
+ if(empty($config)) return [false, ['导入配置表头文件不存在','']];
|
|
|
+
|
|
|
+ $config_array = $config['array'] ?? [];
|
|
|
+ //生成下载文件
|
|
|
+ $filename = $config['name'] . "导入模板_" . time() . '.' . 'xlsx';
|
|
|
+
|
|
|
+ return [true, [$config_array, $filename]];
|
|
|
+ }
|
|
|
+
|
|
|
private function device($data,$user){
|
|
|
$config = $this->getTableConfig($data['type']);
|
|
|
if(empty($config)) return [false, ['导入配置表头文件不存在','']];
|
|
|
@@ -188,6 +213,460 @@ class ImportService extends Service
|
|
|
return [true, ''];
|
|
|
}
|
|
|
|
|
|
+ // 项目 -----------------------------------
|
|
|
+ public function employeeImport($array, $user, $other_param)
|
|
|
+ {
|
|
|
+ $upload = $array[0];
|
|
|
+ list($status, $msg) = $this->compareTableAndReturn($upload, $other_param);
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+ $table_config = $msg;
|
|
|
+
|
|
|
+ unset($array[0]);
|
|
|
+ if (empty($array)) return [false, '导入数据不能为空'];
|
|
|
+
|
|
|
+ // 1. 公共校验 (必填、唯一性等)
|
|
|
+ list($array, $error) = $this->checkCommon($array, $table_config);
|
|
|
+ if (!empty($error)) return [0, $error];
|
|
|
+
|
|
|
+ // 2. 业务详细校验 (获取更新映射及明细数据)
|
|
|
+ list($error, $update_map, $detail_data_map) = $this->employeeCheck($array, $user, $table_config);
|
|
|
+ if (!empty($error)) return [0, $error];
|
|
|
+
|
|
|
+ $time = time();
|
|
|
+ $insert_data = [];
|
|
|
+ $update_data = [];
|
|
|
+ $all_detail_insert = [];
|
|
|
+ $update_main_ids = [];
|
|
|
+
|
|
|
+ // 3. 数据分拣
|
|
|
+ foreach ($array as $key => $value) {
|
|
|
+ $main_tmp = [];
|
|
|
+ foreach ($value as $k => $val) {
|
|
|
+ if (!empty($table_config[$k]['is_main'])) {
|
|
|
+ $main_tmp[$table_config[$k]['key']] = $val;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isset($update_map[$key])) {
|
|
|
+ // 更新逻辑
|
|
|
+ $empId = $update_map[$key];
|
|
|
+ $update_data[] = array_merge($main_tmp, ['id' => $empId]);
|
|
|
+ $update_main_ids[] = $empId;
|
|
|
+
|
|
|
+ // 收集明细 (后续统一插入)
|
|
|
+ if (isset($detail_data_map[$key])) {
|
|
|
+ foreach ($detail_data_map[$key] as $d) {
|
|
|
+ $all_detail_insert[] = array_merge($d, ['employee_id' => $empId, 'top_depart_id' => $user['top_depart_id']]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 新增逻辑
|
|
|
+ $main_tmp['account'] = $user['top_depart_code'] . "_" . $main_tmp['number'];
|
|
|
+ $main_tmp['top_depart_id'] = $user['top_depart_id'];
|
|
|
+ $main_tmp['crt_id'] = $user['id'];
|
|
|
+ $main_tmp['crt_time'] = $time;
|
|
|
+ // 以 number 为键,方便后续回填 ID
|
|
|
+ $insert_data[$main_tmp['number']] = $main_tmp;
|
|
|
+
|
|
|
+ if (isset($detail_data_map[$key])) {
|
|
|
+ foreach ($detail_data_map[$key] as $d) {
|
|
|
+ $all_detail_insert[] = array_merge($d, ['_number' => $main_tmp['number'], 'top_depart_id' => $main_tmp['top_depart_id']]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DB::beginTransaction();
|
|
|
+ try {
|
|
|
+ // 4. 执行新增主表
|
|
|
+ if (!empty($insert_data)) {
|
|
|
+ foreach (array_chunk($insert_data, 500) as $chunk) {
|
|
|
+ Employee::insert($chunk);
|
|
|
+ }
|
|
|
+ // 获取新插入数据的 ID 映射
|
|
|
+ $new_item_maps = Employee::whereIn('number', array_keys($insert_data))
|
|
|
+ ->where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->pluck('id', 'number')->toArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 执行更新主表 (分批更新)
|
|
|
+ if (!empty($update_data)) {
|
|
|
+ foreach (array_chunk($update_data, 100) as $chunk) {
|
|
|
+ foreach ($chunk as $uItem) {
|
|
|
+ $id = $uItem['id'];
|
|
|
+ unset($uItem['id']);
|
|
|
+ Employee::where('id', $id)->update($uItem);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 处理明细表 (先删后插策略)
|
|
|
+ // 删除旧明细 (逻辑删除)
|
|
|
+ if (!empty($update_main_ids)) EmployeeDepartPermission::whereIn('employee_id', $update_main_ids)->delete();
|
|
|
+
|
|
|
+ // 回填新增主表的 ID 到明细数组
|
|
|
+ foreach ($all_detail_insert as &$di) {
|
|
|
+ if (isset($di['_number'])) {
|
|
|
+ $di['employee_id'] = $new_item_maps[$di['_number']] ?? 0;
|
|
|
+ unset($di['_number']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ unset($di);
|
|
|
+
|
|
|
+ // 批量插入所有明细
|
|
|
+ if (!empty($all_detail_insert)) {
|
|
|
+ foreach (array_chunk($all_detail_insert, 500) as $chunk) {
|
|
|
+ EmployeeDepartPermission::insert($chunk);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ return [false, "失败:" . $e->getMessage() . " (行号:" . $e->getLine() . ")"];
|
|
|
+ }
|
|
|
+
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getEmployeeList($array, $user, $index){
|
|
|
+ //查找设备
|
|
|
+ $codes = array_unique(array_filter(array_column($array,$index)));
|
|
|
+
|
|
|
+ return Employee::where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->whereIn('number', $codes)
|
|
|
+ ->pluck('id','number')
|
|
|
+ ->toArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ private function employeeCheck(&$array, $user, $table_config)
|
|
|
+ {
|
|
|
+ $keys = array_column($table_config, 'key');
|
|
|
+ $codeIdx = array_search('number', $keys);
|
|
|
+ $sexIdx = array_search('sex', $keys);
|
|
|
+ $eductionIdx = array_search('education', $keys);
|
|
|
+ $stateIdx = array_search('state', $keys);
|
|
|
+ $depIdx = array_search('depart_list', $keys);
|
|
|
+
|
|
|
+ $code_map = $this->getEmployeeList($array, $user, $codeIdx);
|
|
|
+ $dep_map = $this->getEDataList($array, $user, $depIdx);
|
|
|
+
|
|
|
+ $errors = [];
|
|
|
+ $update_mapping = [];
|
|
|
+ $detail_storage = [];
|
|
|
+ $sex_map = array_flip(Employee::SEX_TYPE);
|
|
|
+ $e_map = array_flip(Employee::Education);
|
|
|
+ $state_map = array_flip(Employee::State_Type);
|
|
|
+
|
|
|
+ foreach ($array as $rowIndex => $rowValue) {
|
|
|
+ $displayLine = $rowIndex + 1;
|
|
|
+
|
|
|
+ $valCode = $rowValue[$codeIdx] ?? '';
|
|
|
+
|
|
|
+ // 1. 判定更新还是新增
|
|
|
+ if (isset($code_map[$valCode])) {
|
|
|
+ $update_mapping[$rowIndex] = $code_map[$valCode];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 校验
|
|
|
+ $sex_text = $rowValue[$sexIdx] ?? '';
|
|
|
+ if(! empty($sex_text)){
|
|
|
+ if (!isset($sex_map[$sex_text])) {
|
|
|
+ $errors[] = "第{$displayLine}行:性别[{$sex_text}]无效";
|
|
|
+ } else {
|
|
|
+ $array[$rowIndex][$sexIdx] = $sex_map[$sex_text];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $e_text = $rowValue[$eductionIdx] ?? '';
|
|
|
+ if(! empty($e_text)){
|
|
|
+ if (!isset($e_map[$e_text])) {
|
|
|
+ $errors[] = "第{$displayLine}行:性别[{$e_text}]无效";
|
|
|
+ } else {
|
|
|
+ $array[$rowIndex][$eductionIdx] = $e_map[$e_text];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $state_text = $rowValue[$stateIdx] ?? '';
|
|
|
+ if (!isset($state_map[$state_text])) {
|
|
|
+ $errors[] = "第{$displayLine}行:状态[{$state_text}]无效";
|
|
|
+ } else {
|
|
|
+ $array[$rowIndex][$stateIdx] = $state_map[$state_text];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 解析部门 (明细类型1)
|
|
|
+ if ($depIdx !== false && !empty($rowValue[$depIdx])) {
|
|
|
+ foreach (explode(',', $rowValue[$depIdx]) as $mNum) {
|
|
|
+ $mNum = trim($mNum);
|
|
|
+ if (!isset($dep_map[$mNum])) {
|
|
|
+ $errors[] = "第{$displayLine}行:部门编码[{$mNum}]不存在";
|
|
|
+ } else {
|
|
|
+ $detail_storage[$rowIndex][] = [
|
|
|
+ 'depart_id' => $dep_map[$mNum],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $error_str = !empty($errors) ? implode('|', $errors) : "";
|
|
|
+ return [$error_str, $update_mapping, $detail_storage];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getEDataList($array, $user, $index1)
|
|
|
+ {
|
|
|
+ $depNums = [];
|
|
|
+
|
|
|
+ // 去重收集
|
|
|
+ foreach ($array as $row) {
|
|
|
+ if (!empty($row[$index1])) {
|
|
|
+ foreach (explode(',', $row[$index1]) as $v) $depNums[trim($v)] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Depart::where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->whereIn('code', array_keys($depNums))
|
|
|
+ ->pluck('id', 'code')->toArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 部门 ----------------------------------
|
|
|
+ public function departImport($array, $user, $other_param)
|
|
|
+ {
|
|
|
+ $upload = $array[0];
|
|
|
+ list($status, $msg) = $this->compareTableAndReturn($upload, $other_param);
|
|
|
+ if (!$status) return [false, $msg];
|
|
|
+ $table_config = $msg;
|
|
|
+
|
|
|
+ unset($array[0]);
|
|
|
+ if (empty($array)) return [false, '导入数据不能为空'];
|
|
|
+
|
|
|
+ list($array, $error) = $this->checkCommon($array, $table_config);
|
|
|
+ if (!empty($error)) return [0, $error];
|
|
|
+
|
|
|
+ // 2. 详细校验
|
|
|
+ list($error, $update_map, $parent_code_map) = $this->departCheck($array, $user, $table_config);
|
|
|
+ if (!empty($error)) return [0, $error];
|
|
|
+
|
|
|
+ $time = time();
|
|
|
+ $insert = [];
|
|
|
+ $update = [];
|
|
|
+ $all_codes = [];
|
|
|
+ $all_parent_codes = [];
|
|
|
+
|
|
|
+ // --- 修正点 1: 必须确保索引提取准确 ---
|
|
|
+ $keys = array_column($table_config, 'key');
|
|
|
+ $codeIdx = array_search('code', $keys);
|
|
|
+ // ------------------------------------
|
|
|
+
|
|
|
+ foreach ($array as $key => $value) {
|
|
|
+ $cCode = trim($value[$codeIdx] ?? '');
|
|
|
+ if($cCode === '') continue;
|
|
|
+
|
|
|
+ $all_codes[] = $cCode;
|
|
|
+ if (isset($parent_code_map[$key])) {
|
|
|
+ $all_parent_codes[] = $parent_code_map[$key];
|
|
|
+ }
|
|
|
+
|
|
|
+ $main_tmp = [];
|
|
|
+ foreach ($value as $k => $val){
|
|
|
+ if(!empty($table_config[$k]['is_main'])){
|
|
|
+ if ($table_config[$k]['key'] !== 'parent_id') {
|
|
|
+ $main_tmp[$table_config[$k]['key']] = $val;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isset($update_map[$key])) {
|
|
|
+ $update[] = array_merge($main_tmp, ['id' => $update_map[$key]]);
|
|
|
+ } else {
|
|
|
+ $main_tmp['top_depart_id'] = $user['top_depart_id'];
|
|
|
+ $main_tmp['crt_time'] = $time;
|
|
|
+ $main_tmp['parent_id'] = 0;
|
|
|
+ $insert[] = $main_tmp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $searchCodes = array_unique(array_merge($all_codes, $all_parent_codes));
|
|
|
+
|
|
|
+ DB::beginTransaction();
|
|
|
+ try {
|
|
|
+ if (!empty($insert)) {
|
|
|
+ foreach (array_chunk($insert, 500) as $chunk) {
|
|
|
+ Depart::insert($chunk);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!empty($update)) {
|
|
|
+ foreach ($update as $item) {
|
|
|
+ $uId = $item['id']; unset($item['id']);
|
|
|
+ Depart::where('id', $uId)->update($item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- 修正点 2: 核心回填逻辑 ---
|
|
|
+ $newCodeToIdMap = Depart::where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->whereIn('code', $searchCodes)
|
|
|
+ ->pluck('id', 'code')
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ foreach ($parent_code_map as $rowIndex => $pCode) {
|
|
|
+ // 这里必须通过 $rowIndex 从原始 $array 中精准获取当前行的编码
|
|
|
+ $currentCode = isset($array[$rowIndex][$codeIdx]) ? trim($array[$rowIndex][$codeIdx]) : '';
|
|
|
+ $pCode = trim($pCode);
|
|
|
+
|
|
|
+ if ($currentCode === '' || $pCode === '') continue;
|
|
|
+
|
|
|
+ $currentId = $newCodeToIdMap[$currentCode] ?? null;
|
|
|
+ $parentId = $newCodeToIdMap[$pCode] ?? null;
|
|
|
+
|
|
|
+ // 严谨判断:只有当前记录存在,且上级记录也存在,且两者不是同一个 ID 时才更新
|
|
|
+ if ($currentId && $parentId && $currentId != $parentId) {
|
|
|
+ Depart::where('id', $currentId)->update(['parent_id' => $parentId]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+ return [false, "失败:" . $e->getMessage() . " (行号:" . $e->getLine() . ")"];
|
|
|
+ }
|
|
|
+ return [true, ''];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function departCheck(&$array, $user, $table_config)
|
|
|
+ {
|
|
|
+ $keys = array_column($table_config, 'key');
|
|
|
+ $codeIdx = array_search('code', $keys);
|
|
|
+ $parentIdx = array_search('parent_id', $keys);
|
|
|
+
|
|
|
+ // 1. 获取基础数据
|
|
|
+ list($dbFeeMap, $excelCodesMap) = $this->getDepartList($array, $user, $codeIdx);
|
|
|
+
|
|
|
+ $errors = [];
|
|
|
+ $update = [];
|
|
|
+ $parent_code_map = [];
|
|
|
+
|
|
|
+ // 2. 建立 Excel 内部父子关系映射(用于环路追溯)
|
|
|
+ $currentExcelMap = [];
|
|
|
+ foreach ($array as $row) {
|
|
|
+ $c = trim($row[$codeIdx] ?? '');
|
|
|
+ $p = trim($row[$parentIdx] ?? '');
|
|
|
+ if ($c !== '') $currentExcelMap[$c] = $p ?: $user['top_depart_code'] ;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 逐行校验
|
|
|
+ foreach ($array as $rowIndex => $value) {
|
|
|
+ $displayLine = $rowIndex + 1;
|
|
|
+
|
|
|
+ $valCode = trim($value[$codeIdx] ?? '');
|
|
|
+ $valParentCode = trim($value[$parentIdx] ?? '');
|
|
|
+
|
|
|
+ if ($valCode === '') continue;
|
|
|
+
|
|
|
+ // 更新状态记录
|
|
|
+ if (isset($dbFeeMap[$valCode])) {
|
|
|
+ $update[$rowIndex] = $dbFeeMap[$valCode]['id'];
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($valParentCode !== '') {
|
|
|
+ // --- A. 存在性校验 ---
|
|
|
+ // 这里会检查 006 是否在数据库,或者是否在本次 Excel 的其他行中
|
|
|
+ if (!isset($dbFeeMap[$valParentCode]) && !isset($excelCodesMap[$valParentCode])) {
|
|
|
+ $errors[] = "第{$displayLine}行:上级编码[{$valParentCode}]在系统和文件中均不存在";
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- B. 自引用校验 ---
|
|
|
+ if ($valCode === $valParentCode) {
|
|
|
+ $errors[] = "第{$displayLine}行:上级编码不能是自身";
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // --- C. 环路追溯 ---
|
|
|
+ $visited = [];
|
|
|
+ $res = $this->findDLoopInAncestors($valParentCode, $valCode, $currentExcelMap, $dbFeeMap, $visited);
|
|
|
+ if ($res !== false) {
|
|
|
+ if ($res['type'] === 'LOOP_SELF') {
|
|
|
+ $errors[] = "第{$displayLine}行:编码[{$valCode}]与上级[{$valParentCode}]存在循环引用";
|
|
|
+ } else {
|
|
|
+ $errors[] = "第{$displayLine}行:上级[{$valParentCode}]的溯源链条已成环";
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录有效的父级关系
|
|
|
+ $parent_code_map[$rowIndex] = $valParentCode;
|
|
|
+ }else{
|
|
|
+ $parent_code_map[$rowIndex] = $user['top_depart_code'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $error_string = !empty($errors) ? implode('|', $errors) : "";
|
|
|
+ return [$error_string, $update, $parent_code_map];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getDepartList($array, $user, $index)
|
|
|
+ {
|
|
|
+ // 关键:一定要把 Excel 里所有的 code 这一列全部拿出来,并去除空值
|
|
|
+ $codesInExcel = [];
|
|
|
+ foreach ($array as $row) {
|
|
|
+ $c = trim($row[$index] ?? '');
|
|
|
+ if ($c !== '') {
|
|
|
+ $codesInExcel[$c] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $allFees = Depart::where('del_time', 0)
|
|
|
+ ->where('top_depart_id', $user['top_depart_id'])
|
|
|
+ ->select('id', 'code', 'parent_id')
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ $dbFeeMap = [];
|
|
|
+ foreach ($allFees as $fee) {
|
|
|
+ $dbFeeMap[$fee->code] = [
|
|
|
+ 'id' => $fee->id,
|
|
|
+ 'code' => $fee->code,
|
|
|
+ 'parent_id' => $fee->parent_id
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回数据库映射和 Excel 编码映射
|
|
|
+ return [$dbFeeMap, $codesInExcel];
|
|
|
+ }
|
|
|
+
|
|
|
+ private function findDLoopInAncestors($startParentCode, $targetCode, $excelMap, $dbFeeMap, &$visited)
|
|
|
+ {
|
|
|
+ $current = $startParentCode;
|
|
|
+ while ($current !== '' && $current !== 0) {
|
|
|
+ if ($current === $targetCode) {
|
|
|
+ return ['type' => 'LOOP_SELF', 'code' => $current];
|
|
|
+ }
|
|
|
+ if (isset($visited[$current])) {
|
|
|
+ return ['type' => 'EXISTING_LOOP', 'code' => $current];
|
|
|
+ }
|
|
|
+ $visited[$current] = true;
|
|
|
+
|
|
|
+ if (isset($excelMap[$current]) && $excelMap[$current] !== '') {
|
|
|
+ $current = $excelMap[$current];
|
|
|
+ } elseif (isset($dbFeeMap[$current])) {
|
|
|
+ $parentId = $dbFeeMap[$current]['parent_id'];
|
|
|
+ $parentCode = '';
|
|
|
+ foreach ($dbFeeMap as $item) {
|
|
|
+ if ($item['id'] == $parentId) {
|
|
|
+ $parentCode = $item['code'];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $current = $parentCode;
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
// 设备 ------------------------------------
|
|
|
public function deviceImport($array, $user, $other_param){
|
|
|
$upload = $array[0];
|
|
|
@@ -434,10 +913,10 @@ class ImportService extends Service
|
|
|
DB::commit();
|
|
|
} catch (\Exception $e) {
|
|
|
DB::rollBack();
|
|
|
- return [false, "入库失败:" . $e->getMessage() . " (行号:" . $e->getLine() . ")"];
|
|
|
+ return [false, "失败:" . $e->getMessage() . " (行号:" . $e->getLine() . ")"];
|
|
|
}
|
|
|
|
|
|
- return [true, '导入成功'];
|
|
|
+ return [true, ''];
|
|
|
}
|
|
|
|
|
|
private function getItemList($array, $user, $index){
|
|
|
@@ -612,6 +1091,9 @@ class ImportService extends Service
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ $all_parent_codes = array_values($parent_code_map);
|
|
|
+ $searchCodes = array_unique(array_merge($all_codes, $all_parent_codes));
|
|
|
+
|
|
|
DB::beginTransaction();
|
|
|
try {
|
|
|
if (!empty($insert)) {
|
|
|
@@ -630,7 +1112,7 @@ class ImportService extends Service
|
|
|
// --- 修正点 2: 核心回填逻辑 ---
|
|
|
$newCodeToIdMap = Fee::where('del_time', 0)
|
|
|
->where('top_depart_id', $user['top_depart_id'])
|
|
|
- ->whereIn('code', array_unique($all_codes))
|
|
|
+ ->whereIn('code', $searchCodes)
|
|
|
->pluck('id', 'code')
|
|
|
->toArray();
|
|
|
|