|
|
@@ -950,448 +950,7 @@ class StatisticsService extends Service
|
|
|
return $data;
|
|
|
}
|
|
|
|
|
|
- public function getChannelReport($data)
|
|
|
- {
|
|
|
- if(empty($data['order_time'])) return [false, '年月不能为空'];
|
|
|
- $yearMonth = $data['order_time'];
|
|
|
-
|
|
|
- // 1. 解析输入
|
|
|
- [$year, $month] = explode('-', $yearMonth);
|
|
|
- $year = (int)$year;
|
|
|
- $month = (int)$month;
|
|
|
-
|
|
|
- $currentMonthTs = mktime(0, 0, 0, $month, 1, $year);
|
|
|
- $yearStartTs = mktime(0, 0, 0, 1, 1, $year);
|
|
|
-
|
|
|
- // 2. 获取所有相关数据
|
|
|
- $records = DB::table('item_report')
|
|
|
- ->whereBetween('time', [$yearStartTs, $currentMonthTs])
|
|
|
- ->whereNotNull('channel_details') // 可选:排除空渠道
|
|
|
- ->get();
|
|
|
-
|
|
|
- // 3. 初始化结果容器
|
|
|
- $channels = [];
|
|
|
-
|
|
|
- foreach ($records as $record) {
|
|
|
- $channel = $record->channel_details;
|
|
|
-
|
|
|
- if (!isset($channels[$channel])) {
|
|
|
- // 初始化当月和累计
|
|
|
- $channels[$channel] = [
|
|
|
- 'monthly' => array_fill_keys($this->getAmountFieldNames(), 0),
|
|
|
- 'cumulative' => array_fill_keys($this->getAmountFieldNames(), 0),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- // 判断是否是当月
|
|
|
- $isCurrentMonth = ($record->time == $currentMonthTs);
|
|
|
-
|
|
|
- // 累加所有字段(包括 NULL 处理)
|
|
|
- foreach ($this->getAmountFieldNames() as $field) {
|
|
|
- $value = $record->$field ?? 0;
|
|
|
- $channels[$channel]['cumulative'][$field] += $value;
|
|
|
- if ($isCurrentMonth) {
|
|
|
- $channels[$channel]['monthly'][$field] += $value;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 4. 插入 amount1 和 amount2,并格式化输出
|
|
|
- $finalResult = [];
|
|
|
- foreach ($channels as $channel => $data) {
|
|
|
- $finalResult[] = [
|
|
|
- 'channel' => $channel,
|
|
|
- 'monthly' => $this->injectAmount1And2($data['monthly']),
|
|
|
- 'cumulative' => $this->injectAmount1And2($data['cumulative']),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- return $finalResult;
|
|
|
- }
|
|
|
-
|
|
|
- private function getAmountFieldNames()
|
|
|
- {
|
|
|
- return [
|
|
|
- 'receipt_amount',
|
|
|
- 'cost',
|
|
|
- 'profit',
|
|
|
- 'settle_amount',
|
|
|
- 'gl_amount',
|
|
|
- 'wl_amount',
|
|
|
- 'ht_amount',
|
|
|
- 'zk_amount',
|
|
|
- 'cx_amount',
|
|
|
- 'tg_amount',
|
|
|
- 'cl_amount',
|
|
|
- 'kq_amount',
|
|
|
- 'zp_amount',
|
|
|
- 'gg_amount',
|
|
|
- 'kd_amount',
|
|
|
- 'xsqt_amount',
|
|
|
- 'ry_amount',
|
|
|
- 'sb_amount',
|
|
|
- 'sj_amount', // 注意:包含 sj_amount
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- private function injectAmount1And2($data)
|
|
|
- {
|
|
|
- $result = [];
|
|
|
- $expenseFields = [
|
|
|
- 'settle_amount',
|
|
|
- 'gl_amount',
|
|
|
- 'wl_amount',
|
|
|
- 'ht_amount',
|
|
|
- 'zk_amount',
|
|
|
- 'cx_amount',
|
|
|
- 'tg_amount',
|
|
|
- 'cl_amount',
|
|
|
- 'kq_amount',
|
|
|
- 'zp_amount',
|
|
|
- 'gg_amount',
|
|
|
- 'kd_amount',
|
|
|
- 'xsqt_amount',
|
|
|
- 'ry_amount',
|
|
|
- 'sb_amount',
|
|
|
- 'sj_amount', // 注意:sj_amount 要包含
|
|
|
- ];
|
|
|
-
|
|
|
- // 第一步:按顺序构建带 amount1/2 的数组
|
|
|
- foreach ($data as $key => $value) {
|
|
|
- if ($key === 'sj_amount') {
|
|
|
- $result['amount1'] = '0.00';
|
|
|
- $result['sj_amount'] = number_format($value, 2, '.', '');
|
|
|
- $result['amount2'] = '0.00';
|
|
|
- } else {
|
|
|
- $result[$key] = number_format($value, 2, '.', '');
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 第二步:计算 total(仅 expenseFields 中的字段,从 $data 原始值取,避免字符串运算)
|
|
|
- $total = 0;
|
|
|
- foreach ($expenseFields as $field) {
|
|
|
- $val = $data[$field] ?? 0;
|
|
|
- $total += is_numeric($val) ? (float)$val : 0;
|
|
|
- }
|
|
|
-
|
|
|
- $result['total'] = number_format($total, 2, '.', '');
|
|
|
-
|
|
|
- return $result;
|
|
|
- }
|
|
|
-
|
|
|
- public function getChannelReportRoad($data)
|
|
|
- {
|
|
|
- if(empty($data['order_time'])) return [false, '年月不能为空'];
|
|
|
- $yearMonth = $data['order_time'];
|
|
|
-
|
|
|
- // 1. 解析输入
|
|
|
- [$year, $month] = explode('-', $yearMonth);
|
|
|
- $year = (int)$year;
|
|
|
- $month = (int)$month;
|
|
|
-
|
|
|
- $currentMonthTs = mktime(0, 0, 0, $month, 1, $year);
|
|
|
- $yearStartTs = mktime(0, 0, 0, 1, 1, $year);
|
|
|
-
|
|
|
- // 2. 获取所有相关数据
|
|
|
- $records = DB::table('item_report_road')
|
|
|
- ->whereBetween('time', [$yearStartTs, $currentMonthTs])
|
|
|
- ->whereNotNull('employee_title_type') //
|
|
|
- ->get();
|
|
|
-
|
|
|
- // 3. 初始化结果容器
|
|
|
- $channels = [];
|
|
|
-
|
|
|
- foreach ($records as $record) {
|
|
|
- $channel = $record->employee_title_type;
|
|
|
-
|
|
|
- if (!isset($channels[$channel])) {
|
|
|
- // 初始化当月和累计
|
|
|
- $channels[$channel] = [
|
|
|
- 'monthly' => array_fill_keys($this->getAmountFieldNames(), 0),
|
|
|
- 'cumulative' => array_fill_keys($this->getAmountFieldNames(), 0),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- // 判断是否是当月
|
|
|
- $isCurrentMonth = ($record->time == $currentMonthTs);
|
|
|
-
|
|
|
- // 累加所有字段(包括 NULL 处理)
|
|
|
- foreach ($this->getAmountFieldNames() as $field) {
|
|
|
- $value = $record->$field ?? 0;
|
|
|
- $channels[$channel]['cumulative'][$field] += $value;
|
|
|
- if ($isCurrentMonth) {
|
|
|
- $channels[$channel]['monthly'][$field] += $value;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 4. 插入 amount1 和 amount2,并格式化输出
|
|
|
- $finalResult = [];
|
|
|
- foreach ($channels as $channel => $data) {
|
|
|
- $finalResult[] = [
|
|
|
- 'channel' => $channel,
|
|
|
- 'monthly' => $this->injectAmount1And2($data['monthly']),
|
|
|
- 'cumulative' => $this->injectAmount1And2($data['cumulative']),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- return $finalResult;
|
|
|
- }
|
|
|
-
|
|
|
- private function getAmountFieldManNames()
|
|
|
- {
|
|
|
- return [
|
|
|
- 'receipt_amount', 'receipt_not_amount', 'cost', 'profit', 'profit_not',
|
|
|
- 'settle_amount', 'gl_amount', 'gl_not_amount', 'wl_amount', 'wl_not_amount',
|
|
|
- 'ht_amount', 'zk_amount', 'cx_amount', 'tg_amount', 'cl_amount',
|
|
|
- 'kq_amount', 'zp_amount', 'gg_amount', 'kd_amount', 'xsqt_amount',
|
|
|
- 'ry_amount', 'sb_amount', 'sj_amount', 'sj_not_amount', 'sx_amount',
|
|
|
- 'sx_not_amount', 'other_ck_amount', 'cg_amount'
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- private function injectAmountMan($data)
|
|
|
- {
|
|
|
- $result = [];
|
|
|
- // 参与 total 计算的费用字段 (排除收入、成本和利润)
|
|
|
- $expenseFields = [
|
|
|
- 'settle_amount', 'gl_amount', 'gl_not_amount', 'wl_amount', 'wl_not_amount',
|
|
|
- 'ht_amount', 'zk_amount', 'cx_amount', 'tg_amount', 'cl_amount',
|
|
|
- 'kq_amount', 'zp_amount', 'gg_amount', 'kd_amount', 'xsqt_amount',
|
|
|
- 'ry_amount', 'sb_amount', 'sj_amount', 'sj_not_amount', 'sx_amount',
|
|
|
- 'sx_not_amount', 'other_ck_amount', 'cg_amount'
|
|
|
- ];
|
|
|
-
|
|
|
- // 第一步:格式化并插入占位符
|
|
|
- foreach ($this->getAmountFieldManNames() as $key) {
|
|
|
- $val = $data[$key] ?? 0;
|
|
|
-
|
|
|
- if ($key === 'sj_amount') {
|
|
|
- $result['amount1'] = '0.00'; // 占位
|
|
|
- $result['sj_amount'] = number_format((float)$val, 2, '.', '');
|
|
|
- $result['amount2'] = '0.00'; // 占位
|
|
|
- } else {
|
|
|
- $result[$key] = number_format((float)$val, 2, '.', '');
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 第二步:计算费用总额
|
|
|
- $total = 0;
|
|
|
- foreach ($expenseFields as $field) {
|
|
|
- $total += (float)($data[$field] ?? 0);
|
|
|
- }
|
|
|
- $result['total'] = number_format($total, 2, '.', '');
|
|
|
-
|
|
|
- return $result;
|
|
|
- }
|
|
|
-
|
|
|
public function getChannelReportMan1($data)
|
|
|
- {
|
|
|
- if(empty($data['order_time'])) return [false, '年月不能为空'];
|
|
|
- $yearMonth = $data['order_time']; // 格式如 2026-02
|
|
|
-
|
|
|
- [$year, $month] = explode('-', $yearMonth);
|
|
|
- $year = (int)$year;
|
|
|
- $month = (int)$month;
|
|
|
-
|
|
|
- // 当前选择月的第一天戳
|
|
|
- $currentMonthTs = mktime(0, 0, 0, $month, 1, $year);
|
|
|
- // 去年7月1日的时间戳 (例如输入2026-02,则起始为2025-07-01)
|
|
|
- $startTs = mktime(0, 0, 0, 7, 1, $year - 1);
|
|
|
-
|
|
|
- // 从业务员报表获取数据
|
|
|
- $records = DB::table('item_report_man')
|
|
|
- ->whereBetween('time', [$startTs, $currentMonthTs])
|
|
|
- ->get();
|
|
|
-
|
|
|
- $channels = [];
|
|
|
- $allFields = $this->getAmountFieldManNames();
|
|
|
-
|
|
|
- foreach ($records as $record) {
|
|
|
- // 以渠道财务分组
|
|
|
- $channel = $record->channel_finance ?: '未知渠道';
|
|
|
-
|
|
|
- if (!isset($channels[$channel])) {
|
|
|
- $channels[$channel] = [
|
|
|
- 'monthly' => array_fill_keys($allFields, 0),
|
|
|
- 'cumulative' => array_fill_keys($allFields, 0),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- $isCurrentMonth = ((int)$record->time === $currentMonthTs);
|
|
|
-
|
|
|
- foreach ($allFields as $field) {
|
|
|
- $val = (float)($record->$field ?? 0);
|
|
|
- // 累计去年7月至今
|
|
|
- $channels[$channel]['cumulative'][$field] += $val;
|
|
|
- // 仅当月
|
|
|
- if ($isCurrentMonth) {
|
|
|
- $channels[$channel]['monthly'][$field] += $val;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- $finalResult = [];
|
|
|
- foreach ($channels as $channelName => $values) {
|
|
|
- $finalResult[] = [
|
|
|
- 'channel' => $channelName,
|
|
|
- 'monthly' => $this->injectAmountMan($values['monthly']),
|
|
|
- 'cumulative' => $this->injectAmountMan($values['cumulative']),
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- return $finalResult;
|
|
|
- }
|
|
|
-
|
|
|
- public function getChannelReportMan2($data)
|
|
|
- {
|
|
|
- if (empty($data['order_time'])) return [false, '年月不能为空'];
|
|
|
- $yearMonth = $data['order_time'];
|
|
|
-
|
|
|
- [$year, $month] = explode('-', $yearMonth);
|
|
|
- $year = (int)$year;
|
|
|
- $month = (int)$month;
|
|
|
-
|
|
|
- // 1. 计算时间范围
|
|
|
- $currentMonthTs = mktime(0, 0, 0, $month, 1, $year);
|
|
|
- // 财年规则:如果当前月 >= 7月,起始是当年7月;否则是去年7月
|
|
|
- $startYear = ($month >= 7) ? $year : $year - 1;
|
|
|
- $startTs = mktime(0, 0, 0, 7, 1, $startYear);
|
|
|
-
|
|
|
- // 2. 一次性获取所有相关记录
|
|
|
- $records = DB::table('item_report_man')
|
|
|
- ->whereBetween('time', [$startTs, $currentMonthTs])
|
|
|
- ->get();
|
|
|
-
|
|
|
- // 3. 定义金额字段(按 B5-B27 的顺序排列,方便后面直接填充 row)
|
|
|
- $rowFieldMapping = [
|
|
|
- 5 => 'receipt_amount', 6 => 'cost', 7 => 'profit',
|
|
|
- 8 => 'settle_amount', 9 => 'gl_amount', 10 => 'wl_amount',
|
|
|
- 11 => 'ht_amount', 12 => 'zk_amount', 13 => 'cx_amount',
|
|
|
- 14 => 'tg_amount', 15 => 'cl_amount', 16 => 'kq_amount',
|
|
|
- 17 => 'zp_amount', 18 => 'gg_amount', 19 => 'kd_amount',
|
|
|
- 20 => 'xsqt_amount', 21 => 'ry_amount', 22 => 'sb_amount',
|
|
|
- 23 => '退货亏损', 24 => 'cg_amount', 25 => 'sj_amount',
|
|
|
- 26 => 'sx_amount', 27 => 'other_ck_amount'
|
|
|
- ];
|
|
|
-
|
|
|
- // 4. 初始化列容器(C到Z)
|
|
|
- $columns = [];
|
|
|
- $columnKeys = range('C', 'Z');
|
|
|
- foreach ($columnKeys as $col) {
|
|
|
- $columns[$col] = array_fill(5, 28, 0); // 5-32行,初始化为0
|
|
|
- }
|
|
|
-
|
|
|
- // 5. 遍历分拣数据
|
|
|
- foreach ($records as $record) {
|
|
|
- $empId = (int)$record->employee_id_1;
|
|
|
- $finance = $record->channel_finance;
|
|
|
- $isCurrent = ((int)$record->time === $currentMonthTs);
|
|
|
-
|
|
|
- foreach ($rowFieldMapping as $rowIdx => $field) {
|
|
|
- $val = (float)($record->$field ?? 0);
|
|
|
-
|
|
|
- // 规则分拣 (C, D, G, H, K, L, O, Q, R, U, W)
|
|
|
- // C: 2+社区
|
|
|
- if ($empId === 2 && $finance === '社区') {
|
|
|
- if ($isCurrent) $columns['C'][$rowIdx] += $val;
|
|
|
- $columns['F'][$rowIdx] += $val; // 累计
|
|
|
- }
|
|
|
- // D: (2+通路) + (5+通路)
|
|
|
- if (($empId === 2 || $empId === 5) && $finance === '通路') {
|
|
|
- if ($isCurrent) $columns['D'][$rowIdx] += $val;
|
|
|
- $columns['F'][$rowIdx] += $val; // 累计到F
|
|
|
- }
|
|
|
- // G: 3+通路
|
|
|
- if ($empId === 3 && $finance === '通路') {
|
|
|
- if ($isCurrent) $columns['G'][$rowIdx] += $val;
|
|
|
- $columns['J'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // H: 3+联华加盟
|
|
|
- if ($empId === 3 && $finance === '联华加盟') {
|
|
|
- if ($isCurrent) $columns['H'][$rowIdx] += $val;
|
|
|
- $columns['J'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // K: 23+通路
|
|
|
- if ($empId === 23 && $finance === '通路') {
|
|
|
- if ($isCurrent) $columns['K'][$rowIdx] += $val;
|
|
|
- $columns['N'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // L: 23+智鲸
|
|
|
- if ($empId === 23 && $finance === '智鲸') {
|
|
|
- if ($isCurrent) $columns['L'][$rowIdx] += $val;
|
|
|
- $columns['N'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // O: (7,8,54) + (通路,大卖场)
|
|
|
- if (in_array($empId, [7, 8, 54]) && in_array($finance, ['通路', '大卖场'])) {
|
|
|
- if ($isCurrent) $columns['O'][$rowIdx] += $val;
|
|
|
- $columns['P'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // Q: 48+通路
|
|
|
- if ($empId === 48 && $finance === '通路') {
|
|
|
- if ($isCurrent) $columns['Q'][$rowIdx] += $val;
|
|
|
- $columns['T'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // R: 48+大卖场
|
|
|
- if ($empId === 48 && $finance === '大卖场') {
|
|
|
- if ($isCurrent) $columns['R'][$rowIdx] += $val;
|
|
|
- $columns['T'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // U: 行政
|
|
|
- if ($finance === '行政') {
|
|
|
- if ($isCurrent) $columns['U'][$rowIdx] += $val;
|
|
|
- $columns['V'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- // W: 鲍总
|
|
|
- if ($finance === '鲍总') {
|
|
|
- if ($isCurrent) $columns['W'][$rowIdx] += $val;
|
|
|
- $columns['X'][$rowIdx] += $val;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 6. 计算横向合计列
|
|
|
- for ($i = 5; $i <= 27; $i++) {
|
|
|
- $columns['E'][$i] = $columns['C'][$i] + $columns['D'][$i]; // 张+霍当月合计
|
|
|
- $columns['I'][$i] = $columns['G'][$i] + $columns['H'][$i]; // 金小勇当月合计
|
|
|
- $columns['M'][$i] = $columns['K'][$i] + $columns['L'][$i]; // 沈强当月合计
|
|
|
- $columns['S'][$i] = $columns['Q'][$i] + $columns['R'][$i]; // 叶南汝当月合计
|
|
|
-
|
|
|
- // Y: 当月总计 (所有当月列累加)
|
|
|
- $columns['Y'][$i] = $columns['C'][$i] + $columns['D'][$i] + $columns['G'][$i] +
|
|
|
- $columns['H'][$i] + $columns['K'][$i] + $columns['L'][$i] +
|
|
|
- $columns['O'][$i] + $columns['Q'][$i] + $columns['R'][$i] +
|
|
|
- $columns['U'][$i] + $columns['W'][$i];
|
|
|
-
|
|
|
- // Z: 年累计总计 (所有累计列累加)
|
|
|
- $columns['Z'][$i] = $columns['F'][$i] + $columns['J'][$i] + $columns['N'][$i] +
|
|
|
- $columns['P'][$i] + $columns['T'][$i] + $columns['V'][$i] + $columns['X'][$i];
|
|
|
- }
|
|
|
-
|
|
|
- // 7. 组装最终供 Excel 填充的数组 (5行到32行)
|
|
|
- $finalData = [];
|
|
|
- for ($row = 5; $row <= 32; $row++) {
|
|
|
- $rowData = [];
|
|
|
- // 从 C 到 Z 循环取数据
|
|
|
- foreach (range('C', 'Z') as $colLetter) {
|
|
|
- $val = $columns[$colLetter][$row] ?? 0;
|
|
|
- // 28-32行填空字符串,其他格式化
|
|
|
- if ($row > 27 && $row < 32) {
|
|
|
- $rowData[] = '';
|
|
|
- } elseif ($row == 32) {
|
|
|
- // 如果需要算小计可以在这里加,目前先填空字符串
|
|
|
- $rowData[] = '';
|
|
|
- } else {
|
|
|
- $rowData[] = $val == 0 ? '0.00' : number_format($val, 2, '.', '');
|
|
|
- }
|
|
|
- }
|
|
|
- $finalData[] = $rowData;
|
|
|
- }
|
|
|
-
|
|
|
- return $finalData;
|
|
|
- }
|
|
|
-
|
|
|
- public function getChannelReportMan($data)
|
|
|
{
|
|
|
if (empty($data['order_time'])) return [false, '年月不能为空'];
|
|
|
$yearMonth = $data['order_time'];
|
|
|
@@ -1511,35 +1070,73 @@ class StatisticsService extends Service
|
|
|
$columns['T'][$i] + $columns['V'][$i] + $columns['X'][$i];
|
|
|
}
|
|
|
|
|
|
- // 纵向小计 (第 32 行 = 8 到 31 行累加)
|
|
|
+ // 6. 计算横向合计与纵向小计
|
|
|
+ // 定义哪些列是“当月”数据列
|
|
|
+ $monthlyCols = ['C', 'D', 'G', 'H', 'K', 'L', 'O', 'Q', 'R', 'U', 'W', 'Y'];
|
|
|
+ // 定义哪些列是“合计”或“年累计”汇总列
|
|
|
+ $summaryCols = ['E', 'F', 'I', 'J', 'M', 'N', 'P', 'S', 'T', 'V', 'X', 'Y', 'Z'];
|
|
|
+
|
|
|
+ // --- 纵向小计 (第32行:销售支出小计) ---
|
|
|
foreach ($columnKeys as $col) {
|
|
|
- $subTotal = 0;
|
|
|
- for ($r = 8; $r <= 31; $r++) {
|
|
|
- $subTotal += (float)($columns[$col][$r] ?? 0);
|
|
|
+ // 只有“当月”列才计算小计,汇总列按你要求不算(设为0或空)
|
|
|
+ if (in_array($col, $monthlyCols)) {
|
|
|
+ $subTotal = 0;
|
|
|
+ for ($r = 8; $r <= 31; $r++) {
|
|
|
+ $subTotal += (float)($columns[$col][$r] ?? 0);
|
|
|
+ }
|
|
|
+ $columns[$col][32] = $subTotal;
|
|
|
+
|
|
|
+ // --- 利润分析区计算 (33-38行) ---
|
|
|
+ // 实际利润 (33) = 毛利(7) - 支出小计(32)
|
|
|
+ $realProfit = (float)$columns[$col][7] - (float)$columns[$col][32];
|
|
|
+ $columns[$col][33] = $realProfit;
|
|
|
+ // 净利润 (38) 初始等于实际利润
|
|
|
+ $columns[$col][38] = $realProfit;
|
|
|
+ } else {
|
|
|
+ // 合计列和年累计列,第32、33、38行全部置空
|
|
|
+ $columns[$col][32] = '';
|
|
|
+ $columns[$col][33] = '';
|
|
|
+ $columns[$col][38] = '';
|
|
|
}
|
|
|
- $columns[$col][32] = $subTotal;
|
|
|
}
|
|
|
|
|
|
- // 7. 最终格式化
|
|
|
+ // --- 横向合计 (E, I, M, S, Y, Z 等) ---
|
|
|
+ // 注意:这里只处理 5-27 行的横向累加,因为 32 行以后不需要在合计列显示数据
|
|
|
+ for ($i = 5; $i <= 27; $i++) {
|
|
|
+ $columns['E'][$i] = $columns['C'][$i] + $columns['D'][$i];
|
|
|
+ $columns['I'][$i] = $columns['G'][$i] + $columns['H'][$i];
|
|
|
+ $columns['M'][$i] = $columns['K'][$i] + $columns['L'][$i];
|
|
|
+ $columns['S'][$i] = $columns['Q'][$i] + $columns['R'][$i];
|
|
|
+
|
|
|
+ // Y/Z 总计
|
|
|
+ $columns['Y'][$i] = $columns['C'][$i] + $columns['D'][$i] + $columns['G'][$i] + $columns['H'][$i] +
|
|
|
+ $columns['K'][$i] + $columns['L'][$i] + $columns['O'][$i] + $columns['Q'][$i] +
|
|
|
+ $columns['R'][$i] + $columns['U'][$i] + $columns['W'][$i];
|
|
|
+
|
|
|
+ $columns['Z'][$i] = $columns['F'][$i] + $columns['J'][$i] + $columns['N'][$i] + $columns['P'][$i] +
|
|
|
+ $columns['T'][$i] + $columns['V'][$i] + $columns['X'][$i];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 7. 最终格式化 (确保输出 5-38 行)
|
|
|
$finalData = [];
|
|
|
- for ($row = 5; $row <= 32; $row++) {
|
|
|
+ for ($row = 5; $row <= 38; $row++) {
|
|
|
$rowData = [];
|
|
|
foreach ($columnKeys as $colLetter) {
|
|
|
- $val = $columns[$colLetter][$row] ?? 0;
|
|
|
-
|
|
|
- if ($row >= 28 && $row <= 31) {
|
|
|
- $rowData[] = ''; // 预留行填空
|
|
|
+ $val = $columns[$colLetter][$row] ?? '';
|
|
|
+ if ($row >= 28 && $row <= 31 && !is_numeric($val)) {
|
|
|
+ $rowData[] = '';
|
|
|
+ } elseif ($val === '') {
|
|
|
+ $rowData[] = '';
|
|
|
} else {
|
|
|
- $rowData[] = ($val == 0) ? '0.00' : number_format($val, 2, '.', '');
|
|
|
+ $rowData[] = is_numeric($val) ? number_format((float)$val, 2, '.', '') : $val;
|
|
|
}
|
|
|
}
|
|
|
$finalData[] = $rowData;
|
|
|
}
|
|
|
-
|
|
|
return $finalData;
|
|
|
}
|
|
|
|
|
|
- public function getChannelReportItem1($data)
|
|
|
+ public function getChannelReportMan($data)
|
|
|
{
|
|
|
if (empty($data['order_time'])) return [false, '年月不能为空'];
|
|
|
$yearMonth = $data['order_time'];
|
|
|
@@ -1548,45 +1145,43 @@ class StatisticsService extends Service
|
|
|
$year = (int)$year;
|
|
|
$month = (int)$month;
|
|
|
|
|
|
- // 1. 计算时间范围:7月财年规则
|
|
|
$currentMonthTs = mktime(0, 0, 0, $month, 1, $year);
|
|
|
$startYear = ($month >= 7) ? $year : $year - 1;
|
|
|
$startTs = mktime(0, 0, 0, 7, 1, $startYear);
|
|
|
|
|
|
- // 2. 一次性获取数据
|
|
|
- $records = DB::table('item_report')
|
|
|
+ $records = DB::table('item_report_man')
|
|
|
->whereBetween('time', [$startTs, $currentMonthTs])
|
|
|
->get();
|
|
|
|
|
|
- // 3. 字段映射 (注意 24 行,若数据库无字段则设为 null 会自动补 0)
|
|
|
$rowFieldMapping = [
|
|
|
- 5 => 'receipt_amount', 6 => 'pk_amount', 7 => 'cost', 8 => 'profit',
|
|
|
- 9 => 'settle_amount', 10 => 'gl_amount', 11 => 'wl_amount',
|
|
|
- 12 => 'ht_amount', 13 => 'zk_amount', 14 => 'cx_amount',
|
|
|
- 15 => 'tg_amount', 16 => 'cl_amount', 17 => 'kq_amount',
|
|
|
- 18 => 'zp_amount', 19 => 'gg_amount', 20 => 'kd_amount',
|
|
|
- 21 => 'xsqt_amount', 22 => 'ry_amount', 23 => 'sb_amount',
|
|
|
- 24 => null, // 退货亏损 (不良仓),暂无字段映射,填充0
|
|
|
- 25 => 'cg_amount', 26 => 'sj_amount',
|
|
|
- 27 => 'sx_amount', 28 => 'other_ck_amount'
|
|
|
+ 5 => 'receipt_not_amount', 6 => 'cost', 7 => 'profit_not',
|
|
|
+ 8 => 'settle_amount', 9 => 'gl_not_amount', 10 => 'wl_not_amount',
|
|
|
+ 11 => 'ht_amount', 12 => 'zk_amount', 13 => 'cx_amount',
|
|
|
+ 14 => 'tg_amount', 15 => 'cl_amount', 16 => 'kq_amount',
|
|
|
+ 17 => 'zp_amount', 18 => 'gg_amount', 19 => 'kd_amount',
|
|
|
+ 20 => 'xsqt_amount', 21 => 'ry_amount', 22 => 'sb_amount',
|
|
|
+ 23 => null,
|
|
|
+ 24 => 'cg_amount', 25 => 'sj_not_amount',
|
|
|
+ 26 => 'sx_not_amount', 27 => 'other_ck_amount'
|
|
|
];
|
|
|
|
|
|
- // 4. 初始化列容器 (C 到 Z)
|
|
|
$columns = [];
|
|
|
- $columnKeys = range('C', 'AB');
|
|
|
+ $columnKeys = range('C', 'Z');
|
|
|
foreach ($columnKeys as $col) {
|
|
|
- $columns[$col] = array_fill(5, 33, 0); // 覆盖 5-33 行
|
|
|
+ $columns[$col] = array_fill(5, 34, 0); // 初始化到38行
|
|
|
}
|
|
|
|
|
|
- // 5. 数据分拣累加
|
|
|
+ // 1. 基础数据分拣 (5-27行)
|
|
|
foreach ($records as $record) {
|
|
|
- $channel_details = $record->channel_details;
|
|
|
+ $empId = (int)$record->employee_id_1;
|
|
|
+ $finance = $record->channel_finance;
|
|
|
$isCurrent = ((int)$record->time === $currentMonthTs);
|
|
|
|
|
|
foreach ($rowFieldMapping as $rowIdx => $field) {
|
|
|
$val = $field ? (float)($record->$field ?? 0) : 0;
|
|
|
|
|
|
- if ($channel_details === '大卖场') {
|
|
|
+ // 张春勇、霍尚琳
|
|
|
+ if ($empId === 2 && $finance === '社区') {
|
|
|
if ($isCurrent) $columns['C'][$rowIdx] += $val;
|
|
|
$columns['F'][$rowIdx] += $val;
|
|
|
}
|
|
|
@@ -1612,7 +1207,7 @@ class StatisticsService extends Service
|
|
|
if ($isCurrent) $columns['L'][$rowIdx] += $val;
|
|
|
$columns['N'][$rowIdx] += $val;
|
|
|
}
|
|
|
- // 王利英等组合 (O/P列)
|
|
|
+ // 王利英等组合
|
|
|
if (in_array($empId, [7, 8, 54]) && in_array($finance, ['通路', '大卖场'])) {
|
|
|
if ($isCurrent) $columns['O'][$rowIdx] += $val;
|
|
|
$columns['P'][$rowIdx] += $val;
|
|
|
@@ -1639,48 +1234,60 @@ class StatisticsService extends Service
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 6. 计算合计列与纵向小计
|
|
|
+ // 2. 计算横向合计 (5-27行)
|
|
|
for ($i = 5; $i <= 27; $i++) {
|
|
|
- // 合计列
|
|
|
$columns['E'][$i] = $columns['C'][$i] + $columns['D'][$i];
|
|
|
$columns['I'][$i] = $columns['G'][$i] + $columns['H'][$i];
|
|
|
$columns['M'][$i] = $columns['K'][$i] + $columns['L'][$i];
|
|
|
$columns['S'][$i] = $columns['Q'][$i] + $columns['R'][$i];
|
|
|
|
|
|
- // Y/Z 总计
|
|
|
+ // Y (当月总合计)
|
|
|
$columns['Y'][$i] = $columns['C'][$i] + $columns['D'][$i] + $columns['G'][$i] + $columns['H'][$i] +
|
|
|
$columns['K'][$i] + $columns['L'][$i] + $columns['O'][$i] + $columns['Q'][$i] +
|
|
|
$columns['R'][$i] + $columns['U'][$i] + $columns['W'][$i];
|
|
|
|
|
|
+ // Z (年累计总合计)
|
|
|
$columns['Z'][$i] = $columns['F'][$i] + $columns['J'][$i] + $columns['N'][$i] + $columns['P'][$i] +
|
|
|
$columns['T'][$i] + $columns['V'][$i] + $columns['X'][$i];
|
|
|
}
|
|
|
|
|
|
- // 纵向小计 (第 32 行 = 8 到 31 行累加)
|
|
|
+ // 3. 计算纵向小计与利润分析 (全列应用,包括合计列)
|
|
|
foreach ($columnKeys as $col) {
|
|
|
+ // 32行:销售支出小计 (8-31行)
|
|
|
$subTotal = 0;
|
|
|
for ($r = 8; $r <= 31; $r++) {
|
|
|
$subTotal += (float)($columns[$col][$r] ?? 0);
|
|
|
}
|
|
|
$columns[$col][32] = $subTotal;
|
|
|
+
|
|
|
+ // 33行:实际利润 = 毛利(7行) - 支出小计(32行)
|
|
|
+ $realProfit = (float)$columns[$col][7] - (float)$columns[$col][32];
|
|
|
+ $columns[$col][33] = $realProfit;
|
|
|
+
|
|
|
+ // 38行:净利润 (初始 = 实际利润)
|
|
|
+ $columns[$col][38] = $realProfit;
|
|
|
+
|
|
|
+ // 34-37行置空
|
|
|
+ $columns[$col][34] = ''; $columns[$col][35] = '';
|
|
|
+ $columns[$col][36] = ''; $columns[$col][37] = '';
|
|
|
}
|
|
|
|
|
|
- // 7. 最终格式化
|
|
|
+ // 4. 格式化输出 (5-38行)
|
|
|
$finalData = [];
|
|
|
- for ($row = 5; $row <= 32; $row++) {
|
|
|
+ for ($row = 5; $row <= 38; $row++) {
|
|
|
$rowData = [];
|
|
|
foreach ($columnKeys as $colLetter) {
|
|
|
- $val = $columns[$colLetter][$row] ?? 0;
|
|
|
-
|
|
|
- if ($row >= 28 && $row <= 31) {
|
|
|
- $rowData[] = ''; // 预留行填空
|
|
|
+ $val = $columns[$colLetter][$row] ?? '';
|
|
|
+ if ($row >= 28 && $row <= 31 && !is_numeric($val)) {
|
|
|
+ $rowData[] = '';
|
|
|
+ } elseif ($val === '') {
|
|
|
+ $rowData[] = '';
|
|
|
} else {
|
|
|
- $rowData[] = ($val == 0) ? '0.00' : number_format($val, 2, '.', '');
|
|
|
+ $rowData[] = is_numeric($val) ? number_format((float)$val, 2, '.', '') : $val;
|
|
|
}
|
|
|
}
|
|
|
$finalData[] = $rowData;
|
|
|
}
|
|
|
-
|
|
|
return $finalData;
|
|
|
}
|
|
|
|
|
|
@@ -1761,7 +1368,7 @@ class StatisticsService extends Service
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 6. 计算横向合计 (AA, AB) 与 纵向小计 (第 33 行)
|
|
|
+ // 6. 计算横向合计 (AA, AB)
|
|
|
$channelStartCols = array_values($channelMap);
|
|
|
for ($row = 5; $row <= 28; $row++) {
|
|
|
foreach ($channelStartCols as $sCol) {
|
|
|
@@ -1773,28 +1380,43 @@ class StatisticsService extends Service
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 计算纵向小计 (第 33 行 = 9 到 28 行的累加,跳过预留行)
|
|
|
+ // --- 纵向计算与利润分析 (全列应用) ---
|
|
|
foreach ($columnKeys as $col) {
|
|
|
+ // 33. 销售支出小计 = 9 到 28 行累加 (所有列都算)
|
|
|
$subTotal = 0;
|
|
|
for ($r = 9; $r <= 28; $r++) {
|
|
|
$subTotal += (float)($columns[$col][$r] ?? 0);
|
|
|
}
|
|
|
$columns[$col][33] = $subTotal;
|
|
|
- }
|
|
|
|
|
|
- // 7. 最终格式化输出
|
|
|
+ // 34. 实际利润 = 第 8 行(回款销售毛利) - 第 33 行(销售支出小计)
|
|
|
+ $realProfit = (float)$columns[$col][8] - (float)$columns[$col][33];
|
|
|
+ $columns[$col][34] = $realProfit;
|
|
|
+
|
|
|
+ // 39. 开票净利润 (初始等于实际利润)
|
|
|
+ $columns[$col][39] = $realProfit;
|
|
|
|
|
|
+ // 35-38 行保持初始化为空 (用于手动填写或预留)
|
|
|
+ $columns[$col][35] = '';
|
|
|
+ $columns[$col][36] = '';
|
|
|
+ $columns[$col][37] = '';
|
|
|
+ $columns[$col][38] = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 7. 最终格式化输出 (保持行号作为 Key)
|
|
|
$finalData = [];
|
|
|
- for ($row = 5; $row <= 33; $row++) {
|
|
|
- // 关键:29-32行我们直接不生成数据,或者生成空
|
|
|
- if ($row >= 29 && $row <= 32) continue;
|
|
|
+ for ($row = 5; $row <= 39; $row++) {
|
|
|
+ if ($row >= 29 && $row <= 32) continue; // 跳过 B 列的那四个“其他”空行
|
|
|
|
|
|
$rowData = [];
|
|
|
foreach ($columnKeys as $colLetter) {
|
|
|
- $val = $columns[$colLetter][$row] ?? 0;
|
|
|
- $rowData[] = ($val == 0) ? '0.00' : number_format($val, 2, '.', '');
|
|
|
+ $val = $columns[$colLetter][$row] ?? '';
|
|
|
+ if ($val === '' || $val === 0 || $val === 0.0) {
|
|
|
+ $rowData[] = '0.00';
|
|
|
+ } else {
|
|
|
+ $rowData[] = is_numeric($val) ? number_format((float)$val, 2, '.', '') : $val;
|
|
|
+ }
|
|
|
}
|
|
|
- // 使用行号作为 Key
|
|
|
$finalData[$row] = $rowData;
|
|
|
}
|
|
|
|