Kaynağa Gözat

公司初始化

cqp 1 ay önce
ebeveyn
işleme
5a5d9d40e2
1 değiştirilmiş dosya ile 109 ekleme ve 0 silme
  1. 109 0
      app/Service/StatisticService.php

+ 109 - 0
app/Service/StatisticService.php

@@ -525,6 +525,115 @@ class StatisticService extends StatisticCommonService
     }
 
     public function itemDeviceMonthStatistic($data, $user)
+    {
+        // 1. 基础校验与时间初始化
+        list($status, $month_start, $month_end) = $this->commonRule($data);
+        if (!$status) return [false, $month_start];
+
+        // 2. 获取设备工时数据 (项目+设备+月)
+        $month_device_list = DailyDwOrderDetails::Clear($user, $data)
+            ->where("order_time", ">=", $month_start)
+            ->where("order_time", "<", $month_end)
+            ->where('del_time', 0)
+            ->select(
+                "item_id",
+                "device_id",
+                DB::raw("FROM_UNIXTIME(order_time, '%Y-%m') as order_month"),
+                DB::raw("SUM(total_work_min) as total_work")
+            )
+            ->groupBy(DB::raw("FROM_UNIXTIME(order_time, '%Y-%m')"), "item_id", "device_id")->get()->toArray();
+
+        // 3. 获取折旧费主表及详情
+        $monthly_dd_query = MonthlyDdOrder::Clear($user, $data)->where('del_time', 0)
+            ->where("month", ">=", $month_start)->where("month", "<", $month_end);
+
+        $monthly_dd_ids = $monthly_dd_query->pluck('id')->toArray();
+        $monthly_dd_months = $monthly_dd_query->select('id', DB::raw("FROM_UNIXTIME(month, '%Y-%m') as month_str"))
+            ->pluck("month_str", 'id')->toArray();
+
+        $device_salary_details = MonthlyDdOrderDetails::wherein('main_id', $monthly_dd_ids)
+            ->select("device_id", "depreciation_amount", "main_id")->get()->toArray();
+
+        // 4. 构建高精度折旧池 (单位:分)
+        $depreciation_pool = [];
+        foreach ($device_salary_details as $val) {
+            $m = $monthly_dd_months[$val['main_id']] ?? '';
+            if ($m) {
+                $key = $val['device_id'] . '_' . $m;
+                // 同一个设备在同一个月可能存在多条折旧记录,需累加
+                $depreciation_pool[$key] = ($depreciation_pool[$key] ?? 0) + (int)round($val['depreciation_amount'] * 100);
+            }
+        }
+
+        // 5. 计算全月总工时及初始化余额池
+        $device_monthly_total_min = [];
+        foreach ($month_device_list as $row) {
+            $key = $row['device_id'] . '_' . $row['order_month'];
+            $device_monthly_total_min[$key] = ($device_monthly_total_min[$key] ?? 0) + $row['total_work'];
+        }
+
+        $rem_depreciation_cents = $depreciation_pool; // 折旧余额池
+        $rem_hours_cents = []; // 工时余额池 (小时*100)
+        foreach ($device_monthly_total_min as $key => $min) {
+            $rem_hours_cents[$key] = (int)round(($min / 60), 2) * 100;
+        }
+
+        // 6. 统计项目数用于判断“最后一条”
+        $device_count = collect($month_device_list)->groupBy(fn($i) => $i['device_id'].'_'.$i['order_month'])
+            ->map(fn($g) => $g->count())->toArray();
+
+        // 7. 预加载设备与项目基础信息
+        $items_ids = collect($month_device_list)->pluck('item_id')->unique()->all();
+        $device_ids = collect($month_device_list)->pluck('device_id')->unique()->all();
+
+        $item_info = Item::TopClear($user, $data)->whereIn('id', $items_ids)->get()->keyBy('id');
+        $device_info = Device::TopClear($user, $data)->whereIn('id', $device_ids)->get()->keyBy('id');
+
+        // 8. 核心转换逻辑
+        $item_month_list = collect($month_device_list)->sortBy('order_month')->values()->transform(function ($item) use (
+            $item_info, $device_info, $depreciation_pool, $device_monthly_total_min,
+            &$device_count, &$rem_depreciation_cents, &$rem_hours_cents
+        ) {
+            $key = $item['device_id'] . '_' . $item['order_month'];
+            $total_min = $device_monthly_total_min[$key] ?? 0;
+
+            $item['item_title'] = $item_info[$item['item_id']]->title ?? "未知项目";
+            $item['item_code'] = $item_info[$item['item_id']]->code ?? "-";
+            $item['device_title'] = $device_info[$item['device_id']]->title ?? "未知设备";
+            $item['device_original'] = $device_info[$item['device_id']]->original_value ?? 0;
+
+            $item['month'] = $item['order_month'];
+            $item['total_depreciatio'] = ($depreciation_pool[$key] ?? 0) / 100;
+            $item['total_hours'] = round($total_min / 60, 2);
+
+            // 分摊比例计算
+            $ratio = $total_min > 0 ? ($item['total_work'] / $total_min) : 0;
+            $item['ratio'] = round($ratio, 4);
+
+            if (--$device_count[$key] > 0) {
+                // 非最后一条项目
+                $cur_hours = round($item['total_work'] / 60, 2);
+                $item['hours'] = $cur_hours;
+                $rem_hours_cents[$key] -= (int)round($cur_hours * 100);
+
+                $cur_depre = round($item['total_depreciatio'] * $ratio, 2);
+                $item['allocated_depreciatio'] = $cur_depre;
+                $rem_depreciation_cents[$key] -= (int)round($cur_depre * 100);
+            } else {
+                // 最后一条项目,余额补平
+                $item['hours'] = round(($rem_hours_cents[$key] ?? 0) / 100, 2);
+                $item['allocated_depreciatio'] = round(($rem_depreciation_cents[$key] ?? 0) / 100, 2);
+                // 比例也做个平账展示
+                $item['ratio'] = round($item['hours'] / ($item['total_hours'] ?: 1), 4);
+            }
+
+            return $item;
+        })->all();
+
+        return [true, $item_month_list];
+    }
+
+    public function itemDeviceMonthStatistic1($data, $user)
     {
         //项目编码、项目名称、设备名称、项目工时、研发工时占比、设备原值、设备折旧额、本项目帐面归集的折旧额、确定的本项目折旧额、加计调整金额、当月工时、日期
         list($status, $month_start, $month_end) = $this->commonRule($data);