cqp 2 săptămâni în urmă
părinte
comite
32866d5400

+ 13 - 0
app/Http/Controllers/Api/StatisticController.php

@@ -145,4 +145,17 @@ class StatisticController extends BaseController
         }
     }
 
+    public function employeeMonthSalaryStatisticCount(Request $request)
+    {
+        $service = new StatisticService();
+        $user = $request->userData;
+        list($status,$data) = $service->employeeMonthSalaryStatisticCount($request->all(),$user);
+
+        if($status){
+            return $this->json_return(200,'',$data);
+        }else{
+            return $this->json_return(201,$data);
+        }
+    }
+
 }

+ 82 - 0
app/Jobs/ProcessDeviceZjTask.php

@@ -0,0 +1,82 @@
+<?php
+
+namespace App\Jobs;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
+
+class ProcessDeviceZjTask implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    public $timeout = 120;
+
+    /**
+     * 接收传入的设备月度折旧单单号数组
+     */
+    protected $ids;
+
+    /**
+     * @param array $codes 例如:['1', '2']
+     */
+    public function __construct(array $ids)
+    {
+        $this->ids = $ids;
+    }
+
+    public function handle()
+    {
+        if (empty($this->ids)) {
+            return;
+        }
+
+        try {
+            $mainIds = $this->ids;
+
+            $affectedDeviceIds = DB::table('monthly_dd_order_details')
+                ->whereIn('main_id', $mainIds)
+                ->where('del_time', 0)
+                ->pluck('device_id')
+                ->unique() // 去重
+                ->toArray();
+
+            if (empty($affectedDeviceIds)) return;
+
+            // 3. 【核心改变】:脱离单号限制!直接去查这些设备在全表里“所有的”历史折旧总和
+            $globalDepreciationMap = DB::table('monthly_dd_order_details')
+                ->select('device_id', DB::raw('SUM(depreciation_amount) as total_amount'))
+                ->whereIn('device_id', $affectedDeviceIds)
+                ->where('del_time', 0)
+                ->groupBy('device_id')
+                ->pluck('total_amount', 'device_id') // 生成 [设备ID => 历史所有折旧累计总额]
+                ->toArray();
+
+            // 4. 分批更新到设备表中
+            $chunkSize = 100;
+            $chunks = array_chunk($affectedDeviceIds, $chunkSize);
+
+            foreach ($chunks as $chunkDeviceIds) {
+                DB::transaction(function () use ($chunkDeviceIds, $globalDepreciationMap) {
+                    foreach ($chunkDeviceIds as $deviceId) {
+                        // 拿到该设备有史以来所有的折旧总和(如果没有查到说明被删光了,默认为 0)
+                        $totalAmount = (float)($globalDepreciationMap[$deviceId] ?? 0);
+
+                        DB::table('device')
+                            ->where('id', $deviceId)
+                            ->update([
+                                'total_depreciation' => $totalAmount, // 绝对总额直接覆盖
+                            ]);
+                    }
+                });
+            }
+
+        } catch (\Throwable $e) {
+            $this->delete();
+        }
+    }
+}

+ 51 - 2
app/Model/DataScopeBaseModel.php

@@ -44,7 +44,7 @@ class DataScopeBaseModel extends Model
     }
 
     //数据权限中  人员 部门 所有 (在公司的基础上)
-    public function scopeClear($query, $user, $search)
+    public function scopeClear1($query, $user, $search)
     {
         //权限范围内的部门
         $depart_range = $user['depart_id'] ?? [];
@@ -60,7 +60,7 @@ class DataScopeBaseModel extends Model
         $this->makeModel($query, $auth_type, $user, $depart_range,$column);
     }
 
-    private function makeModel(&$query, $auth_type, $user, $depart_range, $column){
+    private function makeModel1(&$query, $auth_type, $user, $depart_range, $column){
         $query->where('top_depart_id', $user['top_depart_id']);
 
         if(empty($column)) return;
@@ -83,6 +83,55 @@ class DataScopeBaseModel extends Model
         }
     }
 
