|
@@ -1,951 +1,823 @@
|
|
|
<?php
|
|
<?php
|
|
|
|
|
|
|
|
-
|
|
|
|
|
namespace app\api\controller;
|
|
namespace app\api\controller;
|
|
|
|
|
|
|
|
use app\common\controller\Api;
|
|
use app\common\controller\Api;
|
|
|
|
|
+use think\Db;
|
|
|
|
|
+use think\Queue;
|
|
|
|
|
+use app\service\UnifiedCostCalculationService;
|
|
|
|
|
+use think\Request;
|
|
|
|
|
|
|
|
class CostCalculation extends Api
|
|
class CostCalculation extends Api
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
protected $noNeedLogin = ['*'];
|
|
protected $noNeedLogin = ['*'];
|
|
|
protected $noNeedRight = ['*'];
|
|
protected $noNeedRight = ['*'];
|
|
|
|
|
|
|
|
- // 车间常量
|
|
|
|
|
- const WORKSHOP_ROLLER_PRESS = '03、卷凹机组';
|
|
|
|
|
- const WORKSHOP_LIST_ALL = ['凹丝印车间', '胶印车间', '印后车间', '检验车间'];
|
|
|
|
|
-
|
|
|
|
|
- // 科目名称关键词
|
|
|
|
|
- const SUBJECT_WASTE_GAS = '废气处理';
|
|
|
|
|
- const SUBJECT_BOILER = '锅炉';
|
|
|
|
|
- const SUBJECT_HOT_WATER_BOILER = '热水锅炉';
|
|
|
|
|
- const SUBJECT_AIR_COMPRESSOR_A = '空压机A';
|
|
|
|
|
- const SUBJECT_AIR_COMPRESSOR_B = '空压机B';
|
|
|
|
|
- const SUBJECT_VACUUM_BLOWER_A = '真空鼓风机A';
|
|
|
|
|
- const SUBJECT_VACUUM_BLOWER_B = '真空鼓风机B';
|
|
|
|
|
- const SUBJECT_CENTRAL_AIR_CONDITIONER_A = '中央空调A';
|
|
|
|
|
- const SUBJECT_CENTRAL_AIR_CONDITIONER_B = '中央空调B';
|
|
|
|
|
- const SUBJECT_TOTAL_TO_APPORTION = '待分摊总额';
|
|
|
|
|
|
|
+// // 楼层编组映射(优化版)
|
|
|
|
|
+// const FLOOR_GROUP_MAP = [
|
|
|
|
|
+// '1' => ['02、胶印机组', '03、卷凹机组', '06、单凹机组', '05、圆切机组', '04、圆烫机组', '10、模切机组', '09、烫金机组'], // 1楼编组
|
|
|
|
|
+// '2' => ['01、切纸机组', '11、检品机组', '07、丝印机组', '12、覆膜机组', '08、喷码机组'], // 2楼编组
|
|
|
|
|
+// ];
|
|
|
|
|
+//
|
|
|
|
|
+// // 科目名称常量(简化版)
|
|
|
|
|
+// const SUBJECT_WASTE_GAS = '废气处理(RTO)';
|
|
|
|
|
+// const SUBJECT_BOILER = '锅炉';
|
|
|
|
|
+// const SUBJECT_AIR_COMPRESSOR = '空压机';
|
|
|
|
|
+// const SUBJECT_HOT_WATER_BOILER = '热水锅炉';
|
|
|
|
|
+// const SUBJECT_VACUUM_BLOWER = '真空鼓风机';
|
|
|
|
|
+// const SUBJECT_CENTRAL_AIR_CONDITIONER = '中央空调';
|
|
|
|
|
+// const SUBJECT_TOTAL_TO_APPORTION = '待分摊总额';
|
|
|
|
|
+//
|
|
|
|
|
+// // 需要分配到卷凹机组的科目列表
|
|
|
|
|
+// const ROLL_COATER_ONLY_SUBJECTS = [
|
|
|
|
|
+// self::SUBJECT_BOILER,
|
|
|
|
|
+// self::SUBJECT_HOT_WATER_BOILER,
|
|
|
|
|
+// ];
|
|
|
|
|
+//
|
|
|
|
|
+// // 简化科目列表
|
|
|
|
|
+// const SIMPLIFIED_SUBJECTS = [
|
|
|
|
|
+// self::SUBJECT_WASTE_GAS,
|
|
|
|
|
+// self::SUBJECT_BOILER,
|
|
|
|
|
+// self::SUBJECT_AIR_COMPRESSOR,
|
|
|
|
|
+// self::SUBJECT_HOT_WATER_BOILER,
|
|
|
|
|
+// self::SUBJECT_VACUUM_BLOWER,
|
|
|
|
|
+// self::SUBJECT_CENTRAL_AIR_CONDITIONER,
|
|
|
|
|
+// self::SUBJECT_TOTAL_TO_APPORTION,
|
|
|
|
|
+// ];
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 根据设备编号获取楼层信息
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getFloorByMachineCode($machineCode)
|
|
|
|
|
+// {
|
|
|
|
|
+// static $machineFloorCache = [];
|
|
|
|
|
+//
|
|
|
|
|
+// if (isset($machineFloorCache[$machineCode])) {
|
|
|
|
|
+// return $machineFloorCache[$machineCode];
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 查询设备编组
|
|
|
|
|
+// $group = Db::name('设备_基本资料')
|
|
|
|
|
+// ->where('sys_sbID', '<>','')
|
|
|
|
|
+// ->where('设备编号', $machineCode)
|
|
|
|
|
+// ->value('设备编组');
|
|
|
|
|
+//
|
|
|
|
|
+// if (!$group) {
|
|
|
|
|
+// $machineFloorCache[$machineCode] = null;
|
|
|
|
|
+// return null;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 根据编组判断楼层
|
|
|
|
|
+// foreach (self::FLOOR_GROUP_MAP as $floor => $groups) {
|
|
|
|
|
+// foreach ($groups as $groupName) {
|
|
|
|
|
+// if (strpos($group, $groupName) !== false) {
|
|
|
|
|
+// $machineFloorCache[$machineCode] = $floor;
|
|
|
|
|
+// return $floor;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $machineFloorCache[$machineCode] = null;
|
|
|
|
|
+// return null;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 根据楼层获取该楼层的所有机台
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getMachinesByFloor($floor, $month)
|
|
|
|
|
+// {
|
|
|
|
|
+// // 获取该楼层的所有编组
|
|
|
|
|
+// $groups = self::FLOOR_GROUP_MAP[$floor] ?? [];
|
|
|
|
|
+// if (empty($groups)) {
|
|
|
|
|
+// return [];
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// try {
|
|
|
|
|
+// // 方法1:使用更简单的查询条件构建方式
|
|
|
|
|
+// $query = Db::name('成本v23_月度成本明细')
|
|
|
|
|
+// ->alias('c')
|
|
|
|
|
+// ->join('设备_基本资料 e', 'c.sczl_jtbh = e.设备编号', 'LEFT')
|
|
|
|
|
+// ->where('c.sys_ny', $month)
|
|
|
|
|
+// ->where('e.设备编号', '<>', '')
|
|
|
|
|
+// ->whereIn('e.设备编组', $groups);
|
|
|
|
|
+//
|
|
|
|
|
+//
|
|
|
|
|
+// $query->field([
|
|
|
|
|
+// 'c.sczl_jtbh' => '机台编号',
|
|
|
|
|
+// 'c.占用机时',
|
|
|
|
|
+// 'e.设备编组',
|
|
|
|
|
+// 'c.sczl_gdbh' => '工单编号',
|
|
|
|
|
+// 'c.sczl_yjno' => '印件号',
|
|
|
|
|
+// 'c.sczl_gxh' => '工序号',
|
|
|
|
|
+// 'c.Uniqid',
|
|
|
|
|
+// 'c.车间名称'
|
|
|
|
|
+// ]);
|
|
|
|
|
+//
|
|
|
|
|
+// $machines = $query->select();
|
|
|
|
|
+//
|
|
|
|
|
+// return $machines ?: [];
|
|
|
|
|
+//
|
|
|
|
|
+// } catch (\Exception $e) {
|
|
|
|
|
+// throw new \Exception('查询机台数据失败: ' . $e->getMessage());
|
|
|
|
|
+//
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 获取所有机台(不分楼层)
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getAllMachines($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// return Db::name('成本v23_月度成本明细')
|
|
|
|
|
+// ->alias('c')
|
|
|
|
|
+// ->join('设备_基本资料 e', 'c.sczl_jtbh = e.设备编号')
|
|
|
|
|
+// ->where('c.sys_ny', $month)
|
|
|
|
|
+// ->where('e.设备编号', '<>', '')
|
|
|
|
|
+// ->field([
|
|
|
|
|
+// 'c.sczl_jtbh' => '机台编号',
|
|
|
|
|
+// 'c.占用机时',
|
|
|
|
|
+// 'e.设备编组',
|
|
|
|
|
+// 'c.sczl_gdbh' => '工单编号',
|
|
|
|
|
+// 'c.sczl_yjno' => '印件号',
|
|
|
|
|
+// 'c.sczl_gxh' => '工序号',
|
|
|
|
|
+// 'c.Uniqid',
|
|
|
|
|
+// 'c.车间名称'
|
|
|
|
|
+// ])
|
|
|
|
|
+// ->select();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 获取卷凹机组的所有机台
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getRollCoaterMachines($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// return Db::name('成本v23_月度成本明细')
|
|
|
|
|
+// ->alias('c')
|
|
|
|
|
+// ->join('设备_基本资料 e', 'c.sczl_jtbh = e.设备编号')
|
|
|
|
|
+// ->where('c.sys_ny', $month)
|
|
|
|
|
+// ->where('e.设备编号', '<>', '')
|
|
|
|
|
+// ->where('e.设备编组', 'like', '%03、卷凹机组%')
|
|
|
|
|
+// ->field([
|
|
|
|
|
+// 'c.sczl_jtbh' => '机台编号',
|
|
|
|
|
+// 'c.占用机时',
|
|
|
|
|
+// 'e.设备编组',
|
|
|
|
|
+// 'c.sczl_gdbh' => '工单编号',
|
|
|
|
|
+// 'c.sczl_yjno' => '印件号',
|
|
|
|
|
+// 'c.sczl_gxh' => '工序号',
|
|
|
|
|
+// 'c.Uniqid',
|
|
|
|
|
+// 'c.车间名称'
|
|
|
|
|
+// ])
|
|
|
|
|
+// ->select();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 主计算方法
|
|
|
|
|
+// */
|
|
|
|
|
+// public function costCalculation()
|
|
|
|
|
+// {
|
|
|
|
|
+// if (!$this->request->isGet()) {
|
|
|
|
|
+// $this->error('请求错误');
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $param = $this->request->param();
|
|
|
|
|
+// if (empty($param['month'])) {
|
|
|
|
|
+// $this->error('请选择月份');
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $month = $param['month'];
|
|
|
|
|
+// $sysId = $param['sys_id'] ?? '';
|
|
|
|
|
+//
|
|
|
|
|
+//
|
|
|
|
|
+// // 计算分摊
|
|
|
|
|
+// $apportionmentResults = $this->calculateApportionment($month);
|
|
|
|
|
+//
|
|
|
|
|
+// // 格式化结果并保存
|
|
|
|
|
+// $formattedResults = $this->formatApportionmentResults($apportionmentResults, $month, $sysId);
|
|
|
|
|
+// $this->saveApportionmentCoefficients($formattedResults, $month);
|
|
|
|
|
+//
|
|
|
|
|
+// // 进行二次分配(到工单)
|
|
|
|
|
+// $this->allocateToWorkOrders($month);
|
|
|
|
|
+//
|
|
|
|
|
+// $this->success('成本分摊计算成功');
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 计算分摊(核心方法)
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function calculateApportionment($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// // 获取水电气分摊数据
|
|
|
|
|
+// $utilityData = $this->getUtilityData($month);
|
|
|
|
|
+//
|
|
|
|
|
+// $results = [];
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($utilityData as $item) {
|
|
|
|
|
+// $subject = $this->simplifySubjectName($item['科目名称']);
|
|
|
|
|
+// $amount = $this->calculateAmount($item);
|
|
|
|
|
+//
|
|
|
|
|
+// if ($subject === self::SUBJECT_TOTAL_TO_APPORTION) {
|
|
|
|
|
+// // 待分摊总额按楼层分摊
|
|
|
|
|
+// $floorResults = $this->allocateByFloor($amount, $month);
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($floorResults as $floor => $machineAllocations) {
|
|
|
|
|
+// foreach ($machineAllocations as $machineCode => $machineAmount) {
|
|
|
|
|
+// if (!isset($results[$machineCode])) {
|
|
|
|
|
+// $results[$machineCode] = [];
|
|
|
|
|
+// }
|
|
|
|
|
+// $results[$machineCode][$subject] = $machineAmount;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// } elseif (in_array($subject, self::ROLL_COATER_ONLY_SUBJECTS)) {
|
|
|
|
|
+// // 锅炉和热水锅炉只分配到卷凹机组
|
|
|
|
|
+// $rollCoaterResults = $this->allocateToRollCoaterOnly($amount, $month);
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($rollCoaterResults as $machineCode => $machineAmount) {
|
|
|
|
|
+// if (!isset($results[$machineCode])) {
|
|
|
|
|
+// $results[$machineCode] = [];
|
|
|
|
|
+// }
|
|
|
|
|
+// if (!isset($results[$machineCode][$subject])) {
|
|
|
|
|
+// $results[$machineCode][$subject] = $machineAmount;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// } else {
|
|
|
|
|
+// // 其他科目按所有机台分摊
|
|
|
|
|
+// $globalResults = $this->allocateGlobally($amount, $month);
|
|
|
|
|
+// foreach ($globalResults as $machineCode => $machineAmount) {
|
|
|
|
|
+// if (!isset($results[$machineCode])) {
|
|
|
|
|
+// $results[$machineCode] = [];
|
|
|
|
|
+// }
|
|
|
|
|
+// $results[$machineCode][$subject] = $machineAmount;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// return $results;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 获取水电气数据
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getUtilityData($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// return Db::name('成本_各月水电气')
|
|
|
|
|
+// ->where('Sys_ny', $month)
|
|
|
|
|
+// ->whereLike('费用类型', '%分摊%')
|
|
|
|
|
+// ->select();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 简化科目名称
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function simplifySubjectName($subjectName)
|
|
|
|
|
+// {
|
|
|
|
|
+// $simplifiedMap = [
|
|
|
|
|
+// '废气处理(RTO)' => self::SUBJECT_WASTE_GAS,
|
|
|
|
|
+// '锅炉' => self::SUBJECT_BOILER,
|
|
|
|
|
+// '热水锅炉' => self::SUBJECT_HOT_WATER_BOILER,
|
|
|
|
|
+// '空压机' => self::SUBJECT_AIR_COMPRESSOR,
|
|
|
|
|
+// '真空鼓风机' => self::SUBJECT_VACUUM_BLOWER,
|
|
|
|
|
+// '中央空调' => self::SUBJECT_CENTRAL_AIR_CONDITIONER,
|
|
|
|
|
+// '待分摊总额' => self::SUBJECT_TOTAL_TO_APPORTION,
|
|
|
|
|
+// ];
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($simplifiedMap as $keyword => $simplified) {
|
|
|
|
|
+// if (strpos($subjectName, $keyword) !== false) {
|
|
|
|
|
+// return $simplified;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// return $subjectName;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 计算金额
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function calculateAmount($item)
|
|
|
|
|
+// {
|
|
|
|
|
+// $electricity = ($this->getSafeNumericValue($item['耗电量']) * $this->getSafeNumericValue($item['单位电价']));
|
|
|
|
|
+// $gas = ($this->getSafeNumericValue($item['耗气量']) * $this->getSafeNumericValue($item['单位气价']));
|
|
|
|
|
+//
|
|
|
|
|
+// return round($electricity + $gas, 2);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 按楼层分摊
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function allocateByFloor($totalAmount, $month)
|
|
|
|
|
+// {
|
|
|
|
|
+// $results = [];
|
|
|
|
|
+//
|
|
|
|
|
+// // 计算每个楼层的总机时
|
|
|
|
|
+// $floorTotalHours = [];
|
|
|
|
|
+// foreach ([1, 2] as $floor) {
|
|
|
|
|
+// $machines = $this->getMachinesByFloor($floor, $month);
|
|
|
|
|
+// $totalHours = 0;
|
|
|
|
|
+// foreach ($machines as $machine) {
|
|
|
|
|
+// $totalHours += $machine['占用机时'];
|
|
|
|
|
+// }
|
|
|
|
|
+// $floorTotalHours[$floor] = $totalHours;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $allFloorsTotal = array_sum($floorTotalHours);
|
|
|
|
|
+// if ($allFloorsTotal <= 0) {
|
|
|
|
|
+// return $results;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 按楼层比例分摊
|
|
|
|
|
+// foreach ($floorTotalHours as $floor => $hours) {
|
|
|
|
|
+// $floorAmount = round($totalAmount * ($hours / $allFloorsTotal), 2);
|
|
|
|
|
+//
|
|
|
|
|
+// // 在楼层内按机台分摊
|
|
|
|
|
+// $machines = $this->getMachinesByFloor($floor, $month);
|
|
|
|
|
+// $floorResults = $this->allocateWithinGroup($floorAmount, $machines);
|
|
|
|
|
+//
|
|
|
|
|
+// $results[$floor] = $floorResults;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// return $results;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 全局分摊(不分楼层)
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function allocateGlobally($totalAmount, $month)
|
|
|
|
|
+// {
|
|
|
|
|
+// $machines = $this->getAllMachines($month);
|
|
|
|
|
+// return $this->allocateWithinGroup($totalAmount, $machines);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 只分摊到卷凹机组
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function allocateToRollCoaterOnly($totalAmount, $month)
|
|
|
|
|
+// {
|
|
|
|
|
+// $machines = $this->getRollCoaterMachines($month);
|
|
|
|
|
+// return $this->allocateWithinGroup($totalAmount, $machines);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 在组内按机台运行时间分摊
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function allocateWithinGroup($totalAmount, $machines)
|
|
|
|
|
+// {
|
|
|
|
|
+// $results = [];
|
|
|
|
|
+//
|
|
|
|
|
+// if (empty($machines)) {
|
|
|
|
|
+// return $results;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $totalHours = 0;
|
|
|
|
|
+// $machineHours = [];
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($machines as $machine) {
|
|
|
|
|
+// $hours = floatval($machine['占用机时']);
|
|
|
|
|
+// $machineCode = $machine['机台编号'];
|
|
|
|
|
+//
|
|
|
|
|
+// if ($hours > 0) {
|
|
|
|
|
+// $totalHours += $hours;
|
|
|
|
|
+// if (!isset($machineHours[$machineCode])) {
|
|
|
|
|
+// $machineHours[$machineCode] = $hours;
|
|
|
|
|
+// } else {
|
|
|
|
|
+// $machineHours[$machineCode] += $hours;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// if ($totalHours <= 0) {
|
|
|
|
|
+// return $results;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($machineHours as $machineCode => $hours) {
|
|
|
|
|
+// $results[$machineCode] = round($totalAmount * ($hours / $totalHours), 2);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// return $results;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 格式化分摊结果
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function formatApportionmentResults($results, $month, $sysId)
|
|
|
|
|
+// {
|
|
|
|
|
+// $formatted = [];
|
|
|
|
|
+// $now = date('Y-m-d H:i:s');
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($results as $machineCode => $subjects) {
|
|
|
|
|
+// foreach ($subjects as $subject => $amount) {
|
|
|
|
|
+// $formatted[] = [
|
|
|
|
|
+// 'Sys_ny' => $month,
|
|
|
|
|
+// '科目名称' => $subject,
|
|
|
|
|
+// '设备编号' => $machineCode,
|
|
|
|
|
+// '分摊系数' => 1,
|
|
|
|
|
+// '分摊金额' => $amount,
|
|
|
|
|
+// 'Sys_id' => $sysId,
|
|
|
|
|
+// 'Sys_rq' => $now,
|
|
|
|
|
+// ];
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// return $formatted;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 保存分摊系数
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function saveApportionmentCoefficients($data, $month)
|
|
|
|
|
+// {
|
|
|
|
|
+// // 删除旧数据
|
|
|
|
|
+// Db::name('成本_各月分摊系数')->where('Sys_ny', $month)->delete();
|
|
|
|
|
+//
|
|
|
|
|
+// if (!empty($data)) {
|
|
|
|
|
+// $sql = Db::name('成本_各月分摊系数')->fetchSql(true)->insertAll($data);
|
|
|
|
|
+// \db()->query($sql);
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 分摊到工单(二次分配)
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function allocateToWorkOrders($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// // 获取所有机台的分摊系数(每机时费用)
|
|
|
|
|
+// $coefficients = $this->getMachineCoefficients($month);
|
|
|
|
|
+//
|
|
|
|
|
+// // 获取所有机台的工单
|
|
|
|
|
+// $workOrders = $this->getWorkOrdersByMonth($month);
|
|
|
|
|
+//
|
|
|
|
|
+// $updates = [];
|
|
|
|
|
+// foreach ($workOrders as $order) {
|
|
|
|
|
+// $machineCode = $order['机台编号'];
|
|
|
|
|
+//
|
|
|
|
|
+// if (!isset($coefficients[$machineCode])) {
|
|
|
|
|
+// continue;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $machineCoeffs = $coefficients[$machineCode];
|
|
|
|
|
+// $hours = floatval($order['占用机时']);
|
|
|
|
|
+//
|
|
|
|
|
+// if ($hours <= 0) {
|
|
|
|
|
+// continue;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 计算各科目分摊金额
|
|
|
|
|
+// $updateData = [
|
|
|
|
|
+// '直接水电' => round($hours * 0.69, 2), // 直接水电费
|
|
|
|
|
+// ];
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($machineCoeffs as $subject => $rate) {
|
|
|
|
|
+// $subjectKey = ($subject === '待分摊总额') ? '分摊水电' : $subject;
|
|
|
|
|
+// $updateData[$subjectKey] = round($hours * $rate, 2);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 构建更新条件
|
|
|
|
|
+// $where = [
|
|
|
|
|
+// 'sys_ny' => $month,
|
|
|
|
|
+// 'sczl_gdbh' => $order['工单编号'],
|
|
|
|
|
+// 'sczl_yjno' => $order['印件号'],
|
|
|
|
|
+// 'sczl_gxh' => $order['工序号'],
|
|
|
|
|
+// 'sczl_jtbh' => $machineCode,
|
|
|
|
|
+// ];
|
|
|
|
|
+//
|
|
|
|
|
+// $updates[] = [
|
|
|
|
|
+// 'where' => $where,
|
|
|
|
|
+// 'data' => $updateData
|
|
|
|
|
+// ];
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 批量更新
|
|
|
|
|
+// $this->batchUpdateWorkOrders($updates, $month);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 获取机台分摊系数(每机时费用)
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getMachineCoefficients($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// // 查询分摊系数和机台运行时间
|
|
|
|
|
+// $data = Db::name('成本_各月分摊系数')
|
|
|
|
|
+// ->alias('c')
|
|
|
|
|
+// ->join('成本v23_月度成本明细 d', 'd.sys_ny = c.Sys_ny AND d.sczl_jtbh = c.设备编号')
|
|
|
|
|
+// ->where('c.Sys_ny', $month)
|
|
|
|
|
+// ->field([
|
|
|
|
|
+// 'c.设备编号',
|
|
|
|
|
+// 'c.科目名称',
|
|
|
|
|
+// 'c.分摊金额',
|
|
|
|
|
+// 'SUM(d.占用机时)' => 'total_hours'
|
|
|
|
|
+// ])
|
|
|
|
|
+// ->group('c.设备编号, c.科目名称')
|
|
|
|
|
+// ->select();
|
|
|
|
|
+//
|
|
|
|
|
+// $coefficients = [];
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($data as $item) {
|
|
|
|
|
+// $machineCode = $item['设备编号'];
|
|
|
|
|
+// $subject = $item['科目名称'];
|
|
|
|
|
+// $amount = floatval($item['分摊金额']);
|
|
|
|
|
+// $hours = floatval($item['total_hours']);
|
|
|
|
|
+//
|
|
|
|
|
+// if ($hours > 0) {
|
|
|
|
|
+// $rate = round($amount / $hours, 4);
|
|
|
|
|
+//
|
|
|
|
|
+// if (!isset($coefficients[$machineCode])) {
|
|
|
|
|
+// $coefficients[$machineCode] = [];
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// $coefficients[$machineCode][$subject] = $rate;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// return $coefficients;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 获取所有工单
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getWorkOrdersByMonth($month)
|
|
|
|
|
+// {
|
|
|
|
|
+// return Db::name('成本v23_月度成本明细')
|
|
|
|
|
+// ->where('sys_ny', $month)
|
|
|
|
|
+// ->field([
|
|
|
|
|
+// 'sczl_gdbh' => '工单编号',
|
|
|
|
|
+// 'sczl_yjno' => '印件号',
|
|
|
|
|
+// 'sczl_gxh' => '工序号',
|
|
|
|
|
+// 'sczl_jtbh' => '机台编号',
|
|
|
|
|
+// '占用机时'
|
|
|
|
|
+// ])
|
|
|
|
|
+// ->select();
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 批量更新工单数据
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function batchUpdateWorkOrders($updates, $month)
|
|
|
|
|
+// {
|
|
|
|
|
+// $db = Db::name('成本v23_月度成本明细');
|
|
|
|
|
+//
|
|
|
|
|
+// foreach ($updates as $update) {
|
|
|
|
|
+// $sql = $db->where($update['where'])->fetchSql(true)->update($update['data']);
|
|
|
|
|
+// $db->query($sql);
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// /**
|
|
|
|
|
+// * 安全数值获取
|
|
|
|
|
+// */
|
|
|
|
|
+// protected function getSafeNumericValue($value)
|
|
|
|
|
+// {
|
|
|
|
|
+// if ($value === null || $value === '' || $value === false) {
|
|
|
|
|
+// return 0;
|
|
|
|
|
+// }
|
|
|
|
|
+// return floatval($value);
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+// app/controller/UnifiedCostController.php
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 统一的安全数值获取方法
|
|
|
|
|
- * 处理空字符串和null值,转换为0
|
|
|
|
|
|
|
+ * 执行成本计算
|
|
|
|
|
+ * @ApiMethod POST
|
|
|
|
|
+ * @param string month 年月
|
|
|
|
|
+ * @param string sys_id 系统ID
|
|
|
*/
|
|
*/
|
|
|
- protected function getSafeNumericValue($value)
|
|
|
|
|
|
|
+ public function calculate()
|
|
|
{
|
|
{
|
|
|
- if ($value === null || $value === '' || $value === false) {
|
|
|
|
|
- return 0;
|
|
|
|
|
|
|
+ if (Request::instance()->isPost() == false) {
|
|
|
|
|
+ $this->error('非法请求');
|
|
|
}
|
|
}
|
|
|
- return floatval($value);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 安全的金额计算
|
|
|
|
|
- */
|
|
|
|
|
- protected function calculateSafeAmount($quantity, $unitPrice)
|
|
|
|
|
- {
|
|
|
|
|
- $safeQuantity = $this->getSafeNumericValue($quantity);
|
|
|
|
|
- $safeUnitPrice = $this->getSafeNumericValue($unitPrice);
|
|
|
|
|
- return $safeQuantity * $safeUnitPrice;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $params = Request::instance()->param();
|
|
|
|
|
|
|
|
- public function costCalculation()
|
|
|
|
|
- {
|
|
|
|
|
- if (!$this->request->isGet()) {
|
|
|
|
|
- $this->error('请求错误');
|
|
|
|
|
|
|
+ if (!isset($params['month']) || empty($params['month'])) {
|
|
|
|
|
+ $this->error('月份参数错误');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- $param = $this->request->param();
|
|
|
|
|
- if (empty($param['month'])) {
|
|
|
|
|
- $this->error('请选择月份');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $month = $param['month'];
|
|
|
|
|
|
|
+ $month = trim($params['month']);
|
|
|
|
|
+ $sysId = $params['sys_id'] ?? '';
|
|
|
|
|
|
|
|
- // 计算车间水电气分摊(返回统计结果)
|
|
|
|
|
- $apportionmentResults = $this->apportionmentOne($month);
|
|
|
|
|
-
|
|
|
|
|
- // 格式化最终结果
|
|
|
|
|
- $formattedResults = $this->formatFinalResults($apportionmentResults,$month,$param['sys_id']);
|
|
|
|
|
- $machine = [];
|
|
|
|
|
- foreach ($formattedResults as $formattedResult) {
|
|
|
|
|
- $machine[] = $formattedResult['设备编号'];
|
|
|
|
|
- }
|
|
|
|
|
- $machineList = array_unique($machine);
|
|
|
|
|
- $machineWorkOrder = [];
|
|
|
|
|
- foreach ($machineList as $machine) {
|
|
|
|
|
- $machineWorkOrder[$machine] = $this->getMachineWorkOrder($machine, $month);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $apportionData = db('成本_各月分摊系数')->where(['Sys_ny' => $month])->select();
|
|
|
|
|
- if (!empty($apportionData)) {
|
|
|
|
|
- db('成本_各月分摊系数')->where(['Sys_ny' => $month])->delete();
|
|
|
|
|
- }
|
|
|
|
|
- $apportionSql = db('成本_各月分摊系数')->fetchSql(true)->insertAll($formattedResults);
|
|
|
|
|
- $apportionResults = db()->query($apportionSql);
|
|
|
|
|
-
|
|
|
|
|
- //查询车间机台色度数
|
|
|
|
|
- $machineTotal = $this->getMachineTotal($month);
|
|
|
|
|
- $data = [];
|
|
|
|
|
- foreach ($machineWorkOrder as $machineCode => $orders) {
|
|
|
|
|
- // 检查机台编号是否存在于第二个数组中
|
|
|
|
|
- if (!isset($machineTotal[$machineCode])) {
|
|
|
|
|
- continue; // 如果机台在分摊数组中不存在,跳过
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 检查是否有正在执行的任务
|
|
|
|
|
+ $runningTask = Db::name('queue_tasks')
|
|
|
|
|
+ ->where('task_type', 'cost_calculation')
|
|
|
|
|
+ ->where('task_data', 'like', '%"month":"' . $month . '"%')
|
|
|
|
|
+ ->where('status', 'in', ['pending', 'processing'])
|
|
|
|
|
+ ->find();
|
|
|
|
|
|
|
|
- $machineRates = $machineTotal[$machineCode]; // 获取该机台的费用单价
|
|
|
|
|
-
|
|
|
|
|
- // 遍历该机台下的所有工单
|
|
|
|
|
- foreach ($orders as $order) {
|
|
|
|
|
- $occupationHours = (float)$order['占用机时']; // 占用机时
|
|
|
|
|
-
|
|
|
|
|
- // 创建新记录(基础信息)
|
|
|
|
|
- $newRecord = [
|
|
|
|
|
- 'sczl_gdbh' => $order['工单编号'],
|
|
|
|
|
- 'sczl_yjno' => $order['印件号'],
|
|
|
|
|
- 'sczl_gxh' => $order['工序号'],
|
|
|
|
|
- 'sczl_jtbh' => $order['机台编号']
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- // 动态添加所有科目分摊金额(基于第二个数组中的科目名称)
|
|
|
|
|
- foreach ($machineRates as $subject => $rate) {
|
|
|
|
|
- if ($subject === '待分摊总额') {
|
|
|
|
|
- $subject = '分摊水电';
|
|
|
|
|
- }
|
|
|
|
|
- $newRecord[$subject] = round($occupationHours * $rate, 2);
|
|
|
|
|
- $newRecord['直接水电'] = round($occupationHours * 0.69, 2);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $data[] = $newRecord;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- $i = 0;
|
|
|
|
|
- foreach ($data as $item) {
|
|
|
|
|
- $gdbh = $item['sczl_gdbh'];
|
|
|
|
|
- $yjno = $item['sczl_yjno'];
|
|
|
|
|
- $gxh = $item['sczl_gxh'];
|
|
|
|
|
- $jtbh = $item['sczl_jtbh'];
|
|
|
|
|
- unset($item['sczl_gdbh'], $item['sczl_yjno'], $item['sczl_gxh'], $item['sczl_jtbh']);
|
|
|
|
|
- $sql = db('成本v23_月度成本明细')
|
|
|
|
|
- ->where([
|
|
|
|
|
- 'sys_ny' => $month,
|
|
|
|
|
- 'sczl_gdbh' => $gdbh,
|
|
|
|
|
- 'sczl_yjno' => $yjno,
|
|
|
|
|
- 'sczl_gxh' => $gxh,
|
|
|
|
|
- 'sczl_jtbh' => $jtbh,
|
|
|
|
|
- ])
|
|
|
|
|
- ->fetchSql(true)
|
|
|
|
|
- ->update($item);
|
|
|
|
|
- $res = db()->query($sql);
|
|
|
|
|
- if ($res === false) {
|
|
|
|
|
- $i++;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if ($runningTask) {
|
|
|
|
|
+ $this->success('该月份的成本计算任务已在执行中,请勿重复提交');
|
|
|
}
|
|
}
|
|
|
- if ($i > 0) {
|
|
|
|
|
- $this->error('失败');
|
|
|
|
|
- }else{
|
|
|
|
|
- $this->success('成功');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
|
|
+ // 检查工资计算是否在执行中(可选)
|
|
|
|
|
+ $salaryRunning = Db::name('queue_tasks')
|
|
|
|
|
+ ->where('task_type', 'salary_calculation')
|
|
|
|
|
+ ->where('task_data', 'like', '%"date":"' . $month . '"%')
|
|
|
|
|
+ ->where('status', 'in', ['pending', 'processing'])
|
|
|
|
|
+ ->find();
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 计算水电气分摊费用(优化版)
|
|
|
|
|
- */
|
|
|
|
|
- protected function apportionmentOne($month)
|
|
|
|
|
- {
|
|
|
|
|
- $utilityList = db('成本_各月水电气')
|
|
|
|
|
- ->where('Sys_ny', $month)
|
|
|
|
|
- ->whereLike('费用类型', '%分摊%')
|
|
|
|
|
- ->select();
|
|
|
|
|
-
|
|
|
|
|
- if (empty($utilityList)) {
|
|
|
|
|
- return [];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 初始化统计数据结构
|
|
|
|
|
- $machineSummary = []; // 按机台统计
|
|
|
|
|
- $subjectSummary = []; // 按科目统计
|
|
|
|
|
- $workshopSummary = []; // 按车间统计
|
|
|
|
|
- $apportionmentResults = []; // 原始分摊结果
|
|
|
|
|
- $allMachineData = []; // 所有机台数据
|
|
|
|
|
-
|
|
|
|
|
- // 先处理所有分摊项目
|
|
|
|
|
- foreach ($utilityList as $item) {
|
|
|
|
|
- // 确保数值安全
|
|
|
|
|
- $item['耗电量'] = $this->getSafeNumericValue($item['耗电量']);
|
|
|
|
|
- $item['单位电价'] = $this->getSafeNumericValue($item['单位电价']);
|
|
|
|
|
- $item['耗气量'] = $this->getSafeNumericValue($item['耗气量']);
|
|
|
|
|
- $item['单位气价'] = $this->getSafeNumericValue($item['单位气价']);
|
|
|
|
|
-
|
|
|
|
|
- $result = $this->processUtilityItem($item, $month);
|
|
|
|
|
- if ($result) {
|
|
|
|
|
- $apportionmentResults[] = $result;
|
|
|
|
|
-
|
|
|
|
|
- // 合并所有机台数据
|
|
|
|
|
- $this->mergeMachineData($result['data'], $allMachineData, $item['科目名称']);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if ($salaryRunning) {
|
|
|
|
|
+ $this->error('该月份的工资计算正在执行中,建议等待工资计算完成后再进行成本计算');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 按机台+科目进行汇总统计
|
|
|
|
|
- $this->summarizeByMachineAndSubject($allMachineData, $machineSummary, $subjectSummary, $workshopSummary);
|
|
|
|
|
-
|
|
|
|
|
- // 对统计结果进行排序
|
|
|
|
|
- ksort($machineSummary);
|
|
|
|
|
- return $machineSummary;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 合并所有机台数据
|
|
|
|
|
- */
|
|
|
|
|
- protected function mergeMachineData($machineData, &$allMachineData, $subjectName)
|
|
|
|
|
- {
|
|
|
|
|
- if (empty($machineData)) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- foreach ($machineData as $machine) {
|
|
|
|
|
- $machineId = $machine['机台编号'] ?? '';
|
|
|
|
|
- $workshop = $machine['车间名称'] ?? '未知车间';
|
|
|
|
|
- $workOrder = $machine['工单编号'] ?? '';
|
|
|
|
|
- $processNo = $machine['工序号'] ?? '';
|
|
|
|
|
- $printNo = $machine['印件号'] ?? '';
|
|
|
|
|
- $machineTime = floatval($machine['占用机时'] ?? 0);
|
|
|
|
|
- $uniqid = $machine['Uniqid'] ?? '';
|
|
|
|
|
-
|
|
|
|
|
- if (empty($machineId)) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 初始化机台数据
|
|
|
|
|
- if (!isset($allMachineData[$machineId])) {
|
|
|
|
|
- $allMachineData[$machineId] = [
|
|
|
|
|
- '机台编号' => $machineId,
|
|
|
|
|
- '车间名称' => $workshop,
|
|
|
|
|
- '占用机时' => $machineTime,
|
|
|
|
|
- '工单编号' => $workOrder,
|
|
|
|
|
- '工序号' => $processNo,
|
|
|
|
|
- '印件号' => $printNo,
|
|
|
|
|
- 'Uniqid' => $uniqid,
|
|
|
|
|
- '科目明细' => [],
|
|
|
|
|
- '工单列表' => [],
|
|
|
|
|
- '科目总计' => 0
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 更新机台基础信息(如果有更完整的信息)
|
|
|
|
|
- if (empty($allMachineData[$machineId]['工单编号']) && !empty($workOrder)) {
|
|
|
|
|
- $allMachineData[$machineId]['工单编号'] = $workOrder;
|
|
|
|
|
- }
|
|
|
|
|
- if (empty($allMachineData[$machineId]['工序号']) && !empty($processNo)) {
|
|
|
|
|
- $allMachineData[$machineId]['工序号'] = $processNo;
|
|
|
|
|
- }
|
|
|
|
|
- if (empty($allMachineData[$machineId]['印件号']) && !empty($printNo)) {
|
|
|
|
|
- $allMachineData[$machineId]['印件号'] = $printNo;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 记录工单(去重)
|
|
|
|
|
- if (!empty($workOrder) && !in_array($workOrder, $allMachineData[$machineId]['工单列表'])) {
|
|
|
|
|
- $allMachineData[$machineId]['工单列表'][] = $workOrder;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 合并科目金额
|
|
|
|
|
- $apportionmentTypes = ['分摊水电', '废气处理', '锅炉', '热水锅炉',
|
|
|
|
|
- '空压机A', '空压机B', '真空鼓风机A', '真空鼓风机B',
|
|
|
|
|
- '中央空调A', '中央空调B'];
|
|
|
|
|
-
|
|
|
|
|
- $machineTotal = 0;
|
|
|
|
|
- foreach ($apportionmentTypes as $type) {
|
|
|
|
|
- if (isset($machine[$type]) && floatval($machine[$type]) > 0) {
|
|
|
|
|
- $amount = floatval($machine[$type]);
|
|
|
|
|
- $machineTotal += $amount;
|
|
|
|
|
-
|
|
|
|
|
- // 初始化科目明细
|
|
|
|
|
- if (!isset($allMachineData[$machineId]['科目明细'][$type])) {
|
|
|
|
|
- $allMachineData[$machineId]['科目明细'][$type] = [
|
|
|
|
|
- 'subject_name' => $type,
|
|
|
|
|
- 'total_amount' => 0,
|
|
|
|
|
- 'source_count' => 0,
|
|
|
|
|
- 'source_subjects' => ''
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 累加金额
|
|
|
|
|
- $allMachineData[$machineId]['科目明细'][$type]['total_amount'] += $amount;
|
|
|
|
|
- $allMachineData[$machineId]['科目明细'][$type]['source_count']++;
|
|
|
|
|
-
|
|
|
|
|
- // 记录来源科目
|
|
|
|
|
- $allMachineData[$machineId]['科目明细'][$type]['source_subjects'] = $subjectName;
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 更新机台总计
|
|
|
|
|
- $allMachineData[$machineId]['科目总计'] += $machineTotal;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 按机台+科目进行汇总统计
|
|
|
|
|
- */
|
|
|
|
|
- protected function summarizeByMachineAndSubject($allMachineData, &$machineSummary, &$subjectSummary, &$workshopSummary)
|
|
|
|
|
- {
|
|
|
|
|
- foreach ($allMachineData as $machineId => $machineInfo) {
|
|
|
|
|
- $workshop = $machineInfo['车间名称'];
|
|
|
|
|
-
|
|
|
|
|
- // 1. 按机台统计
|
|
|
|
|
- $machineSummary[$machineId] = [
|
|
|
|
|
- '机台编号' => $machineId,
|
|
|
|
|
- '车间名称' => $workshop,
|
|
|
|
|
- '工单数量' => count($machineInfo['工单列表']),
|
|
|
|
|
- '占用机时' => $machineInfo['占用机时'],
|
|
|
|
|
- '科目总计' => round($machineInfo['科目总计'], 2),
|
|
|
|
|
- '科目明细' => [],
|
|
|
|
|
- '工单列表' => $machineInfo['工单列表']
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- // 处理科目明细
|
|
|
|
|
- foreach ($machineInfo['科目明细'] as $subjectType => $subjectDetail) {
|
|
|
|
|
- $amount = round($subjectDetail['total_amount'], 2);
|
|
|
|
|
- $machineSummary[$machineId]['科目明细'][$subjectType] = [
|
|
|
|
|
- 'amount' => $amount,
|
|
|
|
|
- 'source_count' => $subjectDetail['source_count'],
|
|
|
|
|
- 'source_subjects' => $subjectDetail['source_subjects'],
|
|
|
|
|
- 'percentage' => $machineInfo['科目总计'] > 0
|
|
|
|
|
- ? round(($subjectDetail['total_amount'] / $machineInfo['科目总计']) * 100, 2)
|
|
|
|
|
- : 0
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 2. 按科目统计
|
|
|
|
|
- foreach ($machineInfo['科目明细'] as $subjectType => $subjectDetail) {
|
|
|
|
|
- $amount = round($subjectDetail['total_amount'], 2);
|
|
|
|
|
-
|
|
|
|
|
- // 初始化科目统计
|
|
|
|
|
- if (!isset($subjectSummary[$subjectType])) {
|
|
|
|
|
- $subjectSummary[$subjectType] = [
|
|
|
|
|
- 'subject_name' => $subjectType,
|
|
|
|
|
- 'total_amount' => 0,
|
|
|
|
|
- 'machine_count' => 0,
|
|
|
|
|
- 'workshop_distribution' => [],
|
|
|
|
|
- 'machine_list' => []
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 累加科目总计
|
|
|
|
|
- $subjectSummary[$subjectType]['total_amount'] += $subjectDetail['total_amount'];
|
|
|
|
|
- $subjectSummary[$subjectType]['machine_count']++;
|
|
|
|
|
-
|
|
|
|
|
- // 按车间分布
|
|
|
|
|
- if (!isset($subjectSummary[$subjectType]['workshop_distribution'][$workshop])) {
|
|
|
|
|
- $subjectSummary[$subjectType]['workshop_distribution'][$workshop] = 0;
|
|
|
|
|
- }
|
|
|
|
|
- $subjectSummary[$subjectType]['workshop_distribution'][$workshop] += $subjectDetail['total_amount'];
|
|
|
|
|
-
|
|
|
|
|
- // 机台列表
|
|
|
|
|
- $subjectSummary[$subjectType]['machine_list'][] = [
|
|
|
|
|
- 'machine_id' => $machineId,
|
|
|
|
|
- 'workshop' => $workshop,
|
|
|
|
|
- 'amount' => $amount,
|
|
|
|
|
- 'percentage' => $subjectSummary[$subjectType]['total_amount'] > 0
|
|
|
|
|
- ? round(($subjectDetail['total_amount'] / $subjectSummary[$subjectType]['total_amount']) * 100, 2)
|
|
|
|
|
- : 0
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 3. 按车间统计
|
|
|
|
|
- if (!isset($workshopSummary[$workshop])) {
|
|
|
|
|
- $workshopSummary[$workshop] = [
|
|
|
|
|
- 'workshop_name' => $workshop,
|
|
|
|
|
- 'machine_count' => 0,
|
|
|
|
|
- 'total_amount' => 0,
|
|
|
|
|
- 'subject_distribution' => [],
|
|
|
|
|
- 'machine_list' => []
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $workshopSummary[$workshop]['machine_count']++;
|
|
|
|
|
- $workshopSummary[$workshop]['total_amount'] += $machineInfo['科目总计'];
|
|
|
|
|
-
|
|
|
|
|
- // 车间内科目分布
|
|
|
|
|
- foreach ($machineInfo['科目明细'] as $subjectType => $subjectDetail) {
|
|
|
|
|
- if (!isset($workshopSummary[$workshop]['subject_distribution'][$subjectType])) {
|
|
|
|
|
- $workshopSummary[$workshop]['subject_distribution'][$subjectType] = 0;
|
|
|
|
|
- }
|
|
|
|
|
- $workshopSummary[$workshop]['subject_distribution'][$subjectType] += $subjectDetail['total_amount'];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 车间内机台列表
|
|
|
|
|
- $workshopSummary[$workshop]['machine_list'][] = [
|
|
|
|
|
- 'machine_id' => $machineId,
|
|
|
|
|
- 'total_amount' => round($machineInfo['科目总计'], 2),
|
|
|
|
|
- 'subject_count' => count($machineInfo['科目明细']),
|
|
|
|
|
- 'work_order_count' => count($machineInfo['工单列表'])
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 对科目统计进行后处理
|
|
|
|
|
- $this->processSubjectSummary($subjectSummary);
|
|
|
|
|
-
|
|
|
|
|
- // 对车间统计进行后处理
|
|
|
|
|
- $this->processWorkshopSummary($workshopSummary);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理科目统计
|
|
|
|
|
- */
|
|
|
|
|
- protected function processSubjectSummary(&$subjectSummary)
|
|
|
|
|
- {
|
|
|
|
|
- foreach ($subjectSummary as &$subject) {
|
|
|
|
|
- // 金额四舍五入
|
|
|
|
|
- $subject['total_amount'] = round($subject['total_amount'], 2);
|
|
|
|
|
-
|
|
|
|
|
- // 车间分布百分比
|
|
|
|
|
- foreach ($subject['workshop_distribution'] as $workshop => &$amount) {
|
|
|
|
|
- $amount = round($amount, 2);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 按金额排序机台列表
|
|
|
|
|
- usort($subject['machine_list'], function($a, $b) {
|
|
|
|
|
- return $b['amount'] <=> $a['amount'];
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 计算机台平均金额
|
|
|
|
|
- $subject['avg_per_machine'] = $subject['machine_count'] > 0
|
|
|
|
|
- ? round($subject['total_amount'] / $subject['machine_count'], 2)
|
|
|
|
|
- : 0;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理车间统计
|
|
|
|
|
- */
|
|
|
|
|
- protected function processWorkshopSummary(&$workshopSummary)
|
|
|
|
|
- {
|
|
|
|
|
- foreach ($workshopSummary as &$workshop) {
|
|
|
|
|
- // 金额四舍五入
|
|
|
|
|
- $workshop['total_amount'] = round($workshop['total_amount'], 2);
|
|
|
|
|
-
|
|
|
|
|
- // 科目分布百分比
|
|
|
|
|
- $workshop['subject_percentage'] = [];
|
|
|
|
|
- foreach ($workshop['subject_distribution'] as $subjectType => $amount) {
|
|
|
|
|
- $roundedAmount = round($amount, 2);
|
|
|
|
|
- $workshop['subject_distribution'][$subjectType] = $roundedAmount;
|
|
|
|
|
-
|
|
|
|
|
- if ($workshop['total_amount'] > 0) {
|
|
|
|
|
- $workshop['subject_percentage'][$subjectType] =
|
|
|
|
|
- round(($roundedAmount / $workshop['total_amount']) * 100, 2);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 按金额排序机台列表
|
|
|
|
|
- usort($workshop['machine_list'], function($a, $b) {
|
|
|
|
|
- return $b['total_amount'] <=> $a['total_amount'];
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 计算机台平均金额
|
|
|
|
|
- $workshop['avg_per_machine'] = $workshop['machine_count'] > 0
|
|
|
|
|
- ? round($workshop['total_amount'] / $workshop['machine_count'], 2)
|
|
|
|
|
- : 0;
|
|
|
|
|
-
|
|
|
|
|
- // 统计科目种类数
|
|
|
|
|
- $workshop['subject_count'] = count($workshop['subject_distribution']);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理单个水电费用项
|
|
|
|
|
- */
|
|
|
|
|
- protected function processUtilityItem($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- $subjectName = $item['科目名称'];
|
|
|
|
|
-
|
|
|
|
|
- // 使用switch-like结构提高可读性
|
|
|
|
|
- $processMap = [
|
|
|
|
|
- self::SUBJECT_TOTAL_TO_APPORTION => 'processTotalApportionment',
|
|
|
|
|
- self::SUBJECT_WASTE_GAS => 'processWasteGas',
|
|
|
|
|
- self::SUBJECT_BOILER => 'processBoiler',
|
|
|
|
|
- self::SUBJECT_AIR_COMPRESSOR_A => 'processAirCompressorA',
|
|
|
|
|
- self::SUBJECT_AIR_COMPRESSOR_B => 'processAirCompressorB',
|
|
|
|
|
- self::SUBJECT_VACUUM_BLOWER_A => 'processVacuumBlowerA',
|
|
|
|
|
- self::SUBJECT_VACUUM_BLOWER_B => 'processVacuumBlowerB',
|
|
|
|
|
- self::SUBJECT_CENTRAL_AIR_CONDITIONER_A => 'processCentralAirConditionerA',
|
|
|
|
|
- self::SUBJECT_CENTRAL_AIR_CONDITIONER_B => 'processCentralAirConditionerB',
|
|
|
|
|
- self::SUBJECT_HOT_WATER_BOILER => 'processHotWaterBoiler',
|
|
|
|
|
|
|
+ // 准备任务数据
|
|
|
|
|
+ $taskData = [
|
|
|
|
|
+ 'month' => $month,
|
|
|
|
|
+ 'sys_id' => $sysId,
|
|
|
|
|
+ 'user_id' => session('user_id') ?? 0,
|
|
|
|
|
+ 'user_name' => session('user_name') ?? '系统',
|
|
|
|
|
+ 'request_time' => date('Y-m-d H:i:s')
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
- // 检查是否完全匹配
|
|
|
|
|
- if (isset($processMap[$subjectName])) {
|
|
|
|
|
- $method = $processMap[$subjectName];
|
|
|
|
|
- return $this->$method($item, $month);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查是否包含关键词
|
|
|
|
|
- foreach ($processMap as $keyword => $method) {
|
|
|
|
|
- if (strpos($subjectName, $keyword) !== false) {
|
|
|
|
|
- // 特殊处理:如果包含"锅炉"但不包含"热水锅炉"
|
|
|
|
|
- if ($keyword === self::SUBJECT_BOILER && strpos($subjectName, self::SUBJECT_HOT_WATER_BOILER) !== false) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- return $this->$method($item, $month);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理待分摊总额
|
|
|
|
|
- */
|
|
|
|
|
- protected function processTotalApportionment($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- $money = $this->calculateSafeAmount($item['耗电量'], $item['单位电价']);
|
|
|
|
|
- $data = $this->getMachineTime($item['部门名称'], $month);
|
|
|
|
|
|
|
+ // 先创建任务记录
|
|
|
|
|
+ $taskId = Db::name('queue_tasks')->insertGetId([
|
|
|
|
|
+ 'task_type' => 'cost_calculation',
|
|
|
|
|
+ 'task_data' => json_encode($taskData, JSON_UNESCAPED_UNICODE),
|
|
|
|
|
+ 'status' => 'pending',
|
|
|
|
|
+ 'queue_name' => 'cost_calculation',
|
|
|
|
|
+ 'create_time' => date('Y-m-d H:i:s')
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ // 添加到任务数据中
|
|
|
|
|
+ $taskData['task_id'] = $taskId;
|
|
|
|
|
+
|
|
|
|
|
+ // 提交到成本计算队列
|
|
|
|
|
+ $jobHandlerClassName = 'app\job\CostCalculationJob';
|
|
|
|
|
+ $queueName = 'cost_calculation';
|
|
|
|
|
+
|
|
|
|
|
+ $jobId = Queue::push($jobHandlerClassName, $taskData, $queueName);
|
|
|
|
|
+
|
|
|
|
|
+ if ($jobId) {
|
|
|
|
|
+ // 更新任务记录
|
|
|
|
|
+ Db::name('queue_tasks')
|
|
|
|
|
+ ->where('id', $taskId)
|
|
|
|
|
+ ->update([
|
|
|
|
|
+ 'job_id' => $jobId,
|
|
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $this->success('成本计算任务已提交到队列,请稍后查看结果', null, [
|
|
|
|
|
+ 'task_id' => $taskId,
|
|
|
|
|
+ 'job_id' => $jobId,
|
|
|
|
|
+ 'month' => $month,
|
|
|
|
|
+ 'queue_name' => $queueName
|
|
|
|
|
+ ]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 更新任务状态为失败
|
|
|
|
|
+ Db::name('queue_tasks')
|
|
|
|
|
+ ->where('id', $taskId)
|
|
|
|
|
+ ->update([
|
|
|
|
|
+ 'status' => 'failed',
|
|
|
|
|
+ 'error' => '任务提交到队列失败',
|
|
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
|
|
+ ]);
|
|
|
|
|
|
|
|
- foreach ($data['machine'] as &$machine) {
|
|
|
|
|
- $machine['分摊水电'] = $this->calculateApportionment($money, $machine['占用机时'], $data['sist']);
|
|
|
|
|
|
|
+ $this->error('成本计算任务提交失败');
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return [
|
|
|
|
|
- 'type' => 'total_apportionment',
|
|
|
|
|
- 'data' => $data['machine']
|
|
|
|
|
- ];
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 处理废气处理
|
|
|
|
|
|
|
+ * 查询成本计算状态
|
|
|
|
|
+ * @ApiMethod GET
|
|
|
|
|
+ * @param string month 年月
|
|
|
*/
|
|
*/
|
|
|
- protected function processWasteGas($item, $month)
|
|
|
|
|
|
|
+ public function status()
|
|
|
{
|
|
{
|
|
|
- $electricityMoney = $this->calculateSafeAmount($item['耗电量'], $item['单位电价']);
|
|
|
|
|
- $gasMoney = $this->calculateSafeAmount($item['耗气量'], $item['单位气价']);
|
|
|
|
|
- $data = $this->getMachineTime(self::WORKSHOP_ROLLER_PRESS, $month);
|
|
|
|
|
-
|
|
|
|
|
- foreach ($data['machine'] as &$machine) {
|
|
|
|
|
- $machine['分摊水电'] = $this->calculateApportionment($electricityMoney, $machine['占用机时'], $data['sist']);
|
|
|
|
|
- $machine['废气处理'] = $this->calculateApportionment($gasMoney, $machine['占用机时'], $data['sist']);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return [
|
|
|
|
|
- 'type' => 'waste_gas',
|
|
|
|
|
- 'data' => $data['machine']
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理锅炉
|
|
|
|
|
- */
|
|
|
|
|
- protected function processBoiler($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- $electricityMoney = $this->calculateSafeAmount($item['耗电量'], $item['单位电价']);
|
|
|
|
|
- $gasMoney = $this->calculateSafeAmount($item['耗气量'], $item['单位气价']);
|
|
|
|
|
- $data = $this->getMachineTime(self::WORKSHOP_ROLLER_PRESS, $month);
|
|
|
|
|
-
|
|
|
|
|
- foreach ($data['machine'] as &$machine) {
|
|
|
|
|
- $machine['分摊水电'] = $this->calculateApportionment($electricityMoney, $machine['占用机时'], $data['sist']);
|
|
|
|
|
- $machine['锅炉'] = $this->calculateApportionment($gasMoney, $machine['占用机时'], $data['sist']);
|
|
|
|
|
|
|
+ $month = Request::instance()->param('month');
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($month)) {
|
|
|
|
|
+ $this->error('月份参数错误');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询任务记录
|
|
|
|
|
+ $task = Db::name('queue_tasks')
|
|
|
|
|
+ ->where('task_type', 'cost_calculation')
|
|
|
|
|
+ ->where('task_data', 'like', '%"month":"' . $month . '"%')
|
|
|
|
|
+ ->order('id', 'desc')
|
|
|
|
|
+ ->find();
|
|
|
|
|
+
|
|
|
|
|
+ if ($task) {
|
|
|
|
|
+ $result = json_decode($task['result'] ?? '{}', true);
|
|
|
|
|
+ $taskData = json_decode($task['task_data'] ?? '{}', true);
|
|
|
|
|
+
|
|
|
|
|
+ $response = [
|
|
|
|
|
+ 'exists' => true,
|
|
|
|
|
+ 'task_id' => $task['id'],
|
|
|
|
|
+ 'month' => $month,
|
|
|
|
|
+ 'status' => $task['status'],
|
|
|
|
|
+ 'queue_name' => $task['queue_name'],
|
|
|
|
|
+ 'job_id' => $task['job_id'],
|
|
|
|
|
+ 'start_time' => $task['start_time'],
|
|
|
|
|
+ 'end_time' => $task['end_time'],
|
|
|
|
|
+ 'retry_count' => $task['retry_count'],
|
|
|
|
|
+ 'result' => $result,
|
|
|
|
|
+ 'error' => $task['error'] ?? '',
|
|
|
|
|
+ 'create_time' => $task['create_time'],
|
|
|
|
|
+ 'user_info' => [
|
|
|
|
|
+ 'user_id' => $taskData['user_id'] ?? 0,
|
|
|
|
|
+ 'user_name' => $taskData['user_name'] ?? ''
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $response = ['exists' => false, 'month' => $month];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return [
|
|
|
|
|
- 'type' => 'boiler',
|
|
|
|
|
- 'data' => $data['machine']
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理空压机A
|
|
|
|
|
- */
|
|
|
|
|
- protected function processAirCompressorA($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, self::SUBJECT_AIR_COMPRESSOR_A);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理空压机B
|
|
|
|
|
- */
|
|
|
|
|
- protected function processAirCompressorB($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, self::SUBJECT_AIR_COMPRESSOR_B);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理真空鼓风机A
|
|
|
|
|
- */
|
|
|
|
|
- protected function processVacuumBlowerA($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, self::SUBJECT_VACUUM_BLOWER_A);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理真空鼓风机B
|
|
|
|
|
- */
|
|
|
|
|
- protected function processVacuumBlowerB($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, self::SUBJECT_VACUUM_BLOWER_B);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理中央空调A
|
|
|
|
|
- */
|
|
|
|
|
- protected function processCentralAirConditionerA($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, self::SUBJECT_CENTRAL_AIR_CONDITIONER_A);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理中央空调B
|
|
|
|
|
- */
|
|
|
|
|
- protected function processCentralAirConditionerB($item, $month)
|
|
|
|
|
- {
|
|
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, self::SUBJECT_CENTRAL_AIR_CONDITIONER_B);
|
|
|
|
|
|
|
+ $this->success('查询成功', null, $response);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 处理热水锅炉
|
|
|
|
|
|
|
+ * 获取成本计算任务列表
|
|
|
|
|
+ * @ApiMethod GET
|
|
|
*/
|
|
*/
|
|
|
- protected function processHotWaterBoiler($item, $month)
|
|
|
|
|
|
|
+ public function list()
|
|
|
{
|
|
{
|
|
|
- return $this->processGeneralElectricEquipment($item, $month, '热水锅炉');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $page = Request::instance()->param('page', 1);
|
|
|
|
|
+ $limit = Request::instance()->param('limit', 20);
|
|
|
|
|
+ $month = Request::instance()->param('month');
|
|
|
|
|
+ $status = Request::instance()->param('status');
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 通用电气设备处理(适用于所有车间)
|
|
|
|
|
- */
|
|
|
|
|
- protected function processGeneralElectricEquipment($item, $month, $equipmentType)
|
|
|
|
|
- {
|
|
|
|
|
- $money = $this->calculateSafeAmount($item['耗电量'], $item['单位电价']);
|
|
|
|
|
- $data = $this->getMachineTime(self::WORKSHOP_LIST_ALL, $month);
|
|
|
|
|
|
|
+ $query = Db::name('queue_tasks')
|
|
|
|
|
+ ->where('task_type', 'cost_calculation');
|
|
|
|
|
|
|
|
- foreach ($data['machine'] as &$machine) {
|
|
|
|
|
- $machine[$equipmentType] = $this->calculateApportionment($money, $machine['占用机时'], $data['sist']);
|
|
|
|
|
|
|
+ if ($month) {
|
|
|
|
|
+ $query->where('task_data', 'like', '%"month":"' . $month . '"%');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return [
|
|
|
|
|
- 'type' => $equipmentType,
|
|
|
|
|
- 'data' => $data['machine']
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 计算分摊金额
|
|
|
|
|
- */
|
|
|
|
|
- protected function calculateApportionment($totalAmount, $machineTime, $totalTime)
|
|
|
|
|
- {
|
|
|
|
|
- if ($totalTime <= 0) {
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- return round($totalAmount * ($machineTime / $totalTime), 2);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 查询车间机台通电机时数据(优化版)
|
|
|
|
|
- */
|
|
|
|
|
- protected function getMachineTime($workshop, $month)
|
|
|
|
|
- {
|
|
|
|
|
- $where = [
|
|
|
|
|
- 'a.sys_ny' => $month,
|
|
|
|
|
- 'b.sys_sbID' => ['<>','']
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- // 构建车间查询条件
|
|
|
|
|
- if (is_array($workshop)) {
|
|
|
|
|
- $where['a.车间名称'] = ['in', $workshop];
|
|
|
|
|
- } else {
|
|
|
|
|
- if (strpos($workshop, '机组') !== false) {
|
|
|
|
|
- $where['b.设备编组'] = $workshop;
|
|
|
|
|
- } elseif (strpos($workshop, '车间') !== false) {
|
|
|
|
|
- $where['a.车间名称'] = $workshop;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if ($status) {
|
|
|
|
|
+ $query->where('status', $status);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 查询机台数据
|
|
|
|
|
- $machine = db('成本v23_月度成本明细')
|
|
|
|
|
- ->alias('a')
|
|
|
|
|
- ->join('设备_基本资料 b', 'a.sczl_jtbh = b.设备编号', 'left')
|
|
|
|
|
- ->field('rtrim(车间名称) as 车间名称,a.sczl_gdbh as 工单编号,a.sczl_yjno as 印件号,a.sczl_gxh as 工序号,a.sczl_jtbh as 机台编号,a.占用机时,a.Uniqid')
|
|
|
|
|
- ->where($where)
|
|
|
|
|
|
|
+ $total = $query->count();
|
|
|
|
|
+ $list = $query->order('id', 'desc')
|
|
|
|
|
+ ->page($page, $limit)
|
|
|
->select();
|
|
->select();
|
|
|
|
|
|
|
|
- // 查询总时长
|
|
|
|
|
- $totalTime = db('成本v23_月度成本明细')
|
|
|
|
|
- ->alias('a')
|
|
|
|
|
- ->join('设备_基本资料 b', 'a.sczl_jtbh = b.设备编号', 'left')
|
|
|
|
|
- ->where($where)
|
|
|
|
|
- ->value('sum(a.占用机时) as 占用机时', 0);
|
|
|
|
|
-
|
|
|
|
|
- return [
|
|
|
|
|
- 'machine' => $machine,
|
|
|
|
|
- 'sist' => $totalTime
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 统计分摊结果
|
|
|
|
|
- */
|
|
|
|
|
- protected function summarizeApportionment($result, $department, $subject,
|
|
|
|
|
- &$summaryByDepartment, &$summaryBySubject,
|
|
|
|
|
- &$summaryByDepartmentSubject)
|
|
|
|
|
- {
|
|
|
|
|
- $resultType = $result['type'];
|
|
|
|
|
- $machineData = $result['data'];
|
|
|
|
|
-
|
|
|
|
|
- if (empty($machineData)) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 清洗部门名称
|
|
|
|
|
- $cleanDepartment = trim($department);
|
|
|
|
|
- $cleanSubject = trim($subject);
|
|
|
|
|
-
|
|
|
|
|
- // 初始化统计键
|
|
|
|
|
- if (!isset($summaryByDepartment[$cleanDepartment])) {
|
|
|
|
|
- $summaryByDepartment[$cleanDepartment] = [];
|
|
|
|
|
- }
|
|
|
|
|
- if (!isset($summaryBySubject[$resultType])) {
|
|
|
|
|
- $summaryBySubject[$resultType] = [];
|
|
|
|
|
- }
|
|
|
|
|
- if (!isset($summaryByDepartmentSubject[$cleanDepartment])) {
|
|
|
|
|
- $summaryByDepartmentSubject[$cleanDepartment] = [];
|
|
|
|
|
- }
|
|
|
|
|
- if (!isset($summaryByDepartmentSubject[$cleanDepartment][$resultType])) {
|
|
|
|
|
- $summaryByDepartmentSubject[$cleanDepartment][$resultType] = [
|
|
|
|
|
- 'department' => $cleanDepartment,
|
|
|
|
|
- 'subject' => $cleanSubject,
|
|
|
|
|
- 'result_type' => $resultType,
|
|
|
|
|
- 'total_amount' => 0,
|
|
|
|
|
- 'machine_count' => 0,
|
|
|
|
|
- 'work_order_count' => 0
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 解析任务数据
|
|
|
|
|
+ foreach ($list as &$item) {
|
|
|
|
|
+ $taskData = json_decode($item['task_data'] ?? '{}', true);
|
|
|
|
|
+ $item['month'] = $taskData['month'] ?? '';
|
|
|
|
|
+ $item['user_name'] = $taskData['user_name'] ?? '';
|
|
|
|
|
+ $item['request_time'] = $taskData['request_time'] ?? '';
|
|
|
|
|
|
|
|
- // 按车间和机台统计
|
|
|
|
|
- foreach ($machineData as $machine) {
|
|
|
|
|
- // 获取车间名称(已使用rtrim清洗过)
|
|
|
|
|
- $workshop = isset($machine['车间名称']) ? $machine['车间名称'] : '未知车间';
|
|
|
|
|
-
|
|
|
|
|
- // 统计按部门
|
|
|
|
|
- if (!isset($summaryByDepartment[$cleanDepartment][$workshop])) {
|
|
|
|
|
- $summaryByDepartment[$cleanDepartment][$workshop] = [
|
|
|
|
|
- 'total_amount' => 0,
|
|
|
|
|
- 'machine_count' => 0,
|
|
|
|
|
- 'subjects' => []
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 统计按科目
|
|
|
|
|
- if (!isset($summaryBySubject[$resultType][$workshop])) {
|
|
|
|
|
- $summaryBySubject[$resultType][$workshop] = [
|
|
|
|
|
- 'total_amount' => 0,
|
|
|
|
|
- 'machine_count' => 0,
|
|
|
|
|
- 'departments' => []
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 计算此机台的总分摊金额
|
|
|
|
|
- $machineTotal = 0;
|
|
|
|
|
- $apportionmentTypes = ['分摊水电', '废气处理', '锅炉', '热水锅炉',
|
|
|
|
|
- '空压机A', '空压机B', '真空鼓风机A', '真空鼓风机B',
|
|
|
|
|
- '中央空调A', '中央空调B'];
|
|
|
|
|
-
|
|
|
|
|
- foreach ($apportionmentTypes as $type) {
|
|
|
|
|
- if (isset($machine[$type])) {
|
|
|
|
|
- $amount = floatval($machine[$type]);
|
|
|
|
|
- $machineTotal += $amount;
|
|
|
|
|
-
|
|
|
|
|
- // 按部门+车间统计各科目金额
|
|
|
|
|
- if (!isset($summaryByDepartment[$cleanDepartment][$workshop]['subjects'][$type])) {
|
|
|
|
|
- $summaryByDepartment[$cleanDepartment][$workshop]['subjects'][$type] = 0;
|
|
|
|
|
- }
|
|
|
|
|
- $summaryByDepartment[$cleanDepartment][$workshop]['subjects'][$type] += $amount;
|
|
|
|
|
-
|
|
|
|
|
- // 按科目+车间统计各部门金额
|
|
|
|
|
- if (!in_array($cleanDepartment, $summaryBySubject[$resultType][$workshop]['departments'])) {
|
|
|
|
|
- $summaryBySubject[$resultType][$workshop]['departments'][] = $cleanDepartment;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 更新统计信息
|
|
|
|
|
- if ($machineTotal > 0) {
|
|
|
|
|
- $summaryByDepartment[$cleanDepartment][$workshop]['total_amount'] += $machineTotal;
|
|
|
|
|
- $summaryByDepartment[$cleanDepartment][$workshop]['machine_count']++;
|
|
|
|
|
-
|
|
|
|
|
- $summaryBySubject[$resultType][$workshop]['total_amount'] += $machineTotal;
|
|
|
|
|
- $summaryBySubject[$resultType][$workshop]['machine_count']++;
|
|
|
|
|
-
|
|
|
|
|
- $summaryByDepartmentSubject[$cleanDepartment][$resultType]['total_amount'] += $machineTotal;
|
|
|
|
|
- $summaryByDepartmentSubject[$cleanDepartment][$resultType]['machine_count']++;
|
|
|
|
|
-
|
|
|
|
|
- // 统计工单数(去重)
|
|
|
|
|
- if (!isset($summaryByDepartmentSubject[$cleanDepartment][$resultType]['work_orders'])) {
|
|
|
|
|
- $summaryByDepartmentSubject[$cleanDepartment][$resultType]['work_orders'] = [];
|
|
|
|
|
- }
|
|
|
|
|
- if (isset($machine['工单编号'])) {
|
|
|
|
|
- $summaryByDepartmentSubject[$cleanDepartment][$resultType]['work_orders'][] = $machine['工单编号'];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!empty($item['result'])) {
|
|
|
|
|
+ $item['result_data'] = json_decode($item['result'], true);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 计算工单数(去重)
|
|
|
|
|
- foreach ($summaryByDepartmentSubject[$cleanDepartment] as $type => &$data) {
|
|
|
|
|
- if (isset($data['work_orders'])) {
|
|
|
|
|
- $data['work_order_count'] = count(array_unique($data['work_orders']));
|
|
|
|
|
- unset($data['work_orders']);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 为部门统计添加汇总信息
|
|
|
|
|
- $this->addSummaryToDepartment($summaryByDepartment[$cleanDepartment]);
|
|
|
|
|
-
|
|
|
|
|
- // 为科目统计添加汇总信息
|
|
|
|
|
- $this->addSummaryToSubject($summaryBySubject[$resultType]);
|
|
|
|
|
|
|
+ $this->success('查询成功', null, [
|
|
|
|
|
+ 'list' => $list,
|
|
|
|
|
+ 'total' => $total,
|
|
|
|
|
+ 'page' => $page,
|
|
|
|
|
+ 'pages' => ceil($total / $limit)
|
|
|
|
|
+ ]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 为部门统计添加汇总信息
|
|
|
|
|
|
|
+ * 手动重试失败的任务
|
|
|
|
|
+ * @ApiMethod POST
|
|
|
|
|
+ * @param int task_id 任务ID
|
|
|
*/
|
|
*/
|
|
|
- protected function addSummaryToDepartment(&$departmentData)
|
|
|
|
|
|
|
+ public function retry()
|
|
|
{
|
|
{
|
|
|
- $totalAmount = 0;
|
|
|
|
|
- $totalMachines = 0;
|
|
|
|
|
|
|
+ $taskId = Request::instance()->param('task_id');
|
|
|
|
|
|
|
|
- foreach ($departmentData as $workshop => $data) {
|
|
|
|
|
- if ($workshop === 'summary') continue;
|
|
|
|
|
-
|
|
|
|
|
- $totalAmount += $data['total_amount'];
|
|
|
|
|
- $totalMachines += $data['machine_count'];
|
|
|
|
|
|
|
+ if (empty($taskId)) {
|
|
|
|
|
+ $this->error('任务ID不能为空');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- $departmentData['summary'] = [
|
|
|
|
|
- 'total_amount' => round($totalAmount, 2),
|
|
|
|
|
- 'total_machines' => $totalMachines,
|
|
|
|
|
- 'workshop_count' => count($departmentData) - 1
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 为科目统计添加汇总信息
|
|
|
|
|
- */
|
|
|
|
|
- protected function addSummaryToSubject(&$subjectData)
|
|
|
|
|
- {
|
|
|
|
|
- $totalAmount = 0;
|
|
|
|
|
- $totalMachines = 0;
|
|
|
|
|
- $allDepartments = [];
|
|
|
|
|
-
|
|
|
|
|
- foreach ($subjectData as $workshop => $data) {
|
|
|
|
|
- if ($workshop === 'summary') continue;
|
|
|
|
|
|
|
+ $task = Db::name('queue_tasks')
|
|
|
|
|
+ ->where('id', $taskId)
|
|
|
|
|
+ ->where('task_type', 'cost_calculation')
|
|
|
|
|
+ ->where('status', 'failed')
|
|
|
|
|
+ ->find();
|
|
|
|
|
|
|
|
- $totalAmount += $data['total_amount'];
|
|
|
|
|
- $totalMachines += $data['machine_count'];
|
|
|
|
|
- $allDepartments = array_merge($allDepartments, $data['departments']);
|
|
|
|
|
|
|
+ if (!$task) {
|
|
|
|
|
+ $this->error('任务不存在或无法重试');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- $subjectData['summary'] = [
|
|
|
|
|
- 'total_amount' => round($totalAmount, 2),
|
|
|
|
|
- 'total_machines' => $totalMachines,
|
|
|
|
|
- 'workshop_count' => count($subjectData) - 1,
|
|
|
|
|
- 'department_count' => count(array_unique($allDepartments))
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 解析原任务数据
|
|
|
|
|
+ $taskData = json_decode($task['task_data'], true);
|
|
|
|
|
+ $taskData['task_id'] = $taskId;
|
|
|
|
|
+ $taskData['retry_time'] = date('Y-m-d H:i:s');
|
|
|
|
|
|
|
|
|
|
+ // 更新原任务状态
|
|
|
|
|
+ Db::name('queue_tasks')
|
|
|
|
|
+ ->where('id', $taskId)
|
|
|
|
|
+ ->update([
|
|
|
|
|
+ 'status' => 'retrying',
|
|
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
|
|
+ ]);
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 格式化最终统计结果
|
|
|
|
|
- */
|
|
|
|
|
- protected function formatFinalResults($apportionmentResults,$month,$sys)
|
|
|
|
|
- {
|
|
|
|
|
- $data = [];
|
|
|
|
|
- foreach ($apportionmentResults as $key => $value) {
|
|
|
|
|
- foreach ($value['科目明细'] as $item) {
|
|
|
|
|
- $data[] = [
|
|
|
|
|
- 'Sys_ny' => $month,
|
|
|
|
|
- '科目名称' => $item['source_subjects'],
|
|
|
|
|
- '设备编号' => $key,
|
|
|
|
|
- '分摊系数' => 1,
|
|
|
|
|
- '分摊金额' => $item['amount'],
|
|
|
|
|
- 'Sys_id' => $sys,
|
|
|
|
|
- 'Sys_rq' => date('Y-m-d H:i:s',time()),
|
|
|
|
|
- ];
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return $data;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 获取车间机台生产工单
|
|
|
|
|
- * @param $sist
|
|
|
|
|
- * @param $month
|
|
|
|
|
- * @return bool|\PDOStatement|string|\think\Collection
|
|
|
|
|
- * @throws \think\db\exception\DataNotFoundException
|
|
|
|
|
- * @throws \think\db\exception\ModelNotFoundException
|
|
|
|
|
- * @throws \think\exception\DbException
|
|
|
|
|
- */
|
|
|
|
|
- protected function getMachineWorkOrder($machine,$month)
|
|
|
|
|
- {
|
|
|
|
|
- $list = db('成本v23_月度成本明细')
|
|
|
|
|
- ->where([
|
|
|
|
|
- 'sys_ny' => $month,
|
|
|
|
|
- 'sczl_jtbh' => $machine,
|
|
|
|
|
- ])
|
|
|
|
|
- ->field([
|
|
|
|
|
- 'sczl_gdbh' => '工单编号',
|
|
|
|
|
- 'sczl_yjno' => '印件号',
|
|
|
|
|
- 'sczl_gxh' => '工序号',
|
|
|
|
|
- 'sczl_jtbh' => '机台编号',
|
|
|
|
|
- '占用机时',
|
|
|
|
|
- ])
|
|
|
|
|
- ->group('工单编号,印件号,工序号')
|
|
|
|
|
- ->select();
|
|
|
|
|
- return $list;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 提交到队列
|
|
|
|
|
+ $jobHandlerClassName = 'app\job\CostCalculationJob';
|
|
|
|
|
+ $queueName = 'cost_calculation';
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 查询车间机台色度数
|
|
|
|
|
- * @param $month
|
|
|
|
|
- * @return bool|\PDOStatement|string|\think\Collection
|
|
|
|
|
- * @throws \think\db\exception\DataNotFoundException
|
|
|
|
|
- * @throws \think\db\exception\ModelNotFoundException
|
|
|
|
|
- * @throws \think\exception\DbException
|
|
|
|
|
- */
|
|
|
|
|
- protected function getMachineTotal($month)
|
|
|
|
|
- {
|
|
|
|
|
- $list = db('成本_各月分摊系数')
|
|
|
|
|
- ->alias('a')
|
|
|
|
|
- ->join('成本v23_月度成本明细 b', 'b.sys_ny = a.Sys_ny and b.sczl_jtbh = a.设备编号','LEFT')
|
|
|
|
|
- ->where([
|
|
|
|
|
- 'a.Sys_ny' => $month,
|
|
|
|
|
- 'b.车间名称' => ['in', self::WORKSHOP_LIST_ALL],
|
|
|
|
|
- ])
|
|
|
|
|
- ->field([
|
|
|
|
|
- 'b.sczl_jtbh' => '机台编号',
|
|
|
|
|
- 'sum(b.占用机时)' => '占用机时',
|
|
|
|
|
- 'a.分摊金额',
|
|
|
|
|
- 'a.科目名称',
|
|
|
|
|
- ])
|
|
|
|
|
- ->group('机台编号,a.科目名称')
|
|
|
|
|
- ->select();
|
|
|
|
|
- foreach ($list as $key => $item) {
|
|
|
|
|
- $list[$key]['金额'] = round($item['分摊金额']/$item['占用机时'], 2);
|
|
|
|
|
- }
|
|
|
|
|
- $data = [];
|
|
|
|
|
- foreach ($list as $item) {
|
|
|
|
|
- $machineCode = $item['机台编号'];
|
|
|
|
|
- $subjectName = explode('(',$item['科目名称']);
|
|
|
|
|
- $amount = $item['金额'];
|
|
|
|
|
-
|
|
|
|
|
- // 如果这个机台编号还没有在结果数组中,初始化它
|
|
|
|
|
- if (!isset($data[$machineCode])) {
|
|
|
|
|
- $data[$machineCode] = [];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ $jobId = Queue::push($jobHandlerClassName, $taskData, $queueName);
|
|
|
|
|
|
|
|
- // 将科目名称和金额添加到对应的机台编号下
|
|
|
|
|
- $data[$machineCode][$subjectName[0]] = $amount;
|
|
|
|
|
|
|
+ if ($jobId) {
|
|
|
|
|
+ $this->success('任务已重新提交到队列', null, [
|
|
|
|
|
+ 'task_id' => $taskId,
|
|
|
|
|
+ 'new_job_id' => $jobId,
|
|
|
|
|
+ 'queue_name' => $queueName
|
|
|
|
|
+ ]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $this->error('任务重试失败');
|
|
|
}
|
|
}
|
|
|
- return $data;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|