cqp il y a 2 mois
Parent
commit
5b4817f9ba

+ 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);
+        }
+    }
+}

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

@@ -2,10 +2,319 @@
 
 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
 {
+    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'];
+}

+ 94 - 0
app/Service/ArchiveService.php

@@ -0,0 +1,94 @@
+<?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, ''];
+    }
+}

+ 5 - 0
routes/api.php

@@ -155,6 +155,11 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('calendarDel', 'Api\CalendarController@calendarDel');
     $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
 
     //请假单 加班单