+    public function scopeClear($query, $user, $search)
+    {
+        // 权限范围内的部门
+        $depart_range = $user['depart_id'] ?? [];
+        // 个人 部门 所有
+        $auth_type = $this->getQx($search, $user);
+        // 获取模型的实例
+        $model = $query->getModel();
+        // 获取模型类名
+        $className = get_class($model);
+
+        // 🆕 核心修复 1:动态获取当前主表的表名,用来给字段加前缀防止别名冲突
+        $tableName = $model->getTable();
+
+        // 人员字段
+        $column = defined($className . '::employee_column') ? constant($className . '::employee_column') : '';
+
+        // 🆕 核心修复 2:如果定义了人员字段,且没有带表前缀,自动加上主表前缀
+        if (!empty($column) && strpos($column, '.') === false) {
+            $column = $tableName . '.' . $column;
+        }
+
+        $this->makeModel($query, $auth_type, $user, $depart_range, $column, $tableName);
+    }
+
+    private function makeModel(&$query, $auth_type, $user, $depart_range, $column, $tableName) {
+        // 🆕 核心修复 3:给 top_depart_id 加上主表名前缀,防止关联表也有该字段导致冲突
+        $query->where($tableName . '.top_depart_id', $user['top_depart_id']);
+
+        if (empty($column)) return;
+
+        if ($auth_type == Employee::AUTH_ONE) {
+            // 我创建的 (此时 $column 已经是 "table_name.field" 格式)
+            $query->where($column, $user['id']);
+        } elseif ($auth_type == Employee::AUTH_TWO) {
+            if (empty($depart_range)) {
+                $query->whereRaw('1 = 0');
+            } else {
+                $query->whereExists(function ($q) use ($column, $depart_range) {
+                    $q->from('employee_depart_permission')
+                        ->whereColumn('employee_depart_permission.employee_id', $column) // 这里的 $column 带有表前缀,whereColumn 完美识别
+                        ->whereIn('employee_depart_permission.depart_id', $depart_range);
+                });
+            }
+        } elseif ($auth_type == Employee::AUTH_THREE) {
+            // 所有
+        }
+    }
+
     //根据公司过滤 加人员
     public function scopeTopAndEmployeeClear($query, $user, $search)
     {

+ 9 - 1
app/Model/Device.php

@@ -15,7 +15,7 @@ class Device extends DataScopeBaseModel
         2 => '否',
     ];
 
-    public static $field = ['position','title','id','code','crt_id','crt_time','size','mark','is_use','type','power', 'in_time', 'original_value', 'initial_value'];
+    public static $field = ['position','title','id','code','crt_id','crt_time','size','mark','is_use','type','power', 'in_time', 'original_value', 'initial_value', 'device_type', 'total_depreciation'];
 
     const type_one = 1;
     const type_two = 2;
@@ -26,4 +26,12 @@ class Device extends DataScopeBaseModel
         self::type_two => '机器设备',
         self::type_three => '办公设备',
     ];
+
+    const device_type_zero = 0;
+    const device_type_one = 1;
+
+    public static $device_type = [
+        self::device_type_zero => '专用设备',
+        self::device_type_one => '公用设备',
+    ];
 }

+ 14 - 0
app/Model/DeviceDepartDetails.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Model;
+
+use Illuminate\Database\Eloquent\Model;
+
+class DeviceDepartDetails extends Model
+{
+    protected $guarded = [];
+    protected $table = "device_depart_details"; //指定表
+    const CREATED_AT = 'crt_time';
+    const UPDATED_AT = 'upd_time';
+    protected $dateFormat = 'U';
+}

+ 1 - 1
app/Model/Fee.php

@@ -13,7 +13,7 @@ class Fee extends DataScopeBaseModel
     protected $dateFormat = 'U';
     const IS_UES = 1;//启用
 
-    public static $field = ['title','id','code','is_use','parent_id','is_other'];
+    public static $field = ['title','id','code','is_use','parent_id','is_other','sort'];
 
     const IS_OTHER_ZERO = 0;
     const IS_OTHER_ONE = 1;

+ 16 - 0
app/Service/DeviceDepreciationService.php

@@ -2,6 +2,7 @@
 
 namespace App\Service;
 
+use App\Jobs\ProcessDeviceZjTask;
 use App\Model\Device;
 use App\Model\Employee;
 use App\Model\MonthlyDdOrder;
@@ -28,6 +29,9 @@ class DeviceDepreciationService extends Service
             $this->saveDetail($model->id, $time, $data);
 
             DB::commit();
