Bläddra i källkod

Merge remote-tracking branch 'origin/master'

gogs 2 månader sedan
förälder
incheckning
f44b5621ec

+ 49 - 0
app/Http/Controllers/Api/ArchiveController.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Service\ArchiveService;
+use Illuminate\Http\Request;
+
+class ArchiveController extends BaseController
+{
+    public function archiveAdd(Request $request)
+    {
+        $service = new ArchiveService();
+        $user = $request->userData;
+        list($status,$data) = $service->archiveAdd($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+
+    }
+
+    public function archiveDel(Request $request)
+    {
+        $service = new ArchiveService();
+        $user = $request->userData;
+        list($status,$data) = $service->archiveDel($request->all(), $user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
+    public function archiveList(Request $request)
+    {
+        $service = new ArchiveService();
+        $user = $request->userData;
+        list($status,$data) = $service->archiveList($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+}

+ 1 - 1
app/Http/Controllers/Api/DeviceDepreciationController.php

@@ -38,7 +38,7 @@ class DeviceDepreciationController extends BaseController
     {
     {
         $service = new DeviceDepreciationService();
         $service = new DeviceDepreciationService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->monthlyDdOrderDel($request->all());
+        list($status,$data) = $service->monthlyDdOrderDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);

+ 2 - 2
app/Http/Controllers/Api/DeviceWorkController.php

@@ -38,7 +38,7 @@ class DeviceWorkController extends BaseController
     {
     {
         $service = new DeviceWorkService();
         $service = new DeviceWorkService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->monthlyDwOrderDel($request->all());
+        list($status,$data) = $service->monthlyDwOrderDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);
@@ -105,7 +105,7 @@ class DeviceWorkController extends BaseController
     {
     {
         $service = new DeviceWorkService();
         $service = new DeviceWorkService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->dailyDwOrderDel($request->all());
+        list($status,$data) = $service->dailyDwOrderDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);

+ 1 - 1
app/Http/Controllers/Api/PLeaveOverController.php

@@ -38,7 +38,7 @@ class PLeaveOverController extends BaseController
     {
     {
         $service = new PLeaveOverService();
         $service = new PLeaveOverService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->pLeaveOverDel($request->all());
+        list($status,$data) = $service->pLeaveOverDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);

+ 1 - 1
app/Http/Controllers/Api/PersonSalaryController.php

@@ -38,7 +38,7 @@ class PersonSalaryController extends BaseController
     {
     {
         $service = new PersonSalaryService();
         $service = new PersonSalaryService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->monthlyPsOrderDel($request->all());
+        list($status,$data) = $service->monthlyPsOrderDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);

+ 2 - 2
app/Http/Controllers/Api/PersonWorkController.php

@@ -38,7 +38,7 @@ class PersonWorkController extends BaseController
     {
     {
         $service = new PersonWorkService();
         $service = new PersonWorkService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->monthlyPwOrderDel($request->all());
+        list($status,$data) = $service->monthlyPwOrderDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);
@@ -105,7 +105,7 @@ class PersonWorkController extends BaseController
     {
     {
         $service = new PersonWorkService();
         $service = new PersonWorkService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->dailyPwOrderDel($request->all());
+        list($status,$data) = $service->dailyPwOrderDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);

+ 1 - 1
app/Http/Controllers/Api/RuleSetController.php

@@ -38,7 +38,7 @@ class RuleSetController extends BaseController
     {
     {
         $service = new RuleSetService();
         $service = new RuleSetService();
         $user = $request->userData;
         $user = $request->userData;
-        list($status,$data) = $service->ruleSetDel($request->all());
+        list($status,$data) = $service->ruleSetDel($request->all(), $user);
 
 
         if($status){
         if($status){
             return $this->json_return(200,'',$data);
             return $this->json_return(200,'',$data);

+ 312 - 3
app/Http/Controllers/Api/TestController.php

@@ -2,10 +2,319 @@
 
 
 namespace App\Http\Controllers\Api;
 namespace App\Http\Controllers\Api;
 
 
-use App\Service\qyWechatService;
-use Illuminate\Http\Request;
-use Illuminate\Support\Str;
+use App\Exports\ItemSalaryFTMultipleSheetExport;
+use App\Exports\ItemSalarySheetExport;
+use App\Exports\ManActivityTimeCardMultipleSheetExport;
+use App\Exports\ManMonthlyWorkHourMultipleSheetExport;
+use App\Exports\ProjectDepreciationMultipleSheetExport;
+use App\Exports\ResearchExpenseMultipleSheetExport;
+use App\Exports\ResearchExpenseSummaryMultipleSheetExport;
+use Maatwebsite\Excel\Facades\Excel;
 
 
 class TestController extends BaseController
 class TestController extends BaseController
 {
 {
+    public function aa(){
+         return $this->exportSummary();
+    }
+
+    public function itemSalary(){
+        // 1. 定义动态项目
+        $projects = ['RD01', 'RD02', 'RD03', 'RD04', 'RD03', 'RD04' , 'RD03', 'RD04', 'RD03', 'RD04', 'RD03', 'RD04', 'RD03'];
+
+        // 2. 构造导出数据 (从第5行开始的内容)
+        $exportData = [
+            // 第一行数据:2024年1月
+            [
+                '2024年1月',   // 年月 (A列)
+                '20', '5000',  // RD01 天数, 工资
+                '15', '4000',  // RD02
+                '10', '3000',  // RD03
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '13000'        // 合计 (最后一列)
+            ],
+            // 第二行数据:2024年2月
+            [
+                '2024年2月',
+                '20', '5000',  // RD01 天数, 工资
+                '15', '4000',  // RD02
+                '10', '3000',  // RD03
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '11300'
+            ],
+            [
+                '2024年3月',
+                '20', '5000',  // RD01 天数, 工资
+                '15', '4000',  // RD02
+                '10', '3000',  // RD03
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '11300'
+            ],
+            [
+                '2024年4月',
+                '20', '5000',  // RD01 天数, 工资
+                '15', '4000',  // RD02
+                '10', '3000',  // RD03
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '5',  '1000',  // RD04
+                '11300'
+            ],
+            [
+                '合计',
+            ],
+        ];
+
+        if(empty($file_name)) $file_name = date("Y-m-d") . "_". rand(1000,9999);
+        $filename =  $file_name . '.' . 'xlsx';
+        $bool = Excel::store(new ItemSalarySheetExport($projects, $exportData),"/public/export/{$filename}", null, 'Xlsx', []);
+        return $filename;
+    }
+
+    public function manActivityTimeCard(){
+        $allProjectsData = [
+            'RD01无人机研发' => [
+                ['1月', '研究人员', '张三', 192, 192, '100%', 8000, 1000, 500, 8000, 1000, 500, 8000, 1000, 500, 0, 0, 0],
+                ['小计:', '', '', 192, 192, '100%', 8000, 1000, 500, 8000, 1000, 500, 8000, 1000, 500, 0, 0, 0],
+                ['2月', '研究人员', '张三', 192, 192, '100%', 8000, 1000, 500, 8000, 1000, 500, 8000, 1000, 500, 0, 0, 0],
+                ['小计:', '', '', 192, 192, '100%', 8000, 1000, 500, 8000, 1000, 500, 8000, 1000, 500, 0, 0, 0],
+                ['合计', '', '', 192, 192, '', 8000, 1000, 500, 8000, 1000, 500, 8000, 1000, 500, 0, 0, 0],
+            ],
+            'RD02自动化系统' => [
+                ['1月', '技术人员', '李四', 160, 160, '100%', 7000, 800, 400, 7000, 800, 400, 7000, 800, 400, 0, 0, 0],
+                ['小计:', '', '', 160, 160, '100%', 7000, 800, 400, 7000, 800, 400, 7000, 800, 400, 0, 0, 0],
+                ['2月', '技术人员', '李四', 160, 160, '100%', 7000, 800, 400, 7000, 800, 400, 7000, 800, 400, 0, 0, 0],
+                ['小计:', '', '', 160, 160, '100%', 7000, 800, 400, 7000, 800, 400, 7000, 800, 400, 0, 0, 0],
+                ['合计', '', '', 160, 160, '', 7000, 800, 400, 7000, 800, 400, 7000, 800, 400, 0, 0, 0],
+            ]
+        ];
+
+        if(empty($file_name)) $file_name = date("Y-m-d") . "_". rand(1000,9999);
+        $filename =  $file_name . '.' . 'xlsx';
+
+        $bool =  Excel::store(new ManActivityTimeCardMultipleSheetExport($allProjectsData), "/public/export/{$filename}", null, 'Xlsx', []);
+        return $filename;
+    }
+
+    public function itemSalaryFT(){
+        $monthsData = [
+            '2024年4月' => [
+                'projects' => ['RD01', 'RD02', 'RD03',"aa"], // 4月有3个项目
+                'data' => [
+                    [1, '蔡1', 3165.00, 22, '', 8, 7, 7, 22, 0.00, 1150.91, 1007.05, 1007.04, 3165.00],
+                    [2, '蔡2', 4714.50, 22, '', 2, 8, 12, 22, 0.00, 428.59, 1714.36, 2571.55, 4714.50],
+                    ['合计', '', 30438.50, 110, 18, 14, 32, 46, 110, 6473.95, 2444.05, 7804.91, 13715.59, 30438.50]
+                ]
+            ],
+            '2024年5月' => [
+                'projects' => ['RD01', 'RD02', 'RD03',"cs"], // 4月有3个项目
+                'data' => [
+                    [1, '蔡1', 3165.00, 22, '', 8, 7, 7, 22, 0.00, 1150.91, 1007.05, 1007.04, 3165.00],
+                    [2, '蔡2', 4714.50, 22, '', 2, 8, 12, 22, 0.00, 428.59, 1714.36, 2571.55, 4714.50],
+                    ['合计', '', 30438.50, 110, 18, 14, 32, 46, 110, 6473.95, 2444.05, 7804.91, 13715.59, 30438.50]
+                ]
+            ],
+            '2024年6月' => [
+                'projects' => ['RD01', 'RD02', 'RD03'], // 4月有3个项目
+                'data' => [
+                    [1, '蔡1', 3165.00, 22, '', 8, 7, 7, 22, 0.00, 1150.91, 1007.05],
+                    [2, '蔡2', 4714.50, 22, '', 2, 8, 12, 22, 0.00, 428.59, 1714.36],
+                    ['合计', '', 30438.50, 110, 18, 14, 32, 46, 110, 6473.95, 2444.05, 7804.91]
+                ]
+            ]
+        ];
+
+        if(empty($file_name)) $file_name = date("Y-m-d") . "_". rand(1000,9999);
+        $filename =  $file_name . '.' . 'xlsx';
+
+        $bool =  Excel::store(new ItemSalaryFTMultipleSheetExport($monthsData), "/public/export/{$filename}", null, 'Xlsx', []);
+        return $filename;
+    }
+
+    public function manMonthlyWorkHour(){
+        $monthsData = [
+            '2024年4月' => [
+                'days' => 30,
+                'data' => [
+                    // 项目, 姓名, 1日, 2日, 3日, 4日... (空字符串代表没工时)
+                    ['RD02', '蔡1', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1],
+                    ['RD03', '蔡2', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', ''],
+                    ['RD05', '蔡3', '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, '', '', 1, ''],
+                ]
+            ]
+        ];
+
+        if(empty($file_name)) $file_name = date("Y-m-d") . "_". rand(1000,9999);
+        $filename =  $file_name . '.' . 'xlsx';
+
+        $bool =  Excel::store(new ManMonthlyWorkHourMultipleSheetExport($monthsData), "/public/export/{$filename}", null, 'Xlsx', []);
+        return $filename;
+    }
+
+    public function deviceZj(){
+        $monthsData = [
+            // 第一个 Sheet: 2025年-RD01项目
+            '2025-RD01' => [
+                'project_name' => '智能AI语音助手开发项目',
+                'months' => $this->generateTwelveMonthsData() // 生成1-12月模拟数据
+            ],
+            // 第二个 Sheet: 2025年-RD02项目
+            '2025-RD02' => [
+                'project_name' => '云端大数据分析平台',
+                'months' => $this->generateTwelveMonthsData()
+            ],
+        ];
+
+        if(empty($file_name)) $file_name = date("Y-m-d") . "_". rand(1000,9999);
+        $filename =  $file_name . '.' . 'xlsx';
+
+        $bool =  Excel::store(new ProjectDepreciationMultipleSheetExport($monthsData), "/public/export/{$filename}", null, 'Xlsx', []);
+        return $filename;
+    }
+
+    private function generateTwelveMonthsData()
+    {
+        $yearData = [];
+        for ($m = 1; $m <= 12; $m++) {
+            $yearData[$m] = [
+                [
+                    'name' => '青爻APC-110自动扫码枪',
+                    'total_hours' => 160,
+                    'project_hours' => 80,
+                    'ratio' => 50,
+                    'original_value' => 213675.21,
+                    'depreciation' => 1691.60,
+                    'confirmed_depreciation' => 338.32,
+                    'adjust_amount' => -338.32,
+                ],
+                [
+                    'name' => '自动美式三插端子系统',
+                    'total_hours' => 160,
+                    'project_hours' => 40,
+                    'ratio' => 25,
+                    'original_value' => 30769.23,
+                    'depreciation' => 243.59,
+                    'confirmed_depreciation' => 48.72,
+                    'adjust_amount' => -48.72,
+                ]
+            ];
+        }
+        return $yearData;
+    }
+
+    public function exportSummary()
+    {
+        // 定义你的动态科目(前 N 项)
+        // 注意:这里的顺序决定了 Excel 中 F 列往后的顺序
+        $dynamicHeaders = ['人员人工费用', '直接投入费用', '折旧费用', '无形资产摊销', '新产品设计费等'];
+
+        $items = [];
+        for ($i = 1; $i <= 10; $i++) {
+            $type = $i <= 5 ? '资本化支出' : '费用化支出';
+            $items[] = [
+                'no' => 'RD0' . $i,
+                'name' => '研发项目名称测试_' . $i,
+                'status' => rand(2, 3),
+                'type' => $type,
+                // 【重要】将明细金额放入 values 数组,顺序必须对应 $dynamicHeaders
+                'values' => [
+                    1 * $i, // 人员人工
+                    2 * $i, // 直接投入
+                    3 * $i, // 折旧
+                    4 * $i, // 无形资产
+                    5 * $i  // 新产品
+                ],
+                'val7_1' => 6, // 其他相关费用合计 (7.1)
+                'val8_1' => 7, // 委托境内 (8.1)
+                'val8_3' => 8, // 委托境外 (8.3) -> 原代码写 8.4 是不对的,公式会自动算 8.4
+            ];
+        }
+
+        $monthsData = [
+            '2026' => [
+                'tax_id'       => '91330101MA28XXXXXX',
+                'company_name' => '杭州青艾科技有限公司',
+                'items'        => $items,
+                'dynamic_headers' => $dynamicHeaders // 将配置也放入 payload 方便后面读取
+            ]
+        ];
+
+        $file_name = "研发支出汇总表_" . date("YmdHis");
+        $filename =  $file_name . '.xlsx';
+
+        // 传入 $dynamicHeaders 到构造函数
+        Excel::store(
+            new ResearchExpenseSummaryMultipleSheetExport($monthsData),
+            "public/export/{$filename}"
+        );
+
+        return $filename;
+    }
+
+    public function exportResearchExpense()
+    {
+        $sheetsData = [
+            '2025-RD01' => [
+                'project' => ['code' => '2025RD01', 'name' => '自动化设备研发'],
+                // 这里定义除了 人员人工和折旧 之外的其他科目
+                'dynamic_headers' => ['直接投入费用', '无形资产摊销', '其他相关费用'],
+                'data' => [
+                    // 每一行数据的长度必须与:基础(6列) + 固定明细(2列) + 动态明细(N列) + 委托(2列) 的总长度一致
+                    ['2025/01/31', '记账', '33', '原材料领用', 1000, 1000, 0, 0, 1000, 0, 0, 0, 0],
+                    ['合计', '', '', '', 1000, 1000, 0, 0, 1000, 0, 0, 0, 0]
+                ]
+            ],
+            '2025-RD02' => [
+                'project' => ['code' => '2025RD02', 'name' => '简易项目'],
+                'dynamic_headers' => ['其他相关费用'], // 这个Sheet只有1个动态列
+                'data' => [
+                    ['2025/02/15', '记账', '12', '技术服务费', 500, 500, 0, 0, 500, 0, 0],
+                    ['合计', '', '', '', 500, 500, 0, 0, 500, 0, 0]
+                ]
+            ]
+        ];
+
+        $file_name = date("YmdHis");
+        $filename = $file_name . '.xlsx';
+
+        Excel::store(
+            new ResearchExpenseMultipleSheetExport($sheetsData),
+            "public/export/{$filename}"
+        );
+
+        return $filename;
+    }
 }
 }

+ 16 - 0
app/Model/Archive.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Archive extends DataScopeBaseModel
+{
+    protected $guarded = [];
+    protected $table = "archive"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+
+    public static $field = ['month','id','crt_id','time'];
+}

+ 126 - 0
app/Service/ArchiveService.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace App\Service;
+
+use App\Model\Archive;
+use Illuminate\Support\Facades\DB;
+
+class ArchiveService extends Service
+{
+    public function archiveAdd($data,$user){
+        list($status,$msg) = $this->archiveRule($data,$user);
+        if(!$status) return [$status,$msg];
+
+        try {
+            DB::beginTransaction();
+
+            $model = new Archive();
+            $model->month = $data['month'];
+            $model->crt_id = $user['id'];
+            $model->top_depart_id = $data['top_depart_id'];
+            $model->save();
+
+            DB::commit();
+        }catch (\Exception $exception){
+            DB::rollBack();
+            return [false,$exception->getMessage()];
+        }
+
+        return [true,''];
+    }
+
+    public function archiveDel($data, $user){
+        if(empty($data['id']) || ! is_array($data['id'])) return [false,'ID不能为空或格式错误'];
+
+        Archive::whereIn('id', $data['id'])->update([
+            'del_time'=>time()
+        ]);
+
+        return [true,''];
+    }
+
+    public function archiveCommon($data,$user, $field = []){
+        if(empty($field)) $field = Archive::$field;
+
+        $model = Archive::TopClear($user,$data);
+        $model = $model->where('del_time',0)
+            ->select($field)
+            ->orderby('id', 'desc');
+
+        if(! empty($data['time'][0]) && ! empty($data['time'][1])) {
+            $return = $this->changeDateToTimeStampAboutRange($data['time']);
+            $model->where('month','>=',$return[0]);
+            $model->where('month','<=',$return[1]);
+        }
+
+        return $model;
+    }
+
+    public function archiveList($data, $user){
+        $model = $this->archiveCommon($data, $user);
+        $list = $this->limit($model,'',$data);
+        $list = $this->fillArchiveList($list);
+
+        return [true, $list];
+    }
+
+    public function fillArchiveList($data){
+        if(empty($data['data'])) return $data;
+
+        $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_column($data['data'],'crt_id')));
+        foreach ($data['data'] as $key => $value){
+            $data['data'][$key]['crt_time'] = $value['crt_time'] ? date('Y-m-d H:i:s',$value['crt_time']) : '';
+            $data['data'][$key]['month'] = $value['month'] ? date('Y-m',$value['month']) : '';
+            $data['data'][$key]['crt_name'] = $emp[$value['crt_id']] ?? '';
+        }
+
+        return $data;
+    }
+
+    public function archiveRule(&$data,$user, $add = true){
+        if(empty($data['month'])) return [false, '年月不能为空'];
+        $data['month'] = $this->changeDateToDate($data['month']);
+        $data['top_depart_id'] = $user['top_depart_id'];
+
+        $bool = Archive::where('del_time',0)
+            ->where('top_depart_id', $data['top_depart_id'])
+            ->where('month', $data['month'])
+            ->exists();
+
+        if($bool) return [false, "年月" . date("Y-m") . "已归档"];
+
+        return [true, ''];
+    }
+
+    public static function isArchive($months, $user)
+    {
+        // 1. 统一转为数组处理
+        $monthArray = is_array($months) ? $months : [$months];
+
+        // 2. 将所有传入的时间转换成“当月第一天”的时间戳并去重
+        $normalizedMonths = array_unique(array_map(function($time) {
+            // 如果传的是 2026-03 这种字符串,先转时间戳
+            $timestamp = is_numeric($time) ? $time : strtotime($time);
+            return strtotime(date('Y-m-01', $timestamp));
+        }, $monthArray));
+
+        // 3. 批量查询数据库中存在的已归档月份
+        $archivedMonths = Archive::where('del_time', 0)
+            ->where('top_depart_id', $user['top_depart_id'])
+            ->whereIn('month', $normalizedMonths)
+            ->pluck('month')
+            ->toArray();
+
+        // 4. 如果查询结果不为空,说明命中了归档
+        if (!empty($archivedMonths)) {
+            // 把命中的月份转回人类可读格式展示给用户
+            $errorMonths = array_map(function($ts) {
+                return date('Y-m', $ts);
+            }, $archivedMonths);
+
+            return [false, "操作失败:月份 [" . implode(',', $errorMonths) . "] 已归档锁定。"];
+        }
+
+        return [true, ''];
+    }
+}

+ 16 - 2
app/Service/AuxiliaryAccountService.php

@@ -139,7 +139,7 @@ class AuxiliaryAccountService extends Service
             $v['entrust2_amount'] = $v['entrust_type'] == 2 ?  $v['total_amount'] : 0;
             $v['entrust2_amount'] = $v['entrust_type'] == 2 ?  $v['total_amount'] : 0;
         }
         }
         ///分组
         ///分组
-        $fee_type_list = Fee::Clear($user,$data)->where('del_time',0)->select("title","id","parent_id")->get()->toArray();
+        $fee_type_list = Fee::TopClear($user,$data)->where('del_time',0)->select("title","id","parent_id")->get()->toArray();
 
 
         return [true,$this->groupListByRoot($list,$fee_type_list)];
         return [true,$this->groupListByRoot($list,$fee_type_list)];
     }
     }
@@ -264,6 +264,11 @@ class AuxiliaryAccountService extends Service
         $data['top_depart_id'] = $user['top_depart_id'];
         $data['top_depart_id'] = $user['top_depart_id'];
         if (empty($data['month'])) return [false, '月份不能为空'];
         if (empty($data['month'])) return [false, '月份不能为空'];
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         $monthStart = $data['month'];
         $monthStart = $data['month'];
         $monthEnd = strtotime('+1 month', $monthStart) - 1;
         $monthEnd = strtotime('+1 month', $monthStart) - 1;
         if(empty($data['details'])) return [false, '研发支出辅助账单明细不能为空'];
         if(empty($data['details'])) return [false, '研发支出辅助账单明细不能为空'];
@@ -372,13 +377,22 @@ class AuxiliaryAccountService extends Service
         return [true, ''];
         return [true, ''];
     }
     }
 
 
-    public function auxiliaryAccountDel($data){
+    public function auxiliaryAccountDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = AuxiliaryAccount::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             AuxiliaryAccount::where('del_time',0)
             AuxiliaryAccount::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);

+ 6 - 6
app/Service/CalendarService.php

@@ -95,11 +95,11 @@ class CalendarService extends Service
             'details' => $unit,
             'details' => $unit,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
@@ -148,7 +148,7 @@ class CalendarService extends Service
     public function calendarCommon($data,$user, $field = []){
     public function calendarCommon($data,$user, $field = []){
         if(empty($field)) $field = Calendar::$field;
         if(empty($field)) $field = Calendar::$field;
 
 
-        $model = Calendar::Clear($user,$data);
+        $model = Calendar::TopClear($user,$data);
         $model = $model->where('del_time',0)
         $model = $model->where('del_time',0)
             ->select($field)
             ->select($field)
             ->orderby('id', 'desc');
             ->orderby('id', 'desc');

+ 20 - 7
app/Service/DeviceDepreciationService.php

@@ -104,22 +104,31 @@ class DeviceDepreciationService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function monthlyDdOrderDel($data){
+    public function monthlyDdOrderDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = monthlyDdOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             monthlyDdOrder::where('del_time',0)
             monthlyDdOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -187,10 +196,14 @@ class DeviceDepreciationService extends Service
     }
     }
 
 
     public function monthlyDdOrderRule(&$data, $user, $is_add = true){
     public function monthlyDdOrderRule(&$data, $user, $is_add = true){
+        $data['top_depart_id'] = $user['top_depart_id'];
         if(empty($data['month'])) return [false, '月份不能为空'];
         if(empty($data['month'])) return [false, '月份不能为空'];
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
 
 
-        $data['top_depart_id'] = $user['top_depart_id'];
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         if(empty($data['details'])) return [false, '设备月度工时单明细不能为空'];
         if(empty($data['details'])) return [false, '设备月度工时单明细不能为空'];
         foreach ($data['details'] as $key => $value){
         foreach ($data['details'] as $key => $value){
             if(empty($value['device_id'])) return [false, '设备不能为空'];
             if(empty($value['device_id'])) return [false, '设备不能为空'];

+ 1 - 1
app/Service/DeviceService.php

@@ -105,7 +105,7 @@ class DeviceService extends Service
 
 
     public function deviceCommon($data,$user, $field = []){
     public function deviceCommon($data,$user, $field = []){
         if(empty($field)) $field = Device::$field;
         if(empty($field)) $field = Device::$field;
-        $model = Device::Clear($user,$data);
+        $model = Device::TopClear($user,$data);
         $model = $model->where('del_time',0)
         $model = $model->where('del_time',0)
             ->select($field)
             ->select($field)
             ->orderby('id', 'desc');
             ->orderby('id', 'desc');

+ 58 - 56
app/Service/DeviceWorkService.php

@@ -114,22 +114,31 @@ class DeviceWorkService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function monthlyDwOrderDel($data){
+    public function monthlyDwOrderDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = MonthlyDwOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             MonthlyDwOrder::where('del_time',0)
             MonthlyDwOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -202,6 +211,10 @@ class DeviceWorkService extends Service
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['top_depart_id'] = $user['top_depart_id'];
         $data['top_depart_id'] = $user['top_depart_id'];
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         if (empty($data['details'])) return [false, '设备月度工时单明细不能为空'];
         if (empty($data['details'])) return [false, '设备月度工时单明细不能为空'];
 
 
         // --- 1. 批量获取设备档案信息 (用于展示 [编码]名称) ---
         // --- 1. 批量获取设备档案信息 (用于展示 [编码]名称) ---
@@ -286,45 +299,6 @@ class DeviceWorkService extends Service
         return [true, ''];
         return [true, ''];
     }
     }
 
 
-    public function monthlyDwOrderRule1(&$data, $user, $is_add = true){
-        if(empty($data['month'])) return [false, '月份不能为空'];
-        $data['month'] = $this->changeDateToDate($data['month']);
-
-        $data['top_depart_id'] = $user['top_depart_id'];
-        if(empty($data['details'])) return [false, '设备月度工时单明细不能为空'];
-        foreach ($data['details'] as $key => $value){
-            if(empty($value['device_id'])) return [false, '设备不能为空'];
-            $res = $this->checkNumber($value['total_days'],0,'non-negative');
-            if(! $res['valid']) return [false,'出勤总天数:' . $res['error']];
-            $res = $this->checkNumber($value['rd_total_days'],0,'non-negative');
-            if(! $res['valid']) return [false,'研发出勤总天数:' . $res['error']];
-            $res = $this->checkNumber($value['total_hours'],2,'non-negative');
-            if(! $res['valid']) return [false,'出勤总工时:' . $res['error']];
-            $res = $this->checkNumber($value['rd_total_hours'],2,'non-negative');
-            if(! $res['valid']) return [false,'研发总工时:' . $res['error']];
-            $data['details'][$key]['top_depart_id'] = $data['top_depart_id'];
-        }
-        list($status, $msg) = $this->checkArrayRepeat($data['details'],'device_id','设备');
-        if(! $status) return [false, $msg];
-
-        if($is_add){
-            $bool = MonthlyDwOrder::where('top_depart_id', $data['top_depart_id'])
-                ->where('month', $data['month'])
-                ->where('del_time',0)
-                ->exists();
-        }else{
-            if(empty($data['id'])) return [false,'ID不能为空'];
-            $bool = MonthlyDwOrder::where('top_depart_id', $data['top_depart_id'])
-                ->where('month', $data['month'])
-                ->where('id','<>',$data['id'])
-                ->where('del_time',0)
-                ->exists();
-        }
-        if($bool) return [false, date("Y-m", $data['month']) . '已存在设备月度研发工时单'];
-
-        return [true, ''];
-    }
-
     public function fillData($data){
     public function fillData($data){
         if(empty($data['data'])) return $data;
         if(empty($data['data'])) return $data;
 
 
@@ -507,22 +481,31 @@ class DeviceWorkService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function dailyDwOrderDel($data){
+    public function dailyDwOrderDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = DailyDwOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('order_time')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             DailyDwOrder::where('del_time',0)
             DailyDwOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -581,7 +564,7 @@ class DeviceWorkService extends Service
             $model->where('crt_time','<=',$return[1]);
             $model->where('crt_time','<=',$return[1]);
         }
         }
         if (!empty($data['item_title'])) {
         if (!empty($data['item_title'])) {
-            $models = Item::Clear($user,$data);
+            $models = Item::TopClear($user,$data);
             $id = $models->where('del_time',0)
             $id = $models->where('del_time',0)
                 ->where('title', 'LIKE', '%'.$data['item_title'].'%')
                 ->where('title', 'LIKE', '%'.$data['item_title'].'%')
                 ->pluck('id')
                 ->pluck('id')
@@ -601,16 +584,20 @@ class DeviceWorkService extends Service
     }
     }
 
 
     public function dailyDwOrderRule(&$data, $user, $is_add = true){
     public function dailyDwOrderRule(&$data, $user, $is_add = true){
+        $data['top_depart_id'] = $user['top_depart_id'];
         if(empty($data['order_time'])) return [false, '单据日期不能为空'];
         if(empty($data['order_time'])) return [false, '单据日期不能为空'];
         $data['order_time'] = $this->changeDateToDate($data['order_time']);
         $data['order_time'] = $this->changeDateToDate($data['order_time']);
         $orderTime = $data['order_time'];
         $orderTime = $data['order_time'];
         $itemId = $data['item_id'] ?? 0;
         $itemId = $data['item_id'] ?? 0;
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['order_time'], $user);
+        if(! $status) return [false, $msg];
+
         if(empty($itemId)) return [false, '项目不能为空'];
         if(empty($itemId)) return [false, '项目不能为空'];
         $bool = Item::where('del_time',0)->where('id', $itemId)->exists();
         $bool = Item::where('del_time',0)->where('id', $itemId)->exists();
         if(!$bool) return [false, '项目不存在或已被删除'];
         if(!$bool) return [false, '项目不存在或已被删除'];
 
 
-        $data['top_depart_id'] = $user['top_depart_id'];
         if(empty($data['details'])) return [false, '设备日工时单明细不能为空'];
         if(empty($data['details'])) return [false, '设备日工时单明细不能为空'];
 
 
         // --- 1. 批量预获取人员信息,用于报错提示 ---
         // --- 1. 批量预获取人员信息,用于报错提示 ---
@@ -1036,6 +1023,10 @@ class DeviceWorkService extends Service
 
 
         $monthStart = $this->changeDateToDate($data['month']);
         $monthStart = $this->changeDateToDate($data['month']);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($monthStart, $user);
+        if(! $status) return [false, $msg];
+
         // 调用核心计算逻辑
         // 调用核心计算逻辑
         $result = $this->calculateDailyDeviceAllocation($monthStart, $topDepartId, $user);
         $result = $this->calculateDailyDeviceAllocation($monthStart, $topDepartId, $user);
 
 
@@ -1073,6 +1064,7 @@ class DeviceWorkService extends Service
             ->join('rule_set as r', 'r.id', '=', 'rd.main_id')
             ->join('rule_set as r', 'r.id', '=', 'rd.main_id')
             ->where('r.month', $monthStart)
             ->where('r.month', $monthStart)
             ->where('rd.type', RuleSetDetails::type_two) // 设备类型
             ->where('rd.type', RuleSetDetails::type_two) // 设备类型
+            ->where('rd.top_depart_id', $topDepartId)
             ->where('r.del_time', 0)
             ->where('r.del_time', 0)
             ->where('rd.del_time', 0)
             ->where('rd.del_time', 0)
             ->select('rd.*')
             ->select('rd.*')
@@ -1089,11 +1081,16 @@ class DeviceWorkService extends Service
 
 
         // 标准班次 & 日历 (逻辑同前)
         // 标准班次 & 日历 (逻辑同前)
         $standardWorkRanges = DB::table('work_range_details')
         $standardWorkRanges = DB::table('work_range_details')
-            ->where('top_depart_id', $topDepartId)->where('del_time', 0)->get();
+            ->where('top_depart_id', $topDepartId)
+            ->where('del_time', 0)
+            ->get();
         $dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
         $dayMaxAvail = (int)$standardWorkRanges->sum('total_work_min');
 
 
         $workDays = DB::table('calendar_details')
         $workDays = DB::table('calendar_details')
-            ->where('month', $monthStart)->where('is_work', 1)->where('del_time', 0)
+            ->where('top_depart_id', $topDepartId)
+            ->where('month', $monthStart)
+            ->where('is_work', 1)
+            ->where('del_time', 0)
             ->orderBy('time', 'asc')->get();
             ->orderBy('time', 'asc')->get();
 
 
         if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
         if ($workDays->isEmpty()) return ['status' => false, 'msg' => '未配置工作日历'];
@@ -1199,6 +1196,12 @@ class DeviceWorkService extends Service
 
 
         $topDepartId = $user['top_depart_id'];
         $topDepartId = $user['top_depart_id'];
         $month = $data['month']; // 格式如: "2026-03"
         $month = $data['month']; // 格式如: "2026-03"
+        $monthStart = $this->changeDateToDate($month);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($monthStart, $user);
+        if(! $status) return [false, $msg];
+
         $now = time();
         $now = time();
 
 
         // 1. 预加载映射
         // 1. 预加载映射
@@ -1218,7 +1221,6 @@ class DeviceWorkService extends Service
         DB::beginTransaction();
         DB::beginTransaction();
         try {
         try {
             // A. 清理旧数据
             // A. 清理旧数据
-            $monthStart = $this->changeDateToDate($month);
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
 
 
             $oldOrderIds = DB::table('daily_dw_order')
             $oldOrderIds = DB::table('daily_dw_order')

+ 11 - 6
app/Service/EmployeeService.php

@@ -859,7 +859,7 @@ class EmployeeService extends Service
         $model = $this->departCommon($data, $user);
         $model = $this->departCommon($data, $user);
 
 
         $list = $model->get()->toArray();
         $list = $model->get()->toArray();
-        $list = $this->fillDepartList($list, $user);
+        $list = $this->fillDepartList($list, $user, true);
         $list_tree = $list;
         $list_tree = $list;
         if(! empty($list_tree)) {
         if(! empty($list_tree)) {
             $minParentId = min(array_column($list_tree, 'parent_id'));
             $minParentId = min(array_column($list_tree, 'parent_id'));
@@ -871,13 +871,18 @@ class EmployeeService extends Service
     }
     }
 
 
     public function fillDepartList($list,$user, $is_export = false){
     public function fillDepartList($list,$user, $is_export = false){
+        if(isset($list['data'])){
+            $data = $list['data'];
+        }else{
+            $data = $list;
+        }
         if($is_export){
         if($is_export){
             $map = Depart::where('del_time',0)
             $map = Depart::where('del_time',0)
-                ->whereIn('id', array_column($list['data'], 'parent_id'))
+                ->whereIn('id', array_column($data, 'parent_id'))
                 ->select('code','id', 'title')
                 ->select('code','id', 'title')
                 ->get()->toArray();
                 ->get()->toArray();
             $map = array_column($map,null,'id');
             $map = array_column($map,null,'id');
-            foreach ($list['data'] as $key => $value){
+            foreach ($data as $key => $value){
                 $tmp = $map[$value['parent_id']] ?? "";
                 $tmp = $map[$value['parent_id']] ?? "";
                 if($tmp['code'] == $user['top_depart_code']) {
                 if($tmp['code'] == $user['top_depart_code']) {
                     $code = $title = "";
                     $code = $title = "";
@@ -885,12 +890,12 @@ class EmployeeService extends Service
                     $code = $tmp['code'];
                     $code = $tmp['code'];
                     $title = $tmp['title'];
                     $title = $tmp['title'];
                 }
                 }
-                $list['data'][$key]['parent_code'] = $code;
-                $list['data'][$key]['parent_title'] = $title;
+                $data[$key]['parent_code'] = $code;
+                $data[$key]['parent_title'] = $title;
             }
             }
         }
         }
 
 
-        return $list;
+        return $data;
     }
     }
 
 
 
 

+ 19 - 7
app/Service/ExpenseClaimsService.php

@@ -127,12 +127,15 @@ class ExpenseClaimsService extends Service
         $data['top_depart_id'] = $user['top_depart_id'];
         $data['top_depart_id'] = $user['top_depart_id'];
         if (empty($data['month'])) return [false, '月份不能为空'];
         if (empty($data['month'])) return [false, '月份不能为空'];
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
-//        if(!isset($data['month'])) return [false,"月份必传"];
-//        $monthStr = $data['month']; // 假设是 "2026-03"
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         $monthStart = $data['month'];
         $monthStart = $data['month'];
         // 获取该月最后一秒:下个月 1 号减去 1 秒
         // 获取该月最后一秒:下个月 1 号减去 1 秒
         $monthEnd = strtotime('+1 month', $monthStart) - 1;
         $monthEnd = strtotime('+1 month', $monthStart) - 1;
-        if(empty($data['details'])) return [false, '项目费用报销单详情不能为空'];
+        if(empty($data['details'])) return [false, '费用项目单详情不能为空'];
         foreach ($data['details'] as $index => $item) {
         foreach ($data['details'] as $index => $item) {
             if(empty($item['item_id'])) return [false, "第" . ($index + 1) . "行项目不能为空"];
             if(empty($item['item_id'])) return [false, "第" . ($index + 1) . "行项目不能为空"];
             if(empty($item['fee_id'])) return [false, "第" . ($index + 1) . "行费用类型不能为空"];
             if(empty($item['fee_id'])) return [false, "第" . ($index + 1) . "行费用类型不能为空"];
@@ -157,7 +160,7 @@ class ExpenseClaimsService extends Service
             $query->where('id', '<>', $data['id']);
             $query->where('id', '<>', $data['id']);
         }
         }
 
 
-        if ($query->exists())  return [false, date("Y-m", $monthStart) . '已存在项目费用报销单'];
+        if ($query->exists())  return [false, date("Y-m", $monthStart) . '已存在费用项目单'];
 
 
         return [true,""];
         return [true,""];
     }
     }
@@ -194,13 +197,22 @@ class ExpenseClaimsService extends Service
         return [true, ['file' => ['old' => $old, 'new' => $new]]];
         return [true, ['file' => ['old' => $old, 'new' => $new]]];
     }
     }
 
 
-    public function expenseClaimsDel($data){
+    public function expenseClaimsDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = ExpenseClaims::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             ExpenseClaims::where('del_time',0)
             ExpenseClaims::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -248,13 +260,13 @@ class ExpenseClaimsService extends Service
         $employee_ids = collect($data)->pluck('employee_id')->unique()->values()->all();
         $employee_ids = collect($data)->pluck('employee_id')->unique()->values()->all();
         $fee_ids = collect($data)->pluck('fee_id')->unique()->values()->all();
         $fee_ids = collect($data)->pluck('fee_id')->unique()->values()->all();
 
 
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_key_list = $item->whereIn('id',$item_ids)->pluck('title','id');
         $item_key_list = $item->whereIn('id',$item_ids)->pluck('title','id');
 
 
         $item = Employee::TopClear($user, $data);
         $item = Employee::TopClear($user, $data);
         $employee_key_list = $item->whereIn('id',$employee_ids)->pluck('title','id');
         $employee_key_list = $item->whereIn('id',$employee_ids)->pluck('title','id');
 
 
-        $item = Fee::Clear($user, $data);
+        $item = Fee::TopClear($user, $data);
         $fee_key_list = $item->whereIn('id',$fee_ids)->pluck('title','id');
         $fee_key_list = $item->whereIn('id',$fee_ids)->pluck('title','id');
 
 
         $fileUploadService = new FileUploadService();
         $fileUploadService = new FileUploadService();

+ 139 - 73
app/Service/ImportService.php

@@ -42,7 +42,7 @@ class ImportService extends Service
         'dailyDwOrder', // 设备日工时单
         'dailyDwOrder', // 设备日工时单
         'leaveOrder', // 请假单
         'leaveOrder', // 请假单
         'overtimeOrder', // 加班单
         'overtimeOrder', // 加班单
-        'feeOrder', // 项目费用报销
+        'feeOrder', // 费用项目
         'RDOrder', // 研发支出辅助帐
         'RDOrder', // 研发支出辅助帐
     ];
     ];
 
 
@@ -1425,9 +1425,15 @@ class ImportService extends Service
             $allMonthsTs[] = $valMonthTs;
             $allMonthsTs[] = $valMonthTs;
             if (!empty($row[$empIdx])) $allEmpNumbers[] = trim($row[$empIdx]);
             if (!empty($row[$empIdx])) $allEmpNumbers[] = trim($row[$empIdx]);
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
         $allMonthsTs = array_unique($allMonthsTs);
         $allMonthsTs = array_unique($allMonthsTs);
         $allEmpNumbers = array_unique($allEmpNumbers);
         $allEmpNumbers = array_unique($allEmpNumbers);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allMonthsTs, $user);
+        if(! $status)  return [$msg, [], []];
+
         // --- 2. 批量预加载 ---
         // --- 2. 批量预加载 ---
         // A. 人员档案
         // A. 人员档案
         $empModels = Employee::where('del_time', 0)->whereIn('number', $allEmpNumbers)
         $empModels = Employee::where('del_time', 0)->whereIn('number', $allEmpNumbers)
@@ -1674,8 +1680,14 @@ class ImportService extends Service
             $allMonthsTs[] = $valMonthTs;
             $allMonthsTs[] = $valMonthTs;
             if (!empty($row[$devIdx])) $allDevCodes[] = trim($row[$devIdx]);
             if (!empty($row[$devIdx])) $allDevCodes[] = trim($row[$devIdx]);
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
         $allMonthsTs = array_unique($allMonthsTs);
         $allMonthsTs = array_unique($allMonthsTs);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allMonthsTs, $user);
+        if(! $status)  return [$msg, [], []];
+
         // --- 2. 预加载档案与基准 ---
         // --- 2. 预加载档案与基准 ---
         $devModels = Device::where('del_time', 0)
         $devModels = Device::where('del_time', 0)
             ->whereIn('code', $allDevCodes)
             ->whereIn('code', $allDevCodes)
@@ -1950,18 +1962,22 @@ class ImportService extends Service
             $array[$rowIndex][$monthIdx] = $valMonthTs;
             $array[$rowIndex][$monthIdx] = $valMonthTs;
             $uniqueMonths[] = $valMonthTs;
             $uniqueMonths[] = $valMonthTs;
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
+        $allMonthsTs = array_unique($uniqueMonths);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allMonthsTs, $user);
+        if(! $status)  return [$msg, [], []];
 
 
         // 查询数据库中已存在的月份单据
         // 查询数据库中已存在的月份单据
-        $existingMonthsMap = [];
-        if (!empty($uniqueMonths)) {
-            $existingMonths = DB::table('monthly_ps_order')
-                ->where('top_depart_id', $user['top_depart_id'])
-                ->where('del_time', 0)
-                ->whereIn('month', array_unique($uniqueMonths))
-                ->pluck('month')
-                ->toArray();
-            $existingMonthsMap = array_fill_keys($existingMonths, true);
-        }
+        $existingMonths = DB::table('monthly_ps_order')
+            ->where('top_depart_id', $user['top_depart_id'])
+            ->where('del_time', 0)
+            ->whereIn('month', $allMonthsTs)
+            ->pluck('month')
+            ->toArray();
+        $existingMonthsMap = array_fill_keys($existingMonths, true);
 
 
         $excelAggregator = [];
         $excelAggregator = [];
         $update_map = [];
         $update_map = [];
@@ -2193,18 +2209,22 @@ class ImportService extends Service
             $array[$rowIndex][$monthIdx] = $valMonthTs;
             $array[$rowIndex][$monthIdx] = $valMonthTs;
             $uniqueMonths[] = $valMonthTs;
             $uniqueMonths[] = $valMonthTs;
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
+        $allMonthsTs = array_unique($uniqueMonths);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allMonthsTs, $user);
+        if(! $status)  return [$msg, [], []];
 
 
         // 预查数据库已存在的月份
         // 预查数据库已存在的月份
-        $existingMonthsMap = [];
-        if (!empty($uniqueMonths)) {
-            $existingMonths = DB::table('monthly_dd_order')
-                ->where('top_depart_id', $user['top_depart_id'])
-                ->where('del_time', 0)
-                ->whereIn('month', array_unique($uniqueMonths))
-                ->pluck('month')
-                ->toArray();
-            $existingMonthsMap = array_fill_keys($existingMonths, true);
-        }
+        $existingMonths = DB::table('monthly_dd_order')
+            ->where('top_depart_id', $user['top_depart_id'])
+            ->where('del_time', 0)
+            ->whereIn('month', $allMonthsTs)
+            ->pluck('month')
+            ->toArray();
+        $existingMonthsMap = array_fill_keys($existingMonths, true);
 
 
         $excelAggregator = [];
         $excelAggregator = [];
         $update_map = [];
         $update_map = [];
@@ -2380,13 +2400,19 @@ class ImportService extends Service
 
 
         // --- 步骤 1: 预处理扫描 ---
         // --- 步骤 1: 预处理扫描 ---
         foreach ($array as $rowIndex => $row) {
         foreach ($array as $rowIndex => $row) {
-            list($mStatus, $valMonthTs) = $this->convertExcelCellToDate($row[$monthIdx] ?? '');
-            if ($mStatus) {
-                $valMonthTs = strtotime(date('Y-m-01', $valMonthTs));
-                $array[$rowIndex][$monthIdx] = $valMonthTs;
-                $uniqueMonths[] = $valMonthTs;
+            $valMonthRaw = trim($row[$monthIdx] ?? '');
+            if ($valMonthRaw === '') continue;
+
+            list($mStatus, $valMonthTs) = $this->convertExcelCellToDate($valMonthRaw);
+            if (!$mStatus) {
+                $errors[] = "第" . ($rowIndex + 1) . "行:月份格式错误({$valMonthRaw})";
+                continue;
             }
             }
 
 
+            $valMonthTs = strtotime(date('Y-m-01', $valMonthTs));
+            $array[$rowIndex][$monthIdx] = $valMonthTs;
+            $uniqueMonths[] = $valMonthTs;
+
             $type = $type_map[$row[$typeIdx] ?? ''] ?? 0;
             $type = $type_map[$row[$typeIdx] ?? ''] ?? 0;
             $dCode = trim($row[$dCodeIdx] ?? '');
             $dCode = trim($row[$dCodeIdx] ?? '');
             $iCode = trim($row[$itemIdIdx] ?? '');
             $iCode = trim($row[$itemIdIdx] ?? '');
@@ -2396,6 +2422,14 @@ class ImportService extends Service
             if ($iCode !== '') $itemCodes[] = $iCode;
             if ($iCode !== '') $itemCodes[] = $iCode;
         }
         }
 
 
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
+        $allMonthsTs = array_unique($uniqueMonths);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allMonthsTs, $user);
+        if(! $status)  return [$msg, [], []];
+
         // --- 步骤 2: 批量预加载 ---
         // --- 步骤 2: 批量预加载 ---
         $dbEmps = Employee::where('del_time', 0)->where('top_depart_id', $user['top_depart_id'])
         $dbEmps = Employee::where('del_time', 0)->where('top_depart_id', $user['top_depart_id'])
             ->whereIn('number', array_unique($empCodes))->pluck('id', 'number')->toArray();
             ->whereIn('number', array_unique($empCodes))->pluck('id', 'number')->toArray();
@@ -2428,11 +2462,6 @@ class ImportService extends Service
             $valICode = trim($row[$itemIdIdx] ?? '');
             $valICode = trim($row[$itemIdIdx] ?? '');
             $valRate = $row[$rateIdx] ?? 0;
             $valRate = $row[$rateIdx] ?? 0;
 
 
-            if (!is_numeric($valMonthTs)) {
-                $errors[] = "第{$displayLine}行:月份格式非法";
-                continue;
-            }
-
             // A. 编辑/新增逻辑判定 (核心修正)
             // A. 编辑/新增逻辑判定 (核心修正)
             if ($valMCode !== '' && isset($dbOrders[$valMCode])) {
             if ($valMCode !== '' && isset($dbOrders[$valMCode])) {
                 $dbOrder = $dbOrders[$valMCode];
                 $dbOrder = $dbOrders[$valMCode];
@@ -2659,12 +2688,25 @@ class ImportService extends Service
 
 
         // --- 跨单据预查:提前解析日期并检索库内已存在的工时区间 ---
         // --- 跨单据预查:提前解析日期并检索库内已存在的工时区间 ---
         $allDates = [];
         $allDates = [];
-        foreach ($array as $row) {
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            if ($status) $allDates[] = strtotime(date('Y-m-d', $ts));
+        foreach ($array as $rowIndex => $row) {
+            $valMonthRaw = $row[$timeIdx] ?? '';
+            list($status, $ts) = $this->convertExcelCellToDate($valMonthRaw);
+            if(! $status) {
+                $errors[] = "第" . ($rowIndex + 1) . "行:单据日期格式错误({$valMonthRaw})";
+                continue;
+            }
+            $d = strtotime(date('Y-m-d', $ts));
+            $array[$rowIndex][$timeIdx] = $d;
+            $allDates[] = $d;
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], [], []];
+
         $allDates = array_unique($allDates);
         $allDates = array_unique($allDates);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allDates, $user);
+        if(! $status)  return [$msg, [], [], []];
+
         // 查询数据库:同公司、同日期、同项目、同人员的已有工时 (排除本次 Excel 涉及到的单号)
         // 查询数据库:同公司、同日期、同项目、同人员的已有工时 (排除本次 Excel 涉及到的单号)
         $dbExistingWork = DB::table('daily_pw_order_details as d')
         $dbExistingWork = DB::table('daily_pw_order_details as d')
             ->join('daily_pw_order as m', 'd.main_id', '=', 'm.id')
             ->join('daily_pw_order as m', 'd.main_id', '=', 'm.id')
@@ -2690,14 +2732,7 @@ class ImportService extends Service
         foreach ($array as $rowIndex => $row) {
         foreach ($array as $rowIndex => $row) {
             $displayLine = $rowIndex + 1;
             $displayLine = $rowIndex + 1;
 
 
-            // A. 日期预处理
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            if (!$status) {
-                $errors[] = "第{$displayLine}行:单据日期格式错误";
-                continue;
-            }
-            $ts = strtotime(date('Y-m-d', $ts));
-            $array[$rowIndex][$timeIdx] = $ts;
+            $ts = $row[$timeIdx];
 
 
             $valCode = trim($row[$codeIdx] ?? '');
             $valCode = trim($row[$codeIdx] ?? '');
             $valItemCode = trim($row[$itemIdx] ?? '');
             $valItemCode = trim($row[$itemIdx] ?? '');
@@ -2925,12 +2960,25 @@ class ImportService extends Service
 
 
         // 3. 跨单据预查
         // 3. 跨单据预查
         $allDates = [];
         $allDates = [];
-        foreach ($array as $row) {
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            if ($status) $allDates[] = strtotime(date('Y-m-d', $ts));
+        foreach ($array as $rowIndex => $row) {
+            $valMonthRaw = $row[$timeIdx] ?? '';
+            list($status, $ts) = $this->convertExcelCellToDate($valMonthRaw);
+            if(! $status) {
+                $errors[] = "第" . ($rowIndex + 1) . "行:单据日期格式错误({$valMonthRaw})";
+                continue;
+            }
+            $d = strtotime(date('Y-m-d', $ts));
+            $array[$rowIndex][$timeIdx] = $d;
+            $allDates[] = $d;
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], [], []];
+
         $allDates = array_unique($allDates);
         $allDates = array_unique($allDates);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allDates, $user);
+        if(! $status)  return [$msg, [], [], []];
+
         $dbExistingWork = DB::table('daily_dw_order_details as d')
         $dbExistingWork = DB::table('daily_dw_order_details as d')
             ->join('daily_dw_order as m', 'd.main_id', '=', 'm.id')
             ->join('daily_dw_order as m', 'd.main_id', '=', 'm.id')
             ->where('m.top_depart_id', $topDepartId)
             ->where('m.top_depart_id', $topDepartId)
@@ -2954,13 +3002,7 @@ class ImportService extends Service
         foreach ($array as $rowIndex => $row) {
         foreach ($array as $rowIndex => $row) {
             $displayLine = $rowIndex + 1;
             $displayLine = $rowIndex + 1;
 
 
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            if (!$status) {
-                $errors[] = "第{$displayLine}行:单据日期格式错误";
-                continue;
-            }
-            $ts = strtotime(date('Y-m-d', $ts));
-            $array[$rowIndex][$timeIdx] = $ts;
+            $ts = $row[$timeIdx];
 
 
             $valCode = trim($row[$codeIdx] ?? '');
             $valCode = trim($row[$codeIdx] ?? '');
             $valItemCode = trim($row[$itemIdx] ?? '');
             $valItemCode = trim($row[$itemIdx] ?? '');
@@ -3152,11 +3194,25 @@ class ImportService extends Service
 
 
         // --- 2. 日历 & 主表预查 (代码省略,保持原样) ---
         // --- 2. 日历 & 主表预查 (代码省略,保持原样) ---
         $allDateTs = [];
         $allDateTs = [];
-        foreach ($array as $row) {
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            if ($status) $allDateTs[] = strtotime(date('Y-m-d', $ts));
+        foreach ($array as $rowIndex => $row) {
+            $valMonthRaw = $row[$timeIdx] ?? '';
+            list($status, $ts) = $this->convertExcelCellToDate($valMonthRaw);
+            if(! $status) {
+                $errors[] = "第" . ($rowIndex + 1) . "行:单据日期格式错误({$valMonthRaw})";
+                continue;
+            }
+            $d = strtotime(date('Y-m-d', $ts));
+            $array[$rowIndex][$timeIdx] = $d;
+            $allDateTs[] = $d;
         }
         }
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
         $allDateTs = array_unique($allDateTs);
         $allDateTs = array_unique($allDateTs);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allDateTs, $user);
+        if(! $status)  return [$msg, [], []];
+
         $calendarMap = DB::table('calendar_details')->where('del_time', 0)->where('top_depart_id', $topDepartId)
         $calendarMap = DB::table('calendar_details')->where('del_time', 0)->where('top_depart_id', $topDepartId)
             ->whereIn('time', $allDateTs)->pluck('is_work', 'time')->toArray();
             ->whereIn('time', $allDateTs)->pluck('is_work', 'time')->toArray();
 
 
@@ -3197,14 +3253,7 @@ class ImportService extends Service
             $line = $rowIndex + 1;
             $line = $rowIndex + 1;
             $rowErrors = []; // 临时收集本行的所有错误
             $rowErrors = []; // 临时收集本行的所有错误
 
 
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            $ts = $status ? strtotime(date('Y-m-d', $ts)) : 0;
-            $array[$rowIndex][$timeIdx] = $ts;
-
-            if (!$ts) {
-                $errors[] = "第{$line}行:日期格式错误";
-                continue;
-            }
+            $ts = $row[$timeIdx];
 
 
             // 1. 单据与编辑逻辑检查
             // 1. 单据与编辑逻辑检查
             $valCode = trim($row[$codeIdx] ?? '');
             $valCode = trim($row[$codeIdx] ?? '');
@@ -3416,11 +3465,26 @@ class ImportService extends Service
 
 
         // 2. 日期、日历、主表预查
         // 2. 日期、日历、主表预查
         $allDateTs = [];
         $allDateTs = [];
-        foreach ($array as $row) {
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            if ($status) $allDateTs[] = strtotime(date('Y-m-d', $ts));
+        foreach ($array as $rowIndex => $row) {
+            $valMonthRaw = $row[$timeIdx] ?? '';
+            list($status, $ts) = $this->convertExcelCellToDate($valMonthRaw);
+            if(! $status) {
+                $errors[] = "第" . ($rowIndex + 1) . "行:单据日期格式错误({$valMonthRaw})";
+                continue;
+            }
+            $d = strtotime(date('Y-m-d', $ts));
+            $array[$rowIndex][$timeIdx] = $d;
+            $allDateTs[] = $d;
         }
         }
+
+        if (!empty($errors)) return [implode('|', $errors), [], []];
+
         $allDateTs = array_unique($allDateTs);
         $allDateTs = array_unique($allDateTs);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allDateTs, $user);
+        if(! $status)  return [$msg, [], []];
+
         $calendarMap = DB::table('calendar_details')->where('del_time', 0)->where('top_depart_id', $topDepartId)
         $calendarMap = DB::table('calendar_details')->where('del_time', 0)->where('top_depart_id', $topDepartId)
             ->whereIn('time', $allDateTs)->pluck('is_work', 'time')->toArray();
             ->whereIn('time', $allDateTs)->pluck('is_work', 'time')->toArray();
 
 
@@ -3461,11 +3525,7 @@ class ImportService extends Service
             $line = $rowIndex + 1;
             $line = $rowIndex + 1;
             $rowErrors = [];
             $rowErrors = [];
 
 
-            list($status, $ts) = $this->convertExcelCellToDate($row[$timeIdx] ?? '');
-            $ts = $status ? strtotime(date('Y-m-d', $ts)) : 0;
-            $array[$rowIndex][$timeIdx] = $ts;
-
-            if (!$ts) { $errors[] = "第{$line}行:日期格式错误"; continue; }
+            $ts = $row[$timeIdx];
 
 
             // A. 单据存在性逻辑
             // A. 单据存在性逻辑
             $valCode = trim($row[$codeIdx] ?? '');
             $valCode = trim($row[$codeIdx] ?? '');
@@ -3541,7 +3601,7 @@ class ImportService extends Service
         return [!empty($errors) ? implode('|', $errors) : "", $update_map, $dbEmps];
         return [!empty($errors) ? implode('|', $errors) : "", $update_map, $dbEmps];
     }
     }
 
 
-    // 项目费用报销单月度导入 ------------------------------
+    // 费用项目单月度导入 ------------------------------
     public function feeOrderImport($array, $user, $other_param)
     public function feeOrderImport($array, $user, $other_param)
     {
     {
         $upload = $array[0];
         $upload = $array[0];
@@ -3730,6 +3790,12 @@ class ImportService extends Service
 
 
         if (!empty($errors)) return [implode('|', $errors), [], []];
         if (!empty($errors)) return [implode('|', $errors), [], []];
 
 
+        $allMonthsTs = array_unique($allMonthsTs);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($allMonthsTs, $user);
+        if(! $status)  return [$msg, [], []];
+
         // --- 2. 批量预加载档案映射 ---
         // --- 2. 批量预加载档案映射 ---
         $dbEmps = DB::table('employee')->where('del_time', 0)->where('top_depart_id', $topDepartId)
         $dbEmps = DB::table('employee')->where('del_time', 0)->where('top_depart_id', $topDepartId)
             ->whereIn('number', array_unique($allEmpNos))->pluck('id', 'number')->toArray();
             ->whereIn('number', array_unique($allEmpNos))->pluck('id', 'number')->toArray();
@@ -3741,7 +3807,7 @@ class ImportService extends Service
             ->whereIn('code', array_unique($allFeeCodes))->pluck('id', 'code')->toArray();
             ->whereIn('code', array_unique($allFeeCodes))->pluck('id', 'code')->toArray();
 
 
         $existingMonthsMap = DB::table('expense_claims')->where('del_time', 0)->where('top_depart_id', $topDepartId)
         $existingMonthsMap = DB::table('expense_claims')->where('del_time', 0)->where('top_depart_id', $topDepartId)
-            ->whereIn('month', array_unique($allMonthsTs))->pluck('code', 'month')->toArray();
+            ->whereIn('month', $allMonthsTs)->pluck('code', 'month')->toArray();
 
 
         $dbOrdersByCode = DB::table('expense_claims')->where('del_time', 0)->where('top_depart_id', $topDepartId)
         $dbOrdersByCode = DB::table('expense_claims')->where('del_time', 0)->where('top_depart_id', $topDepartId)
             ->whereIn('code', array_unique($allCodes))->get()->keyBy('code');
             ->whereIn('code', array_unique($allCodes))->get()->keyBy('code');

+ 14 - 14
app/Service/ItemService.php

@@ -144,11 +144,11 @@ class ItemService extends Service
             'device_list' => $receipt,
             'device_list' => $receipt,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
@@ -210,7 +210,7 @@ class ItemService extends Service
     public function itemCommon($data,$user, $field = []){
     public function itemCommon($data,$user, $field = []){
         if(empty($field)) $field = Item::$field;
         if(empty($field)) $field = Item::$field;
 
 
-        $model = Item::Clear($user,$data);
+        $model = Item::TopClear($user,$data);
         $model = $model->where('del_time',0)
         $model = $model->where('del_time',0)
             ->select($field)
             ->select($field)
             ->orderby('id', 'desc');
             ->orderby('id', 'desc');
@@ -254,14 +254,14 @@ class ItemService extends Service
         }
         }
         list($status, $msg) = $this->checkArrayRepeat($data['man_list'],'data_id','人员');
         list($status, $msg) = $this->checkArrayRepeat($data['man_list'],'data_id','人员');
         if(! $status) return [false, $msg];
         if(! $status) return [false, $msg];
-        if(empty($data['device_list'])) return [false, '设备不能为空'];
-        foreach ($data['device_list'] as $key => $value){
-            if(empty($value['type'])) return [false, '类型不能为空'];
-            if(empty($value['data_id'])) return [false, '设备ID不能为空'];
-            $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
-        }
-        list($status, $msg) = $this->checkArrayRepeat($data['device_list'],'data_id','设备');
-        if(! $status) return [false, $msg];
+//        if(empty($data['device_list'])) return [false, '设备不能为空'];
+//        foreach ($data['device_list'] as $key => $value){
+//            if(empty($value['type'])) return [false, '类型不能为空'];
+//            if(empty($value['data_id'])) return [false, '设备ID不能为空'];
+//            $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
+//        }
+//        list($status, $msg) = $this->checkArrayRepeat($data['device_list'],'data_id','设备');
+//        if(! $status) return [false, $msg];
 
 
         if($is_add){
         if($is_add){
             $bool = Item::where('code',$data['code'])
             $bool = Item::where('code',$data['code'])

+ 19 - 6
app/Service/PLeaveOverService.php

@@ -113,22 +113,31 @@ class PLeaveOverService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function pLeaveOverDel($data){
+    public function pLeaveOverDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = PLeaveOverOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('order_time')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             PLeaveOverOrder::where('del_time',0)
             PLeaveOverOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -210,6 +219,10 @@ class PLeaveOverService extends Service
         $orderTime = $data['order_time'];
         $orderTime = $data['order_time'];
         $orderType = $data['type'];
         $orderType = $data['type'];
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['order_time'], $user);
+        if(! $status) return [false, $msg];
+
         if (!$is_add) {
         if (!$is_add) {
             if (empty($data['id'])) return [false, 'ID不能为空'];
             if (empty($data['id'])) return [false, 'ID不能为空'];
             $orderExists = DB::table('p_leave_over_order')
             $orderExists = DB::table('p_leave_over_order')

+ 20 - 6
app/Service/PersonSalaryService.php

@@ -104,22 +104,31 @@ class PersonSalaryService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function MonthlyPsOrderDel($data){
+    public function MonthlyPsOrderDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = MonthlyPsOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             MonthlyPsOrder::where('del_time',0)
             MonthlyPsOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -191,6 +200,11 @@ class PersonSalaryService extends Service
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
 
 
         $data['top_depart_id'] = $user['top_depart_id'];
         $data['top_depart_id'] = $user['top_depart_id'];
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         if(empty($data['details'])) return [false, '人员月度工时单明细不能为空'];
         if(empty($data['details'])) return [false, '人员月度工时单明细不能为空'];
         foreach ($data['details'] as $key => $value){
         foreach ($data['details'] as $key => $value){
             if(empty($value['employee_id'])) return [false, '人员不能为空'];
             if(empty($value['employee_id'])) return [false, '人员不能为空'];

+ 68 - 62
app/Service/PersonWorkService.php

@@ -113,22 +113,31 @@ class PersonWorkService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function monthlyPwOrderDel($data){
+    public function monthlyPwOrderDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = MonthlyPwOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             MonthlyPwOrder::where('del_time',0)
             MonthlyPwOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -201,6 +210,10 @@ class PersonWorkService extends Service
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['top_depart_id'] = $user['top_depart_id'];
         $data['top_depart_id'] = $user['top_depart_id'];
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         if (empty($data['details'])) return [false, '人员月度工时单明细不能为空'];
         if (empty($data['details'])) return [false, '人员月度工时单明细不能为空'];
 
 
         //获取系统计算的考勤基准数据 ---
         //获取系统计算的考勤基准数据 ---
@@ -266,46 +279,6 @@ class PersonWorkService extends Service
         return [true, ''];
         return [true, ''];
     }
     }
 
 
-    public function monthlyPwOrderRule1(&$data, $user, $is_add = true){
-        if(empty($data['month'])) return [false, '月份不能为空'];
-        $data['month'] = $this->changeDateToDate($data['month']);
-
-        $data['top_depart_id'] = $user['top_depart_id'];
-        if(empty($data['details'])) return [false, '人员月度工时单明细不能为空'];
-        foreach ($data['details'] as $key => $value){
-            if(empty($value['employee_id'])) return [false, '人员不能为空'];
-            $res = $this->checkNumber($value['total_days'],0,'non-negative');
-            if(! $res['valid']) return [false,'出勤总天数:' . $res['error']];
-            $res = $this->checkNumber($value['rd_total_days'],0,'non-negative');
-            if(! $res['valid']) return [false,'研发出勤总天数:' . $res['error']];
-            $res = $this->checkNumber($value['total_hours'],2,'non-negative');
-            if(! $res['valid']) return [false,'出勤总工时:' . $res['error']];
-            $res = $this->checkNumber($value['rd_total_hours'],2,'non-negative');
-            if(! $res['valid']) return [false,'研发总工时:' . $res['error']];
-
-            $data['details'][$key]['top_depart_id'] = $data['top_depart_id'];
-        }
-        list($status, $msg) = $this->checkArrayRepeat($data['details'],'employee_id','人员');
-        if(! $status) return [false, $msg];
-
-        if($is_add){
-            $bool = MonthlyPwOrder::where('top_depart_id', $data['top_depart_id'])
-                ->where('month', $data['month'])
-                ->where('del_time',0)
-                ->exists();
-        }else{
-            if(empty($data['id'])) return [false,'ID不能为空'];
-            $bool = MonthlyPwOrder::where('top_depart_id', $data['top_depart_id'])
-                ->where('month', $data['month'])
-                ->where('id','<>',$data['id'])
-                ->where('del_time',0)
-                ->exists();
-        }
-        if($bool) return [false, date("Y-m", $data['month']) . '已存在人员月度研发工时单'];
-
-        return [true, ''];
-    }
-
     public function fillData($data){
     public function fillData($data){
         if(empty($data['data'])) return $data;
         if(empty($data['data'])) return $data;
 
 
@@ -489,22 +462,31 @@ class PersonWorkService extends Service
             'details' => $data,
             'details' => $data,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function dailyPwOrderDel($data){
+    public function dailyPwOrderDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = DailyPwOrder::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('order_time')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             DailyPwOrder::where('del_time',0)
             DailyPwOrder::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -563,7 +545,7 @@ class PersonWorkService extends Service
             $model->where('crt_time','<=',$return[1]);
             $model->where('crt_time','<=',$return[1]);
         }
         }
         if (!empty($data['item_title'])) {
         if (!empty($data['item_title'])) {
-            $models = Item::Clear($user,$data);
+            $models = Item::TopClear($user,$data);
             $id = $models->where('del_time',0)
             $id = $models->where('del_time',0)
                 ->where('title', 'LIKE', '%'.$data['item_title'].'%')
                 ->where('title', 'LIKE', '%'.$data['item_title'].'%')
                 ->pluck('id')
                 ->pluck('id')
@@ -583,16 +565,20 @@ class PersonWorkService extends Service
     }
     }
 
 
     public function dailyPwOrderRule(&$data, $user, $is_add = true){
     public function dailyPwOrderRule(&$data, $user, $is_add = true){
+        $data['top_depart_id'] = $user['top_depart_id'];
         if(empty($data['order_time'])) return [false, '单据日期不能为空'];
         if(empty($data['order_time'])) return [false, '单据日期不能为空'];
         $data['order_time'] = $this->changeDateToDate($data['order_time']);
         $data['order_time'] = $this->changeDateToDate($data['order_time']);
         $orderTime = $data['order_time'];
         $orderTime = $data['order_time'];
         $itemId = $data['item_id'] ?? 0;
         $itemId = $data['item_id'] ?? 0;
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['order_time'], $user);
+        if(! $status) return [false, $msg];
+
         if(empty($itemId)) return [false, '项目不能为空'];
         if(empty($itemId)) return [false, '项目不能为空'];
         $bool = Item::where('del_time',0)->where('id', $itemId)->exists();
         $bool = Item::where('del_time',0)->where('id', $itemId)->exists();
         if(!$bool) return [false, '项目不存在或已被删除'];
         if(!$bool) return [false, '项目不存在或已被删除'];
 
 
-        $data['top_depart_id'] = $user['top_depart_id'];
         if(empty($data['details'])) return [false, '人员日工时单明细不能为空'];
         if(empty($data['details'])) return [false, '人员日工时单明细不能为空'];
 
 
         // --- 1. 批量预获取人员信息,用于报错提示 ---
         // --- 1. 批量预获取人员信息,用于报错提示 ---
@@ -1048,6 +1034,10 @@ class PersonWorkService extends Service
         // 1. 前置校验 (保留你之前的校验逻辑)
         // 1. 前置校验 (保留你之前的校验逻辑)
         $monthStart = $this->changeDateToDate($data['month']);
         $monthStart = $this->changeDateToDate($data['month']);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($monthStart, $user);
+        if(! $status) return [false, $msg];
+
         // 1. 检查是否存在月度工时明细
         // 1. 检查是否存在月度工时明细
         $hasMonthlyOrder = DB::table('monthly_pw_order_details as d')
         $hasMonthlyOrder = DB::table('monthly_pw_order_details as d')
             ->join('monthly_pw_order as m', 'm.id', '=', 'd.main_id')
             ->join('monthly_pw_order as m', 'm.id', '=', 'd.main_id')
@@ -1148,12 +1138,23 @@ class PersonWorkService extends Service
             ->groupBy('data_id');
             ->groupBy('data_id');
 
 
         // 加载员工/标准班次、日历、请假加班数据 (逻辑同前)
         // 加载员工/标准班次、日历、请假加班数据 (逻辑同前)
-        $empWorkRanges = DB::table('employee_work_range')->whereIn('employee_id', $empIds)->where('top_depart_id', $topDepartId)->get()->groupBy('employee_id');
-        $standardWorkRanges = DB::table('work_range_details')->where('top_depart_id', $topDepartId)->where('del_time', 0)->get();
-        $allDays = DB::table('calendar_details')->where('month', $monthStart)->where('del_time', 0)->orderBy('time', 'asc')->get();
+        $empWorkRanges = DB::table('employee_work_range')
+            ->whereIn('employee_id', $empIds)
+            ->where('top_depart_id', $topDepartId)
+            ->get()->groupBy('employee_id');
+        $standardWorkRanges = DB::table('work_range_details')->where('top_depart_id', $topDepartId)
+            ->where('del_time', 0)->get();
+        $allDays = DB::table('calendar_details')->where('top_depart_id', $topDepartId)
+            ->where('month', $monthStart)
+            ->where('del_time', 0)
+            ->orderBy('time', 'asc')
+            ->get();
         $leaveOverData = DB::table('p_leave_over_order_details as d')->join('p_leave_over_order as m', 'd.main_id', '=', 'm.id')
         $leaveOverData = DB::table('p_leave_over_order_details as d')->join('p_leave_over_order as m', 'd.main_id', '=', 'm.id')
-            ->whereBetween('m.order_time', [$monthStart, $monthEnd])->where('m.del_time', 0)
-            ->select('d.*', 'm.order_time', 'm.type as main_type')->get()->groupBy(['employee_id', 'order_time']);
+            ->whereBetween('m.order_time', [$monthStart, $monthEnd])
+            ->where('d.top_depart_id', $topDepartId)
+            ->where('m.del_time', 0)
+            ->select('d.*', 'm.order_time', 'm.type as main_type')
+            ->get()->groupBy(['employee_id', 'order_time']);
 
 
         // --- 2. 阶段一:计算每个人每天在每个项目上应分配的整数分钟数 ---
         // --- 2. 阶段一:计算每个人每天在每个项目上应分配的整数分钟数 ---
         $finalAlloc = [];
         $finalAlloc = [];
@@ -1254,7 +1255,13 @@ class PersonWorkService extends Service
         if (empty($list)) return [false, '没有可保存的数据'];
         if (empty($list)) return [false, '没有可保存的数据'];
 
 
         $topDepartId = $user['top_depart_id'];
         $topDepartId = $user['top_depart_id'];
-        $month = $data['month']; // 格式如: "2026-03"
+        $month = $data['month'];
+        $monthStart = $this->changeDateToDate($month);
+
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($monthStart, $user);
+        if(! $status) return [false, $msg];
+
         $now = time();
         $now = time();
 
 
         // 1. 预加载员工名称映射 (使用 title 字段)
         // 1. 预加载员工名称映射 (使用 title 字段)
@@ -1276,7 +1283,6 @@ class PersonWorkService extends Service
         DB::beginTransaction();
         DB::beginTransaction();
         try {
         try {
             // A. 清理该月份旧数据
             // A. 清理该月份旧数据
-            $monthStart = $this->changeDateToDate($month);
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
             $monthEnd = strtotime('+1 month', $monthStart) - 1;
 
 
             $oldOrderIds = DB::table('daily_pw_order')
             $oldOrderIds = DB::table('daily_pw_order')
@@ -1370,7 +1376,7 @@ class PersonWorkService extends Service
             }
             }
 
 
             DB::commit();
             DB::commit();
-            return [true, '保存成功'];
+            return [true, ''];
         } catch (\Exception $e) {
         } catch (\Exception $e) {
             DB::rollBack();
             DB::rollBack();
             return [false, "保存失败:" . $e->getMessage()];
             return [false, "保存失败:" . $e->getMessage()];

+ 37 - 23
app/Service/RuleSetService.php

@@ -159,22 +159,31 @@ class RuleSetService extends Service
             'device_list' => $receipt,
             'device_list' => $receipt,
         ];
         ];
 
 
-        foreach ($detail as $key => $value) {
-            if (empty($value)) {
-                $detail[$key] = (object)[]; // 转成 stdClass 对象
-            }
-        }
+        //foreach ($detail as $key => $value) {
+           // if (empty($value)) {
+                //$detail[$key] = (object)[]; // 转成 stdClass 对象
+            //}
+        //}
 
 
         return $detail;
         return $detail;
     }
     }
 
 
-    public function ruleSetDel($data){
+    public function ruleSetDel($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
 
 
         try {
         try {
             DB::beginTransaction();
             DB::beginTransaction();
             $time = time();
             $time = time();
 
 
+            $month = RuleSet::where('del_time',0)
+                ->whereIn('id',$data['id'])
+                ->pluck('month')
+                ->toArray();
+
+            //归档
+            list($status, $msg) = ArchiveService::isArchive($month, $user);
+            if(! $status) return [false, $msg];
+
             RuleSet::where('del_time',0)
             RuleSet::where('del_time',0)
                 ->whereIn('id',$data['id'])
                 ->whereIn('id',$data['id'])
                 ->update(['del_time' => $time]);
                 ->update(['del_time' => $time]);
@@ -247,6 +256,10 @@ class RuleSetService extends Service
         if (empty($data['month'])) return [false, '月份不能为空'];
         if (empty($data['month'])) return [false, '月份不能为空'];
         $data['month'] = $this->changeDateToDate($data['month']);
         $data['month'] = $this->changeDateToDate($data['month']);
 
 
+        //归档
+        list($status, $msg) = ArchiveService::isArchive($data['month'], $user);
+        if(! $status) return [false, $msg];
+
         // --- 0. 批量预加载档案用于错误提示 (核心优化点) ---
         // --- 0. 批量预加载档案用于错误提示 (核心优化点) ---
         $manIds = array_unique(array_column($data['man_list'] ?? [], 'data_id'));
         $manIds = array_unique(array_column($data['man_list'] ?? [], 'data_id'));
         $devIds = array_unique(array_column($data['device_list'] ?? [], 'data_id'));
         $devIds = array_unique(array_column($data['device_list'] ?? [], 'data_id'));
@@ -283,27 +296,28 @@ class RuleSetService extends Service
         }
         }
 
 
         // --- 2. 设备列表校验 ---
         // --- 2. 设备列表校验 ---
-        if (empty($data['device_list'])) return [false, '设备不能为空'];
-        $deviceRates = [];
-        foreach ($data['device_list'] as $key => $value) {
-            if (empty($value['type'])) return [false, '类型不能为空'];
-            if (empty($value['data_id'])) return [false, '设备ID不能为空'];
-            if (empty($value['item_id'])) return [false, '项目不能为空'];
+        if (! empty($data['device_list'])){
+            $deviceRates = [];
+            foreach ($data['device_list'] as $key => $value) {
+                if (empty($value['type'])) return [false, '类型不能为空'];
+                if (empty($value['data_id'])) return [false, '设备ID不能为空'];
+                if (empty($value['item_id'])) return [false, '项目不能为空'];
 
 
-            $res = $this->checkNumber($value['rate'], 2, 'non-negative');
-            if (!$res['valid']) return [false, '设备工时分摊比例:' . $res['error']];
+                $res = $this->checkNumber($value['rate'], 2, 'non-negative');
+                if (!$res['valid']) return [false, '设备工时分摊比例:' . $res['error']];
 
 
-            $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
+                $data['device_list'][$key]['top_depart_id'] = $data['top_depart_id'];
 
 
-            $devId = $value['data_id'];
-            $deviceRates[$devId] = ($deviceRates[$devId] ?? 0) + $value['rate'];
-        }
+                $devId = $value['data_id'];
+                $deviceRates[$devId] = ($deviceRates[$devId] ?? 0) + $value['rate'];
+            }
 
 
-        // 校验设备比例 (错误提示加入设备名称)
-        foreach ($deviceRates as $dId => $total) {
-            if (abs($total - 100) > 0.0001) {
-                $displayName = $devMap[$dId] ?? "ID:{$dId}";
-                return [false, "设备{$displayName}的分摊比例合计为{$total}%,必须等于100%"];
+            // 校验设备比例 (错误提示加入设备名称)
+            foreach ($deviceRates as $dId => $total) {
+                if (abs($total - 100) > 0.0001) {
+                    $displayName = $devMap[$dId] ?? "ID:{$dId}";
+                    return [false, "设备{$displayName}的分摊比例合计为{$total}%,必须等于100%"];
+                }
             }
             }
         }
         }
 
 

+ 13 - 13
app/Service/StatisticService.php

@@ -50,10 +50,10 @@ class StatisticService extends Service
         $item_ids = $dataCollection->pluck('item_id')->unique()->values()->all();
         $item_ids = $dataCollection->pluck('item_id')->unique()->values()->all();
         $employee_ids = $dataCollection->pluck('employee_id')->unique()->values()->all();
         $employee_ids = $dataCollection->pluck('employee_id')->unique()->values()->all();
 
 
-        $employee = Employee::Clear($user, $data);
+        $employee = Employee::TopClear($user, $data);
         $employee_key_list = $employee->wherein('id', $employee_ids)->pluck("title", "id")->toArray();
         $employee_key_list = $employee->wherein('id', $employee_ids)->pluck("title", "id")->toArray();
 
 
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_title_key_list = $item->wherein('id', $item_ids)->pluck("title", "id")->toArray();
         $item_title_key_list = $item->wherein('id', $item_ids)->pluck("title", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $item_ids)->pluck("code", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $item_ids)->pluck("code", "id")->toArray();
         $collect = collect($month_employee_list);
         $collect = collect($month_employee_list);
@@ -187,7 +187,7 @@ class StatisticService extends Service
         $collect = collect($item_month_list);
         $collect = collect($item_month_list);
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
 
 
@@ -342,13 +342,13 @@ class StatisticService extends Service
 
 
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
 
 
         $employee_ids = collect($item_month_list)->pluck('employee_id')->unique()->values()->all();
         $employee_ids = collect($item_month_list)->pluck('employee_id')->unique()->values()->all();
 
 
-        $employee = Employee::Clear($user, $data);
+        $employee = Employee::TopClear($user, $data);
         $employee_key_list = $employee->wherein('id', $employee_ids)->pluck("title", "id")->toArray();
         $employee_key_list = $employee->wherein('id', $employee_ids)->pluck("title", "id")->toArray();
 
 
         $item_month_list = collect($item_month_list)->transform(function ($item, $index) use ($item_title_key_list, $item_code_key_list, $employee_key_list, &$total_work_min, &$all_salary, &$employee_count) {
         $item_month_list = collect($item_month_list)->transform(function ($item, $index) use ($item_title_key_list, $item_code_key_list, $employee_key_list, &$total_work_min, &$all_salary, &$employee_count) {
@@ -464,13 +464,13 @@ class StatisticService extends Service
         }
         }
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
 
 
         $device_ids = collect($item_month_list)->pluck('device_id')->unique()->values()->all();
         $device_ids = collect($item_month_list)->pluck('device_id')->unique()->values()->all();
 
 
-        $device = Device::Clear($user, $data);
+        $device = Device::TopClear($user, $data);
         $device_key_list = $device->wherein('id', $device_ids)->pluck("title", "id")->toArray();
         $device_key_list = $device->wherein('id', $device_ids)->pluck("title", "id")->toArray();
         $device_original_value_key_list = $device->wherein('id', $device_ids)->pluck("original_value", "id")->toArray();
         $device_original_value_key_list = $device->wherein('id', $device_ids)->pluck("original_value", "id")->toArray();
 
 
@@ -576,7 +576,7 @@ class StatisticService extends Service
             return [false, $month_start];
             return [false, $month_start];
         }
         }
         //第一步确定项目
         //第一步确定项目
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_list = $item->where('del_time', 0)
         $item_list = $item->where('del_time', 0)
             ->where(function ($query) use ($month_start, $month_end) {
             ->where(function ($query) use ($month_start, $month_end) {
                 $query->where('start_time', '<=', $month_start)
                 $query->where('start_time', '<=', $month_start)
@@ -829,7 +829,7 @@ class StatisticService extends Service
                 "entrust_type"
                 "entrust_type"
             )->get()->toArray();
             )->get()->toArray();
         //需要根据分类去汇总
         //需要根据分类去汇总
-        $fee = Fee::Clear($user, $data);
+        $fee = Fee::TopClear($user, $data);
         $fee = $fee->where('del_time', 0)->orderBy("sort", 'desc')->get()->toArray();
         $fee = $fee->where('del_time', 0)->orderBy("sort", 'desc')->get()->toArray();
         return $this->groupListByRoot($expense_list, $fee);
         return $this->groupListByRoot($expense_list, $fee);
     }
     }
@@ -924,7 +924,7 @@ class StatisticService extends Service
         //项目编码、项目名称、项目状态、凭证日期、凭证种类、凭证号数、凭证摘要、会计凭证归集金额、N个一级费用类型、委内、委外
         //项目编码、项目名称、项目状态、凭证日期、凭证种类、凭证号数、凭证摘要、会计凭证归集金额、N个一级费用类型、委内、委外
 
 
         //确认所有项目
         //确认所有项目
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_list = $item->where('del_time', 0)
         $item_list = $item->where('del_time', 0)
             ->where(function ($query) use ($month_start, $month_end) {
             ->where(function ($query) use ($month_start, $month_end) {
                 $query->where('start_time', '<=', $month_start)
                 $query->where('start_time', '<=', $month_start)
@@ -937,7 +937,7 @@ class StatisticService extends Service
         //获取该区间内所有项目人工费、折旧费
         //获取该区间内所有项目人工费、折旧费
         $item_salary = $this->auxiliaryEmployee($user, $data, $month_start, $month_end);
         $item_salary = $this->auxiliaryEmployee($user, $data, $month_start, $month_end);
         $device_depreciation = $this->auxiliaryDevice($user, $data, $month_start, $month_end);
         $device_depreciation = $this->auxiliaryDevice($user, $data, $month_start, $month_end);
-        $fee = Fee::Clear($user, $data);
+        $fee = Fee::TopClear($user, $data);
         $fee = $fee->where('del_time', 0)->orderBy("sort", 'desc')->get()->toArray();
         $fee = $fee->where('del_time', 0)->orderBy("sort", 'desc')->get()->toArray();
         $auxiliary = AuxiliaryAccountDetails::Clear($user, $data);
         $auxiliary = AuxiliaryAccountDetails::Clear($user, $data);
         $auxiliary_list = $auxiliary->where("voucher_date", ">=", $month_start)->where("voucher_date", "<", $month_end)
         $auxiliary_list = $auxiliary->where("voucher_date", ">=", $month_start)->where("voucher_date", "<", $month_end)
@@ -1339,13 +1339,13 @@ class StatisticService extends Service
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $item_month_list = collect($item_month_list)->sortBy('month')->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
         $items = collect($item_month_list)->pluck('item_id')->unique()->values()->all();
         $employee_ids = collect($item_month_list)->pluck('employee_id')->unique()->values()->all();
         $employee_ids = collect($item_month_list)->pluck('employee_id')->unique()->values()->all();
-        $employee = Employee::Clear($user, $data);
+        $employee = Employee::TopClear($user, $data);
         $employee_list = $employee->wherein('id', $employee_ids)->select("major", "title", "id")->get()->toArray();
         $employee_list = $employee->wherein('id', $employee_ids)->select("major", "title", "id")->get()->toArray();
         $employee_key_list = [];
         $employee_key_list = [];
         foreach ($employee_list as $v) {
         foreach ($employee_list as $v) {
             $employee_key_list[$v['id']] = $v;
             $employee_key_list[$v['id']] = $v;
         }
         }
-        $item = Item::Clear($user, $data);
+        $item = Item::TopClear($user, $data);
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
         $item_code_key_list = $item->wherein('id', $items)->pluck("code", "id")->toArray();
         //项目编码、项目名称、姓名、人员类别、应出勤工时、研发出勤工时、研发工时占比、归集工资总额、归集社保金额、归集公积金、研发工资总额、研发社保金额、研发公积金
         //项目编码、项目名称、姓名、人员类别、应出勤工时、研发出勤工时、研发工时占比、归集工资总额、归集社保金额、归集公积金、研发工资总额、研发社保金额、研发公积金

+ 1 - 1
config/excel/feeOrder.php

@@ -1,6 +1,6 @@
 <?php
 <?php
 return [
 return [
-    "name" => "项目费用报销单",
+    "name" => "费用项目单",
     "array" => [
     "array" => [
         [
         [
             'key' =>'code',
             'key' =>'code',

+ 5 - 0
routes/api.php

@@ -155,6 +155,11 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('calendarDel', 'Api\CalendarController@calendarDel');
     $route->any('calendarDel', 'Api\CalendarController@calendarDel');
     $route->any('calendarDetail', 'Api\CalendarController@calendarDetail');
     $route->any('calendarDetail', 'Api\CalendarController@calendarDetail');
 
 
+    //归档
+    $route->any('archiveList', 'Api\ArchiveController@archiveList');
+    $route->any('archiveAdd', 'Api\ArchiveController@archiveAdd');
+    $route->any('archiveDel', 'Api\ArchiveController@archiveDel');
+
     //工时设置 暂时后台写死数据 toDo
     //工时设置 暂时后台写死数据 toDo
 
 
     //请假单 加班单
     //请假单 加班单