|
@@ -0,0 +1,357 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+namespace App\Service;
|
|
|
|
|
+
|
|
|
|
|
+use App\Model\DailyDwOrderDetails;
|
|
|
|
|
+use App\Model\DailyPwOrder;
|
|
|
|
|
+use App\Model\DailyPwOrderDetails;
|
|
|
|
|
+use App\Model\ExpenseClaims;
|
|
|
|
|
+use App\Model\ExpenseClaimsDetails;
|
|
|
|
|
+use App\Model\Fee;
|
|
|
|
|
+use App\Model\Item;
|
|
|
|
|
+use App\Model\MonthlyDdOrder;
|
|
|
|
|
+use App\Model\MonthlyDdOrderDetails;
|
|
|
|
|
+use App\Model\MonthlyPsOrder;
|
|
|
|
|
+use App\Model\MonthlyPsOrderDetails;
|
|
|
|
|
+use App\Model\PLeaveOverOrder;
|
|
|
|
|
+use App\Model\PLeaveOverOrderDetails;
|
|
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
|
|
+
|
|
|
|
|
+class BIService extends Service
|
|
|
|
|
+{
|
|
|
|
|
+ private function commonRule($data)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (isset($data['time']) && !empty($data['time'])) {
|
|
|
|
|
+ $start = $this->changeDateToDate($data['time'][0]);
|
|
|
|
|
+ $end = $this->changeDateToDate($data['time'][1], true);
|
|
|
|
|
+ $data['month_start'] = date("Y-m-d", $start);
|
|
|
|
|
+ $data['month_end'] = date("Y-m-d", $end);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!isset($data['month_start'])) $month_start = date('Y-01-01');
|
|
|
|
|
+ else $month_start = date('Y-m-01', strtotime($data['month_start']));
|
|
|
|
|
+ if (!isset($data['month_end'])) $month_end = date('Y-01-01', strtotime('+1 year', strtotime($month_start)));
|
|
|
|
|
+ else {
|
|
|
|
|
+ $start_year = date('Y', strtotime($month_start));
|
|
|
|
|
+ $end_year = date('Y', strtotime($data['month_end']));
|
|
|
|
|
+ if ($start_year != $end_year) return [false, "查询不得跨年!", ""];
|
|
|
|
|
+ $month_end = date('Y-m-01', strtotime($data['month_end'] . ' +1 month'));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [true, strtotime($month_start), strtotime($month_end)];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function homePageData($data, $user)
|
|
|
|
|
+ {
|
|
|
|
|
+ list($status, $month_start, $month_end) = $this->commonRule($data);
|
|
|
|
|
+ if (!$status) return [false, $month_start];
|
|
|
|
|
+
|
|
|
|
|
+ //人员费用
|
|
|
|
|
+ list($total_man, $salary_map) = $this->getEmployeeSalary($month_start, $month_end, $data, $user);
|
|
|
|
|
+
|
|
|
|
|
+ //折旧费用
|
|
|
|
|
+ list($total_zj, $zj_map) = $this->getDeviceSalary($month_start, $month_end, $data, $user);
|
|
|
|
|
+
|
|
|
|
|
+ //费用报销
|
|
|
|
|
+ list($total_other, $other_map, $return_fee) = $this->getFeeItemSalary($month_start, $month_end, $data, $user);
|
|
|
|
|
+
|
|
|
|
|
+ //研发费用总额
|
|
|
|
|
+ $total = bcadd(bcadd($total_man, $total_zj,3), $total_other,3);
|
|
|
|
|
+
|
|
|
|
|
+ //研发费用结构
|
|
|
|
|
+ $rd = [
|
|
|
|
|
+ 0 => [
|
|
|
|
|
+ 'title' => '人工费用',
|
|
|
|
|
+ 'rate' => bcmul(bcdiv($total_man,$total,4),100,2),
|
|
|
|
|
+ 'rate_unit' => '%',
|
|
|
|
|
+ 'total' => $total_man,
|
|
|
|
|
+ 'total_unit' => '¥',
|
|
|
|
|
+ ],
|
|
|
|
|
+ 1 => [
|
|
|
|
|
+ 'title' => '折旧费用',
|
|
|
|
|
+ 'rate' => bcmul(bcdiv($total_zj,$total,4),100,2),
|
|
|
|
|
+ 'rate_unit' => '%',
|
|
|
|
|
+ 'total' => $total_zj,
|
|
|
|
|
+ 'total_unit' => '¥',
|
|
|
|
|
+ ],
|
|
|
|
|
+ 2 => [
|
|
|
|
|
+ 'title' => '费用报销',
|
|
|
|
|
+ 'rate' => bcmul(bcdiv($total_other,$total,4),100,2),
|
|
|
|
|
+ 'rate_unit' => '%',
|
|
|
|
|
+ 'total' => $total_other,
|
|
|
|
|
+ 'total_unit' => '¥',
|
|
|
|
|
+ ],
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ //研发费用趋势
|
|
|
|
|
+ $rd_trend = $this->makeTrend($month_start, $salary_map, $zj_map, $other_map);
|
|
|
|
|
+
|
|
|
|
|
+ //研发费用报销占比
|
|
|
|
|
+ $rd_rate = $return_fee;
|
|
|
|
|
+
|
|
|
|
|
+ //加班 请假 总时长
|
|
|
|
|
+ list($over_time, $leave_time) = $this->overLeave($month_start, $month_end, $data, $user);
|
|
|
|
|
+
|
|
|
|
|
+ // 项目人员工时汇总
|
|
|
|
|
+ $man_work = $this->manWork($month_start, $month_end, $data, $user);
|
|
|
|
|
+
|
|
|
|
|
+ //加计扣除金额
|
|
|
|
|
+ $discount = 0; //todo
|
|
|
|
|
+
|
|
|
|
|
+ return [true, [
|
|
|
|
|
+ 'rd_total' => $total,
|
|
|
|
|
+ 'rd_unit' => '¥',
|
|
|
|
|
+ 'rd_title' => '研发费用总额', //-----
|
|
|
|
|
+ 'discount_total' => $discount,
|
|
|
|
|
+ 'discount_unit' => '¥',
|
|
|
|
|
+ 'discount_title' => '加计扣除金额', //------
|
|
|
|
|
+ 'over_time' => $over_time, // 加班
|
|
|
|
|
+ 'leave_time' => $leave_time, // 请假
|
|
|
|
|
+ 'rd' => $rd, //研发费用结构
|
|
|
|
|
+ 'rd_trend' => $rd_trend, //研发费用趋势
|
|
|
|
|
+ 'rd_rate' => $rd_rate, // 研发费用报销占比
|
|
|
|
|
+ 'man_work' => $man_work, //项目人员工时汇总
|
|
|
|
|
+ ]];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function getEmployeeSalary($month_start, $month_end, $data, $user)
|
|
|
|
|
+ {
|
|
|
|
|
+ $monthly_ps_order = MonthlyPsOrder::Clear($user, $data)
|
|
|
|
|
+ ->where('del_time', 0)
|
|
|
|
|
+ ->where("month", ">=", $month_start)
|
|
|
|
|
+ ->where("month", "<", $month_end)
|
|
|
|
|
+ ->pluck('month','id')
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $monthly_ps_order_ids = array_keys($monthly_ps_order);
|
|
|
|
|
+
|
|
|
|
|
+ $month_employee_salary = MonthlyPsOrderDetails::whereIn('main_id', $monthly_ps_order_ids)
|
|
|
|
|
+ ->select("salary", "main_id")
|
|
|
|
|
+ ->get()
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $total = 0;
|
|
|
|
|
+ $salary_map = [];
|
|
|
|
|
+ foreach ($month_employee_salary as $value) {
|
|
|
|
|
+ $currentAmount = (string)$value['salary'];
|
|
|
|
|
+
|
|
|
|
|
+ if(isset($monthly_ps_order[$value['main_id']])){
|
|
|
|
|
+ $month = $monthly_ps_order[$value['main_id']];
|
|
|
|
|
+ if(isset($salary_map[$month])){
|
|
|
|
|
+ $salary_map[$month] = bcadd($salary_map[$month], $currentAmount,3);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $salary_map[$month] = $currentAmount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $total = bcadd($total, $currentAmount,3);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [$total, $salary_map];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function getDeviceSalary($month_start, $month_end, $data, $user)
|
|
|
|
|
+ {
|
|
|
|
|
+ $monthly_dd_order= MonthlyDdOrder::Clear($user, $data)
|
|
|
|
|
+ ->where('del_time', 0)
|
|
|
|
|
+ ->where("month", ">=", $month_start)
|
|
|
|
|
+ ->where("month", "<", $month_end)
|
|
|
|
|
+ ->pluck('month','id')
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $monthly_dd_order_ids = array_keys($monthly_dd_order);
|
|
|
|
|
+
|
|
|
|
|
+ $month_device_salary = MonthlyDdOrderDetails::whereIn('main_id', $monthly_dd_order_ids)
|
|
|
|
|
+ ->select("depreciation_amount as amount", "main_id")
|
|
|
|
|
+ ->get()
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ $total = 0;
|
|
|
|
|
+ $amount_map = [];
|
|
|
|
|
+ foreach ($month_device_salary as $value) {
|
|
|
|
|
+ $currentAmount = (string)$value['amount'];
|
|
|
|
|
+
|
|
|
|
|
+ if(isset($monthly_dd_order[$value['main_id']])){
|
|
|
|
|
+ $month = $monthly_dd_order[$value['main_id']];
|
|
|
|
|
+ if(isset($amount_map[$month])){
|
|
|
|
|
+ $amount_map[$month] = bcadd($amount_map[$month], $currentAmount,3);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $amount_map[$month] = $currentAmount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $total = bcadd($total, $currentAmount,3);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [$total, $amount_map];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function getFeeItemSalary($month_start, $month_end, $data, $user)
|
|
|
|
|
+ {
|
|
|
|
|
+ $e_order = ExpenseClaims::Clear($user, $data)
|
|
|
|
|
+ ->where('del_time', 0)
|
|
|
|
|
+ ->where("month", ">=", $month_start)
|
|
|
|
|
+ ->where("month", "<", $month_end)
|
|
|
|
|
+ ->pluck('month','id')
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $e_order_ids = array_keys($e_order);
|
|
|
|
|
+
|
|
|
|
|
+ $e_order_detail = ExpenseClaimsDetails::whereIn('expense_claims_id', $e_order_ids)
|
|
|
|
|
+ ->select("amount", "expense_claims_id as main_id", "fee_id")
|
|
|
|
|
+ ->get()
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ $fee = Fee::TopClear($user, $data);
|
|
|
|
|
+ $fee_map = $fee->whereIn('id', array_unique(array_column($e_order_detail,'fee_id')))->pluck('title','id')->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ $total = 0;
|
|
|
|
|
+ $amount_map = [];
|
|
|
|
|
+ $fee_amount_map = [];
|
|
|
|
|
+ foreach ($e_order_detail as $value) {
|
|
|
|
|
+ $currentAmount = (string)$value['amount'];
|
|
|
|
|
+
|
|
|
|
|
+ if(isset($e_order[$value['main_id']])){
|
|
|
|
|
+ $month = $e_order[$value['main_id']];
|
|
|
|
|
+ if(isset($amount_map[$month])){
|
|
|
|
|
+ $amount_map[$month] = bcadd($amount_map[$month], $currentAmount,3);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $amount_map[$month] = $currentAmount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $fee_tmp = $fee_map[$value['fee_id']] ?? "";
|
|
|
|
|
+ if(! empty($fee_tmp)){
|
|
|
|
|
+ if(isset($fee_amount_map[$fee_tmp])){
|
|
|
|
|
+ $fee_amount_map[$fee_tmp] = bcadd($fee_amount_map[$fee_tmp], $currentAmount,3);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $fee_amount_map[$fee_tmp] = $currentAmount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $total = bcadd($total, $currentAmount,3);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $return_fee = [];
|
|
|
|
|
+ foreach ($fee_amount_map as $key => $value){
|
|
|
|
|
+ $amount = (string)$value;
|
|
|
|
|
+ $return_fee[] = [
|
|
|
|
|
+ "title" => $key,
|
|
|
|
|
+ "total" => $amount,
|
|
|
|
|
+ "total_unit" => "元",
|
|
|
|
|
+ "rate" => bcmul(bcdiv($amount,$total,4),100,2),
|
|
|
|
|
+ "rate_unit" => "%"
|
|
|
|
|
+ ];
|
|
|
|
|
+ }unset($fee_amount_map);
|
|
|
|
|
+
|
|
|
|
|
+ return [$total, $amount_map, $return_fee];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function makeTrend($month_start, $salary_map, $zj_map, $other_map)
|
|
|
|
|
+ {
|
|
|
|
|
+ $trend = [];
|
|
|
|
|
+
|
|
|
|
|
+ for ($i = 0; $i < 12; $i++) {
|
|
|
|
|
+ // 计算每个月第一天的时间戳作为 Key
|
|
|
|
|
+ $timestamp = strtotime("+$i month", $month_start);
|
|
|
|
|
+
|
|
|
|
|
+ $monthName = ($i + 1) . '月';
|
|
|
|
|
+
|
|
|
|
|
+ $trend[$timestamp] = [
|
|
|
|
|
+ 'month' => $monthName,
|
|
|
|
|
+// 'salary' => "0.000",
|
|
|
|
|
+// 'zj' => "0.000",
|
|
|
|
|
+// 'other' => "0.000",
|
|
|
|
|
+ 'total' => "0.000",
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 将传入的 Map 数据填充进去
|
|
|
|
|
+ foreach ($trend as $timestamp => &$item) {
|
|
|
|
|
+ // 使用 ?? "0" 容错,并强制转为 string 保证 bcadd 精度
|
|
|
|
|
+ $s = $salary_map[$timestamp] ?? "0";
|
|
|
|
|
+ $z = $zj_map[$timestamp] ?? "0";
|
|
|
|
|
+ $o = $other_map[$timestamp] ?? "0";
|
|
|
|
|
+
|
|
|
|
|
+// $item['salary'] = bcadd($s, "0", 3);
|
|
|
|
|
+// $item['zj'] = bcadd($z, "0", 3);
|
|
|
|
|
+// $item['other'] = bcadd($o, "0", 3);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算该月总计
|
|
|
|
|
+ $item['total'] = bcadd(bcadd($s, $z, 3), $o, 3);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return array_values($trend);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function overLeave($month_start, $month_end, $data, $user)
|
|
|
|
|
+ {
|
|
|
|
|
+ $id = PLeaveOverOrder::Clear($user, $data)
|
|
|
|
|
+ ->where('del_time', 0)
|
|
|
|
|
+ ->where("order_time", ">=", $month_start)
|
|
|
|
|
+ ->where("order_time", "<", $month_end)
|
|
|
|
|
+ ->pluck('id')
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ $p = PLeaveOverOrderDetails::whereIn('main_id', $id)
|
|
|
|
|
+ ->select("type", "total_min")
|
|
|
|
|
+ ->get()
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $total = $total_1 = 0;
|
|
|
|
|
+ foreach ($p as $value) {
|
|
|
|
|
+ $total_min = (string)$value['total_min'];
|
|
|
|
|
+
|
|
|
|
|
+ if($value['type'] == PLeaveOverOrderDetails::TYPE_ONE){
|
|
|
|
|
+ $total = bcadd($total, $total_min,2);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $total_1 = bcadd($total_1, $total_min,2);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 最终返回或输出前转换
|
|
|
|
|
+ $total_hours = bcdiv($total, 60, 2);
|
|
|
|
|
+ $total_1_hours = bcdiv($total_1, 60, 2);
|
|
|
|
|
+
|
|
|
|
|
+ return [$total_1_hours, $total_hours];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function manWork($month_start, $month_end, $data, $user)
|
|
|
|
|
+ {
|
|
|
|
|
+ $daily_pw = DailyPwOrder::Clear($user, $data)
|
|
|
|
|
+ ->where('del_time', 0)
|
|
|
|
|
+ ->where("order_time", ">=", $month_start)
|
|
|
|
|
+ ->where("order_time", "<", $month_end)
|
|
|
|
|
+ ->select('id','item_id')
|
|
|
|
|
+ ->get()->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ $item_map = Item::whereIn('id',array_unique(array_column($daily_pw,'item_id')))
|
|
|
|
|
+ ->pluck('title','id')
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $p = PLeaveOverOrderDetails::whereIn('main_id', array_column($daily_pw,'id'))
|
|
|
|
|
+ ->select("item_id", "total_work_min")
|
|
|
|
|
+ ->get()
|
|
|
|
|
+ ->toArray();
|
|
|
|
|
+ $total = 0;
|
|
|
|
|
+ $map = [];
|
|
|
|
|
+ foreach ($p as $value) {
|
|
|
|
|
+ $total_min = (string)$value['total_min'];
|
|
|
|
|
+ if(isset($map[$value['item_id']])){
|
|
|
|
|
+ $map[$value['item_id']] = bcadd($map[$value['item_id']], $total_min,2);
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $map[$value['item_id']] = $total_min;
|
|
|
|
|
+ }
|
|
|
|
|
+ $total = bcadd($total, $total_min,2);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ foreach ($map as $key => $value){
|
|
|
|
|
+ $rate = bcmul(bcdiv($value, $total,4),100,2);
|
|
|
|
|
+ $total_hours = bcdiv($value, 60, 2);
|
|
|
|
|
+
|
|
|
|
|
+ $return[] = [
|
|
|
|
|
+ 'title' => $item_map[$key] ?? "",
|
|
|
|
|
+ 'total_work_hour' => $total_hours,
|
|
|
|
|
+ 'total_work_hour_unit' => "小时",
|
|
|
|
|
+ "rate" => $rate,
|
|
|
|
|
+ "rate_unit" => "%",
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $return;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|