+
+            //触发折旧计算
+            $this->triggerJob($model->id);
         }catch (\Exception $exception){
             DB::rollBack();
             return [false,$exception->getMessage()];
@@ -57,6 +61,9 @@ class DeviceDepreciationService extends Service
             $this->saveDetail($model->id, time(), $data);
 
             DB::commit();
+
+            //触发折旧计算
+            $this->triggerJob($model->id);
         }catch (\Exception $exception){
             DB::rollBack();
             return [false,$exception->getMessage()];
@@ -138,6 +145,9 @@ class DeviceDepreciationService extends Service
                 ->update(['del_time' => $time]);
 
             DB::commit();
+
+            //触发折旧计算
+            $this->triggerJob($data['id']);
         }catch (\Exception $exception){
             DB::rollBack();
             return [false,$exception->getMessage()];
@@ -146,6 +156,12 @@ class DeviceDepreciationService extends Service
         return [true, ''];
     }
 
+    public function triggerJob($id){
+        if(! is_array($id)) $id = [$id];
+
+        ProcessDeviceZjTask::dispatch($id)->onQueue("count_device_zj");
+    }
+
     public function monthlyDdOrderDetail($data, $user){
         if($this->isEmpty($data,'id')) return [false,'请选择数据!'];
         $customer = monthlyDdOrder::where('del_time',0)

+ 61 - 0
app/Service/DeviceService.php

@@ -3,6 +3,8 @@
 namespace App\Service;
 
 use App\Model\CalendarDetails;
+use App\Model\Depart;
+use App\Model\DeviceDepartDetails;
 use App\Model\Employee;
 use App\Model\Device;
 use Illuminate\Support\Facades\DB;
@@ -28,8 +30,15 @@ class DeviceService extends Service
             $model->position = $data['position'] ?? "";
             $model->original_value = $data['original_value'] ?? 0;
             $model->initial_value = $data['initial_value'] ?? 0;
+            $model->device_type = $data['device_type'] ?? 0;
             $model->save();
 
+            $time = time();
+            DeviceDepartDetails::where('del_time',0)
+                ->where('main_id', $model->id)
+                ->update(['del_time' => $time]);
+            $this->saveDetail($model->id, $time, $data);
+
             DB::commit();
         }catch (\Exception $exception){
             DB::rollBack();
@@ -58,10 +67,13 @@ class DeviceService extends Service
             $model->position = $data['position'] ?? "";
             $model->original_value = $data['original_value'] ?? 0;
             $model->initial_value = $data['initial_value'] ?? 0;
+            $model->device_type = $data['device_type'] ?? 0;
             $model->top_depart_id = $data['top_depart_id'] ?? 0;
             $model->crt_id = $user['id'];
             $model->save();
 
+            $this->saveDetail($model->id, time(), $data);
+
             DB::commit();
         }catch (\Exception $exception){
             DB::rollBack();
@@ -71,6 +83,46 @@ class DeviceService extends Service
         return [true, ''];
     }
 
+    private function saveDetail($id, $time, $data){
+        if(! empty($data['details'])){
+            $unit = [];
+            foreach ($data['details'] as $value){
+                $unit[] = [
+                    'main_id' => $id,
+                    'depart_id' => $value,
+                    'crt_time' => $time,
+                    'top_depart_id' => $value['top_depart_id'],
+                ];
+            }
+            if(! empty($unit)) DeviceDepartDetails::insert($unit);
+        }
+    }
+
+    private function getDetail($id){
+        $data = DeviceDepartDetails::where('del_time',0)
+            ->where('main_id', $id)
+            ->select('depart_id', 'main_id')
+            ->get()->toArray();
+
+        $id = array_column($data,'depart_id');
+        $map = Depart::whereIn('id', $id)->select('title','id','code')->get()->toArray();
+        $map = array_column($map,null,'id');
+
+        foreach ($data as $key => $value){
+            $tmp = $map[$value['main_id']] ?? [];
+            $merge = [];
+            $merge['depart_title'] = $tmp['title'];
+            $merge['depart_code'] = $tmp['code'];
+            $data[$key] = array_merge($value, $merge);
+        }
+
+        $detail = [
+            'details' => $data,
+        ];
+
+        return $detail;
+    }
+
     public function deviceDel($data){
         if($this->isEmpty($data,'id')) return [false,'请选择数据'];
 
@@ -82,6 +134,10 @@ class DeviceService extends Service
                 ->whereIn('id', $data['id'])
                 ->update(['del_time' => $time]);
 
+            DeviceDepartDetails::where('del_time',0)
+                ->where('main_id', $data['id'])
+                ->update(['del_time' => $time]);
+
             DB::commit();
         }catch (\Exception $exception){
             DB::rollBack();
@@ -100,8 +156,12 @@ class DeviceService extends Service
         $customer = $customer->toArray();
         $customer['crt_name'] = Employee::where('id',$customer['crt_id'])->value('title');
         $customer['crt_time'] = $customer['crt_time'] ? date("Y-m-d H:i:s",$customer['crt_time']): '';
+        $customer['use_year'] = $customer['in_time'] ? $this->getDiffYearsFromNow($customer['in_time']) : 0;
         $customer['in_time'] = $customer['in_time'] ? date("Y-m-d",$customer['in_time']): '';
 
+        $details = $this->getDetail($data['id']);
+        $customer = array_merge($customer, $details);
+
         return [true, $customer];
     }
 
@@ -142,6 +202,7 @@ class DeviceService extends Service
         if(! isset(Device::Use[$data['is_use']])) return [false, '是否启用错误'];
         if(empty($data['type'])) return [false, '固定资产类型不能为空'];
         if(! isset(Device::$type[$data['type']])) return [false, '固定资产类型错误'];
+        if(! isset(Device::$device_type[$data['device_type']])) return [false, '设备标签错误'];
         if(! empty($data['in_time'])) $data['in_time'] = $this->changeDateToDate($data['in_time']);
         if(! empty($data['original_value'])){
             $res = $this->checkNumber($data['original_value'],0,'positive');

+ 17 - 9
app/Service/ExportFileService.php

@@ -239,7 +239,7 @@ class ExportFileService extends Service
         return [true, $this->saveExportData($return,$header)];
     }
 
-    public function monthPsOrder1($ergs,$user){
+    public function monthPsOrder($ergs,$user){
         // 导出数据
         $return = [];
         $header_default = $user['e_header_default'];
@@ -257,7 +257,7 @@ class ExportFileService extends Service
         return [true, $this->saveExportData($return,$header)];
     }
 
-    public function monthPsOrder($ergs, $user)
+    public function monthPsOrderCount($ergs, $user)
     {
         $service = new PersonSalaryService();
         // 1. 获取主表查询模型
@@ -283,14 +283,14 @@ class ExportFileService extends Service
                     $empKey = $sub['employee_number'] . '_' . $sub['employee_title'];
 
                     // 计算当前月份该员工的总薪资 = 基本 + 绩效 + 奖金 + 其他
-                    $totalSalary = (float)$sub['base_salary']
-                        + (float)$sub['performance_salary']
-                        + (float)$sub['bonus']
-                        + (float)$sub['other'];
+                    $totalSalary = (float)($sub['base_salary'] ?? 0)
+                        + (float)($sub['performance_salary'] ?? 0)
+                        + (float)($sub['bonus'] ?? 0)
+                        + (float)($sub['other'] ?? 0);
 
                     // 归入矩阵:如果该年该人该月已经有值,做累加(防止单月重复发薪单)
                     if (!isset($yearlyData[$year][$empKey][$month])) {
-                        $yearlyData[$year][$empKey][$month] = 0;
+                        $yearlyData[$year][$empKey][$month] = 0.00;
                     }
                     $yearlyData[$year][$empKey][$month] += $totalSalary;
                 }
@@ -301,13 +301,21 @@ class ExportFileService extends Service
             return [false, '没有可导出的数据'];
         }
 
-        // 3. 排序:年份按从小到大,员工按工号排序
+        // 3. 排序并统一格式化金额为两位小数
         ksort($yearlyData);
         foreach ($yearlyData as $year => &$emps) {
             ksort($emps); // 员工按工号等 Key 排序
+
+            // ✨【核心修改】:遍历当前年份下的所有员工和月份,统一将累加完的最终金额保留2位小数
+            foreach ($emps as $empKey => &$months) {
+                foreach ($months as $month => $totalSalary) {
+                    $months[$month] = number_format($totalSalary, 2, '.', '');
+                }
+            }
         }
+        unset($emps); // 释放引用避免后续潜在干扰
 
-        $file_name = "人员月工资单统计表_" . date("Y-m-d") . "_". rand(1000,9999);
+        $file_name = "人员月工资单统计表_" . date("Y-m-d") . "_". rand(1000, 9999);
         $filename =  $file_name . '.' . 'xlsx';
 
         $bool =  Excel::store(new MonthlyPsMatrixExport($yearlyData), "/public/export/{$filename}", null, 'Xlsx', []);

+ 2 - 0
app/Service/FeeService.php

@@ -31,6 +31,7 @@ class FeeService extends Service
                 $model->title = $value['title'];
                 $model->code = $value['code'];
                 $model->is_other = $value['is_other'] ?? Fee::IS_OTHER_ZERO;
+                $model->sort = $value['sort'] ?? 0;
                 $model->top_depart_id = $value['top_depart_id'];
                 $model->save();
             }
@@ -70,6 +71,7 @@ class FeeService extends Service
         $model = Fee::TopClear($user,$data);
         $model = $model->where('del_time',0)
             ->select($field)
+            ->orderby('sort', 'asc')
             ->orderby('id', 'asc');
 
         if(isset($data['parent_id'])) $model->where('parent_id', $data['parent_id']);

+ 15 - 0
app/Service/ImportService.php

@@ -750,6 +750,7 @@ class ImportService extends Service
         $codeIdx = array_search('code', array_column($table_config, 'key'));
         $dateIdx = array_search('in_time', array_column($table_config, 'key'));
         $typeIdx = array_search('type', array_column($table_config, 'key'));
+        $deviceTypeIdx = array_search('device_type', array_column($table_config, 'key'));
         $type2Idx = array_search('is_use', array_column($table_config, 'key'));
 
         $code_map = $this->getDeviceList($array, $user, $codeIdx);
@@ -759,6 +760,7 @@ class ImportService extends Service
 
         $map_type = array_flip(Device::$type);
         $map_type_2 = array_flip(Device::Use);
+        $map_type_3 = array_flip(Device::$device_type);
         foreach ($array as $rowIndex => $value) {
             $displayLine = $rowIndex + 1;
 
@@ -774,6 +776,11 @@ class ImportService extends Service
             }else{
                 $array[$rowIndex][$typeIdx] = $map_type[$value[$typeIdx]];
             }
+            if(empty($map_type_3[$value[$deviceTypeIdx]])){
+                $errors[] = "第{$displayLine}行设备标签错误";
+            }else{
+                $array[$rowIndex][$typeIdx] = $map_type_3[$value[$deviceTypeIdx]];
+            }
             if(empty($map_type_2[$value[$type2Idx]])){
                 $errors[] = "第{$displayLine}行是否启用错误";
             }else{
@@ -2196,6 +2203,8 @@ class ImportService extends Service
         DB::beginTransaction();
         try {
             $time = time();
+
+            $id = [];
             foreach ($groups as $aggKey => $group) {
                 $mainId = $group['main_id'];
 
@@ -2233,12 +2242,18 @@ class ImportService extends Service
                     $insertDetails[] = $detail;
                 }
 
+                if(! in_array($mainId, $id)) $id[] = $mainId;
+
                 if (!empty($insertDetails)) {
                     DB::table('monthly_dd_order_details')->insert($insertDetails);
                 }
             }
 
             DB::commit();
+
+            //触发折旧计算
+            (new DeviceDepreciationService())->triggerJob($id);
+
         } catch (\Exception $e) {
             DB::rollBack();
             return [false, "失败:" . $e->getMessage() . " (行号:" . $e->getLine() . ")"];

+ 40 - 0
app/Service/Service.php

@@ -3,6 +3,7 @@
 namespace App\Service;
 
 
+use Carbon\Carbon;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Redis;
 
@@ -502,4 +503,43 @@ class Service
 
         return $dateTime->getTimestamp(); // 推荐使用 getTimestamp() 而非 strtotime
     }
+
+    /**
+     * 计算传入时间戳与当前时间相差的完整年数
+     * @param int $timestamp 传入的时间戳
+     * @return int 相差的年数(向下取整,不满一年返回 0)
+     */
+    public function getDiffYearsFromNow(int $timestamp): int
+    {
+        // 1. 使用 Laravel 自带的 Carbon 库,分别解析传入时间和当前时间
+        $passedTime = Carbon::createFromTimestamp($timestamp);
+        $now = Carbon::now(); // 自动获取当前系统时间(例如:2026年5月)
+
+        // 2. 直接使用 Carbon 自带的 diffInYears 方法
+        // 该方法会自动处理闰年、大小月,并且默认返回的是“满几年”
+        return $passedTime->diffInYears($now);
+    }
+
+    public function getBatchDiffYears(array $timestamps, bool $absolute = true): array
+    {
+        if (empty($timestamps)) return [];
+
+        $now = Carbon::now(); // 当前时间 (2026年5月)
+        $result = [];
+
+        foreach ($timestamps as $ts) {
+            if(empty($ts)) continue;
+            $passedTime = Carbon::createFromTimestamp((int)$ts);
+
+            if ($absolute) {
+                // 逻辑 A:绝对满年(满365天)
+                $result[$ts] = $passedTime->diffInYears($now);
+            } else {
+                // 逻辑 B:自然年差(只看年份数字相减,比如 2026 - 2025 = 1)
+                $result[$ts] = $now->year - $passedTime->year;
+            }
+        }
+
+        return $result;
+    }
 }

+ 109 - 3
app/Service/StatisticService.php

@@ -5,7 +5,9 @@ namespace App\Service;
 use App\Model\AuxiliaryAccountDetails;
 use App\Model\DailyDwOrderDetails;
 use App\Model\DailyPwOrderDetails;
+use App\Model\Depart;
 use App\Model\Device;
+use App\Model\DeviceDepartDetails;
 use App\Model\Employee;
 use App\Model\EmployeeDepartPermission;
 use App\Model\ExpenseClaimsDetails;
@@ -230,11 +232,31 @@ class StatisticService extends StatisticCommonService
         $item = Item::TopClear($user, $data);
         $item_title_key_list = $item->wherein('id', $items)->pluck("title", "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 = Device::TopClear($user, $data);
-        $device_key_list = $device->wherein('id', $device_ids)->pluck("title", "id")->toArray();
+        $devices = $device->whereIn('id', $device_ids)
+            ->get(['id', 'title', 'total_depreciation', 'in_time', 'device_type']);
+        $timestamps = $devices->pluck('in_time')->unique()->toArray();
+        $yearsMap = $this->getBatchDiffYears($timestamps);
+        $depart_map = $this->getDepart($devices->pluck('id')->unique()->toArray());
+
+        $device_key_list = [];
+        foreach ($devices as $d) {
+            $useYear = $d->in_time ? $yearsMap[$d->in_time] : 0;
+            $depart_title = $depart_map[$d->id] ?? "";
+
+            $device_key_list[$d->id] = [
+                'id'           => $d->id,
+                'title'        => $d->title,
+                'now_depreciation' => $d->total_depreciation,
+                'in_time'      => $d->in_time,
+                'device_type_title'  => Device::$device_type[$d->device_type] ?? "",
+                'use_year'     => $useYear,
+                'depart_title'     => $depart_title,
+            ];
+        }
+//        $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();
 
         $collect = collect($item_month_list);
@@ -273,7 +295,12 @@ class StatisticService extends StatisticCommonService
         $item_month_list = collect($item_month_list)->transform(function ($item) use ($item_title_key_list, $item_code_key_list, $device_key_list, $device_original_value_key_list, &$device_total_depreciation, &$device_counts,&$rate_list,$word_keys) {
             $item['item_title'] = $item_title_key_list[$item['item_id']] ?? "未知项目({$item['item_id']})";
             $item['item_code'] = $item_code_key_list[$item['item_id']] ?? "未知项目({$item['item_id']})";
-            $item['device_title'] = $device_key_list[$item['device_id']] ?? "未知人员({$item['device_id']})";
+            $tmp = $device_key_list[$item['device_id']] ?? [];
+            $item['device_title'] = $tmp['title'] ?? "";
+            $item['device_type_title'] = $tmp['device_type_title'] ?? "";
+            $item['use_year'] = $tmp['use_year'] ?? 0;
+            $item['depart_title'] = $tmp['depart_title'] ?? "";
+            $item['now_depreciation'] = $tmp['now_depreciation'] ?? 0;
             $item['allocated_depreciatio'] = $item['allocated_depreciation'];
             $item['total_depreciatio'] =  round($item['total_depreciation']/100,2);
             $item['device_original'] = $device_original_value_key_list[$item['device_id']] ?? "未知人员({$item['device_id']})";
@@ -287,6 +314,34 @@ class StatisticService extends StatisticCommonService
         return [true, $item_month_list];
     }
 
+    public function getDepart($id){
+        $details = DeviceDepartDetails::where('del_time', 0)
+            ->whereIn('main_id', $id)
+            ->select(['main_id as device_id', 'depart_id'])
+            ->get();
+        $departIds = $details->pluck('depart_id')->unique()->toArray();
+        $departMap = Depart::whereIn('id', $departIds)
+            ->pluck('title', 'id')
+            ->toArray();
+
+        $result = [];
+
+        foreach ($details as $value) {
+            $deviceId = $value['device_id'];
+            $departId = $value['depart_id'];
+
+            $t = $departMap[$departId] ?? '';
+            if(empty($t)) continue;
+
+            if(isset($result[$deviceId])){
+                $result[$deviceId] .= ',' . $t;
+            }else{
+                $result[$deviceId] = $t;
+            }
+        }
+
+        return $result;
+    }
 
     public function employeeAttendanceMonthStatistic($data, $user)
     {
@@ -1112,4 +1167,55 @@ class StatisticService extends StatisticCommonService
 
         return $list;
     }
+
+    public function employeeMonthSalaryStatisticCountCommon($data,$user){
+        $model = MonthlyPsOrder::Clear($user,$data);
+        $model->leftJoin('monthly_ps_order_details as b', 'b.main_id', 'monthly_ps_order.id')
+            ->where('monthly_ps_order.del_time',0)
+            ->where('b.del_time',0)
+            ->select('monthly_ps_order.month', 'b.employee_id', 'b.base_salary','b.performance_salary','b.bonus','b.other')
+            ->orderby('monthly_ps_order.month','desc');
+
+        if(! empty($data['time'][0]) && ! empty($data['time'][1])) {
+            $return = $this->changeDateToTimeStampAboutRange($data['time']);
+            $model->where('monthly_ps_order.month','>=',$return[0]);
+            $model->where('monthly_ps_order.month','<=',$return[1]);
+        }
+
+        if(! empty($data['employee_title'])){
+            $model_2 = Employee::TopClear($user,$data);
+            $id = $model_2->where('del_time',0)
+                ->where('title', 'LIKE', '%'.$data['employee_title'].'%')
+                ->pluck('id')
+                ->toArray();
+            $model->whereIn('b.employee_id', $id);
+        }
+
+        return $model;
+    }
+
+    public function employeeMonthSalaryStatisticCount($data, $user){
+        $model = $this->employeeMonthSalaryStatisticCountCommon($data, $user);
+        $list = $this->limit($model,'',$data);
+        $list = $this->fillEmployeeMonthSalaryStatisticCount($list, $data, $user);
+
+        return [true, $list];
+    }
+
+    public function fillEmployeeMonthSalaryStatisticCount($data, $ergs, $user){
+        if(empty($data['data'])) return $data;
+
+        $emp = (new EmployeeService())->getEmployeeMap(array_unique(array_column($data['data'],'employee_id')));
+        foreach ($data['data'] as $key => $value){
+            $data['data'][$key]['month'] = $value['month'] ? date('Y-m',$value['month']) : '';
+            $data['data'][$key]['employee_title'] = $emp[$value['employee_id']] ?? '';
+            $totalSalary = (float)($value['base_salary'] ?? 0)
+                + (float)($value['performance_salary'] ?? 0)
+                + (float)($value['bonus'] ?? 0)
+                + (float)($value['other'] ?? 0);
+            $data['data'][$key]['total_salary'] = number_format($totalSalary, 2, '.', '');
+        }
+
+        return $data;
+    }
 }

+ 11 - 0
config/excel/device.php

@@ -35,6 +35,17 @@ return [
             'enums' => array_values(\App\Model\Device::$type),
             'comments' => '必填'
         ],
+        [
+            'key' =>'device_type',
+            'export' =>'device_type_title',
+            'value' => '设备标签',
+            'required' => true,
+            'is_main' => true,
+            'default' => 0,
+            'unique' => false,
+            'enums' => array_values(\App\Model\Device::$device_type),
+            'comments' => '必填'
+        ],
         [
             'key' =>'in_time',
             'export' =>'in_time',

+ 2 - 1
routes/api.php

@@ -281,7 +281,8 @@ Route::group(['middleware'=> ['checkLogin']],function ($route){
     $route->any('enterpriseRdManStatistic', 'Api\StatisticController@enterpriseRdManStatistic');
     //企业研发开发活动汇总表
     $route->any('enterpriseRdItemStatistic', 'Api\StatisticController@enterpriseRdItemStatistic');
-
+    //人员月度工资
+    $route->any('employeeMonthSalaryStatisticCount', 'Api\StatisticController@employeeMonthSalaryStatisticCount');
 
     //首页BI数据
     $route->any('homePageData', 'Api\BIController@homePageData');