Achievementatestatistics.php 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use Monolog\Handler\IFTTTHandler;
  5. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  6. use think\Db;
  7. use think\Request;
  8. use PhpOffice\PhpSpreadsheet\IOFactory;
  9. class Achievementatestatistics extends Api
  10. {
  11. protected $noNeedLogin = ['*'];
  12. protected $noNeedRight = ['*'];
  13. /**
  14. * 1.1达成率统计->左侧菜单
  15. */
  16. public function Leftmenu(){
  17. // 获取所有部门(排除特定)
  18. $departments = Db::name('设备_基本资料')
  19. ->field('使用部门')
  20. ->whereNotIn('使用部门', ['打样室', '智能车间'])
  21. ->group('使用部门')
  22. ->select();
  23. // 部门名数组
  24. $deptList = array_map(function($item) {
  25. return trim($item['使用部门']);
  26. }, $departments);
  27. // 获取产量表日期
  28. $rawData = Db::name('设备_产量计酬')
  29. ->field("DATE(sys_rq) as rq")
  30. ->whereRaw("YEAR(sys_rq) >= 2000")
  31. ->order("rq desc")
  32. ->select();
  33. $workStats = [];
  34. $addedMonths = []; // 记录已处理年月
  35. foreach ($rawData as $item) {
  36. $rq = $item['rq'];
  37. $year = date('Y', strtotime($rq));
  38. $yearMonth = date('Ym', strtotime($rq));
  39. // 如果该年月还没加过,才添加
  40. if (!isset($addedMonths[$year][$yearMonth])) {
  41. $workStats[$year][$yearMonth] = $deptList;
  42. $addedMonths[$year][$yearMonth] = true;
  43. }
  44. }
  45. $result = [
  46. '排产计划达成率统计' => $departments,
  47. '设备工时达成率统计' => $workStats
  48. ];
  49. $this->success('成功',$result);
  50. }
  51. public function Machine_List()
  52. {
  53. if (!$this->request->isGet()) {
  54. $this->error('请求方式错误');
  55. }
  56. $param = $this->request->param();
  57. if (empty($param['Machine'])) {
  58. $this->error('缺少参数 Machine');
  59. }
  60. // 日期映射:近 7 天
  61. $dateMap = [];
  62. $recentDates = [];
  63. for ($i = 0; $i < 7; $i++) {
  64. $date = date('Y-m-d', strtotime("-{$i} days"));
  65. $label = date('m月d日', strtotime($date));
  66. $dateMap[$date] = $label;
  67. $recentDates[] = $date;
  68. }
  69. $devices = Db::name('设备_基本资料')
  70. ->field('设备编号, 设备名称')
  71. ->whereLike('使用部门', '%' . $param['Machine'] . '%')
  72. ->select();
  73. $results = [];
  74. foreach ($devices as $device) {
  75. $jtbh = $device['设备编号'];
  76. $jtname = trim($device['设备名称']);
  77. // 获取原始产量数据
  78. $records = Db::name('设备_产量计酬')
  79. ->field([
  80. 'sczl_bzdh as 班组',
  81. 'sczl_cl',
  82. 'sczl_Pgcl',
  83. 'sczl_rq as 日期',
  84. 'sczl_gdbh',
  85. 'sczl_yjno',
  86. 'sczl_gxh'
  87. ])
  88. ->where('sczl_jtbh', $jtbh)
  89. ->where('sczl_rq', '>=', date('Y-m-d 00:00:00', strtotime('-6 days')))
  90. ->where('sczl_rq', '<=', date('Y-m-d 23:59:59'))
  91. ->select();
  92. $stat = [];
  93. $summary = [];
  94. foreach ($records as $row) {
  95. $bz = $row['班组'] ?: '未分组';
  96. $rq = date('Y-m-d', strtotime($row['日期']));
  97. $cl = floatval($row['sczl_cl']);
  98. $pgcl = floatval($row['sczl_Pgcl']);
  99. $actual = ($cl == 0) ? 0 : (($pgcl > 0) ? $cl * $pgcl : $cl);
  100. // 查询排产产量
  101. $plan = Db::name('工单_工艺资料')
  102. ->where('Gy0_gdbh', $row['sczl_gdbh'])
  103. ->where('Gy0_yjno', $row['sczl_yjno'])
  104. ->where('Gy0_gxh', $row['sczl_gxh'])
  105. ->value('Gy0_计划接货数');
  106. $plan = floatval($plan);
  107. // 班组维度统计
  108. if (!isset($stat[$bz][$rq])) {
  109. $stat[$bz][$rq] = ['实际产量' => 0, '排产产量' => 0];
  110. }
  111. $stat[$bz][$rq]['实际产量'] += $actual;
  112. $stat[$bz][$rq]['排产产量'] += $plan;
  113. // 合计维度统计
  114. if (!isset($summary[$rq])) {
  115. $summary[$rq] = ['实际产量' => 0, '排产产量' => 0];
  116. }
  117. $summary[$rq]['实际产量'] += $actual;
  118. $summary[$rq]['排产产量'] += $plan;
  119. }
  120. // 输出每个班组
  121. foreach ($stat as $bz => $dateList) {
  122. $item = [
  123. '机台编号' => $jtbh,
  124. '机台名称' => $jtname,
  125. '班组' => $bz,
  126. '实际总产量' => 0,
  127. '排产总产量' => 0,
  128. '近7天综合达成率' => '0%'
  129. ];
  130. $i = 1;
  131. foreach ($dateMap as $date => $label) {
  132. $actual = isset($dateList[$date]) ? round($dateList[$date]['实际产量'], 2) : 0;
  133. $plan = isset($dateList[$date]) ? round($dateList[$date]['排产产量'], 2) : 0;
  134. $rate = ($plan > 0) ? round($actual / $plan * 100, 2) . '%' : '0%';
  135. $item[$label] = $rate;
  136. $item["实际产量{$i}"] = $actual;
  137. $item["排产产量{$i}"] = $plan;
  138. $item['实际总产量'] += $actual;
  139. $item['排产总产量'] += $plan;
  140. $i++;
  141. }
  142. $item['近7天综合达成率'] = ($item['排产总产量'] > 0)
  143. ? round($item['实际总产量'] / $item['排产总产量'] * 100, 2) . '%'
  144. : '0%';
  145. $results[] = $item;
  146. }
  147. // 合计行
  148. $item = [
  149. '机台编号' => $jtbh,
  150. '机台名称' => '合计',
  151. '班组' => '',
  152. '实际总产量' => 0,
  153. '排产总产量' => 0,
  154. '近7天综合达成率' => '0%'
  155. ];
  156. $i = 1;
  157. foreach ($dateMap as $date => $label) {
  158. $actual = isset($summary[$date]) ? round($summary[$date]['实际产量'], 2) : 0;
  159. $plan = isset($summary[$date]) ? round($summary[$date]['排产产量'], 2) : 0;
  160. // 重新计算达成率,不使用之前累加的百分比
  161. $rate = ($plan > 0) ? round($actual / $plan * 100, 2) . '%' : '0%';
  162. $item[$label] = $rate;
  163. $item["实际产量{$i}"] = $actual;
  164. $item["排产产量{$i}"] = $plan;
  165. $item['实际总产量'] += $actual;
  166. $item['排产总产量'] += $plan;
  167. $i++;
  168. }
  169. // 修正“近7天综合达成率”的计算
  170. $item['近7天综合达成率'] = ($item['排产总产量'] > 0)
  171. ? round($item['实际总产量'] / $item['排产总产量'] * 100, 2) . '%'
  172. : '0%';
  173. $results[] = $item;
  174. }
  175. $this->success('成功', [
  176. 'data' => $results,
  177. 'list' => $recentDates
  178. ]);
  179. }
  180. /**
  181. * 1.3达成率统计->机台生产详情
  182. */
  183. public function Machine_Detail()
  184. {
  185. if (!$this->request->isGet()) {
  186. $this->error('请求方式错误');
  187. }
  188. $param = $this->request->param();
  189. if (empty($param['jtbh']) || empty($param['bz'])) {
  190. // $this->error('缺少参数:jtbh(机台编号)或 bz(班组)');
  191. }
  192. $jtbh = $param['jtbh'];
  193. $bz = $param['bz'];
  194. // 查询近 7 天产量记录
  195. $records = Db::name('设备_产量计酬')->alias('a')
  196. ->field('
  197. a.sczl_rq as 日期,
  198. a.sczl_jtbh as 机台编号,
  199. a.sczl_bzdh as 班组,
  200. a.sczl_gdbh as 工单编号,
  201. a.sczl_yjno as 印件号,
  202. b.yj_yjmc as 印件名称,
  203. a.sczl_gxh as 工序号,
  204. a.sczl_gxmc as 工序名称,
  205. a.sczl_cl as 实际产量,
  206. c.排单小时定额 as 排产标准产能,
  207. d.Gy0_计划接货数 as 排产产量,
  208. a.sczl_设备运行工时 as 上报运行工时,
  209. a.sczl_装版总工时 as 装版实际工时,
  210. a.sczl_保养工时 as 保养工时,
  211. a.sczl_打样总工时 as 打样工时,
  212. d.版距 as 版距,
  213. c.设备名称 as 机台名称
  214. ')
  215. ->join('工单_印件资料 b','a.sczl_gdbh = b.Yj_Gdbh')
  216. ->join('设备_基本资料 c','a.sczl_jtbh = c.设备编号')
  217. ->join('工单_工艺资料 d','a.sczl_gdbh = d.Gy0_gdbh AND a.sczl_yjno = d.Gy0_yjno AND a.sczl_gxh = d.Gy0_gxh')
  218. ->where('a.sczl_jtbh', $jtbh)
  219. ->where('a.sczl_bzdh', $bz)
  220. ->where('a.sczl_rq', '>=', date('Y-m-d 00:00:00', strtotime('-6 days')))
  221. ->where('a.sczl_rq', '<=', date('Y-m-d 23:59:59'))
  222. ->order('a.sczl_rq desc')
  223. ->select();
  224. $details = [];
  225. foreach ($records as $row) {
  226. $rq = date('Y-m-d', strtotime($row['日期']));
  227. $details[] = [
  228. '日期' => $rq,
  229. '机台编号' => $row['机台编号'],
  230. '班组' => $row['班组'],
  231. '工单编号' => $row['工单编号'],
  232. '印件号' => $row['印件号'],
  233. '印件名称' => $row['印件名称'],
  234. '工序号' => $row['工序号'],
  235. '工序名称' => $row['工序名称'],
  236. '实际产量' => floatval($row['实际产量']),
  237. '排产标准产能' => $row['排产标准产能'],
  238. '排产产量' => floatval($row['排产产量']),
  239. '上报运行工时' => $row['上报运行工时'],
  240. '装版实际工时' => $row['装版实际工时'],
  241. '保养工时' => $row['保养工时'],
  242. '打样工时' => $row['打样工时'],
  243. '版距' => $row['版距'],
  244. '机台名称' => $row['机台名称'],
  245. ];
  246. }
  247. $this->success('明细获取成功', $details);
  248. }
  249. /**
  250. * 1.4达成率统计 -> 按月份汇总机台产量(按班组分组)
  251. */
  252. public function Machine_production_list()
  253. {
  254. if (!$this->request->isGet()) {
  255. $this->error('请求方式错误');
  256. }
  257. $param = $this->request->param();
  258. if (empty($param['Machine']) || empty($param['rq'])) {
  259. $this->error('参数错误');
  260. }
  261. $machine = $param['Machine'];
  262. $rq = $param['rq'];
  263. $ym = substr($rq, 0, 4) . '-' . substr($rq, 4, 2);
  264. // 查询设备编号
  265. $devices = Db::name('设备_基本资料')
  266. ->where('使用部门', $machine)
  267. ->column('设备编号');
  268. $devices = array_map('trim', $devices);
  269. // 查询产量记录
  270. $records = Db::name('设备_产量计酬')
  271. ->alias('a')
  272. ->field([
  273. 'a.sczl_jtbh as 机台编号',
  274. 'a.sczl_bzdh as 班组',
  275. 'a.sczl_rq',
  276. 'a.sczl_cl',
  277. 'a.sczl_ls',
  278. 'a.sczl_rq',
  279. 'a.sczl_装版总工时 as 装板实际工时',
  280. 'a.sczl_装版工时 as 装板补产工时',
  281. 'a.sczl_保养工时 as 保养工时',
  282. 'a.sczl_打样总工时 as 打样总工时',
  283. 'a.sczl_打样工时 as 打样补产工时',
  284. 'a.sczl_异常停机工时 as 异常总工时',
  285. 'a.sczl_异常工时1 as 异常补时',
  286. 'a.sczl_设备运行工时 as 运行工时',
  287. 'c.排单小时定额 as 小时产能',
  288. 'c.平均车速'
  289. ])
  290. ->join('设备_基本资料 c', 'a.sczl_jtbh = c.设备编号')
  291. ->whereIn('a.sczl_jtbh', $devices)
  292. ->where('a.sczl_rq', 'like', $ym . '%')
  293. ->select();
  294. // 分组汇总:按 机台编号 + 班组
  295. $resultList = [];
  296. foreach ($records as $row) {
  297. $jtbh = $row['机台编号'];
  298. $bz = $row['班组'] ?: '未分组';
  299. $key = $jtbh . '|' . $bz;
  300. if ($row['运行工时'] >= 8) {
  301. $row['运行工时'] = $row['运行工时'] - 1;
  302. }elseif ($row['运行工时'] < 8 && $row['运行工时'] > 4) {
  303. $row['运行工时'] = $row['运行工时'] - 0.5;
  304. }
  305. if (strpos($row['机台编号'],'YJY') !== false) {
  306. $plate_hours = $row['装板补产工时'] * 1.7;
  307. $plate_mounting_hours = $row['装板实际工时'] * 1.5;
  308. if ($plate_hours < $plate_mounting_hours) {
  309. $row['装板补产工时'] = $plate_hours;
  310. }elseif ($plate_hours > $plate_mounting_hours) {
  311. $row['装板补产工时'] = $plate_mounting_hours;
  312. }elseif ($row['装板补产工时'] > $plate_mounting_hours) {
  313. $row['装板补产工时'] = $row['装板补产工时'];
  314. }else{
  315. $row['装板补产工时'] = $plate_hours;
  316. }
  317. }
  318. if (!isset($resultList[$key])) {
  319. $resultList[$key] = [
  320. '机台编号' => $jtbh,
  321. '班组' => $bz,
  322. '实际产量' => 0,
  323. '装板实际工时' => 0,
  324. '装板补产工时' => 0,
  325. '保养工时' => 0,
  326. '打样总工时' => 0,
  327. '打样补产工时' => 0,
  328. '异常总工时' => 0,
  329. '异常补时' => 0,
  330. '运行工时' => 0,
  331. 'sczl_rq' => date('Ym', strtotime($row['sczl_rq'])),
  332. // 新增字段
  333. '目标产量' => 0,
  334. '负荷产量' => 0,
  335. '小时产能' => $row['小时产能'],
  336. '平均车速' => $row['平均车速']
  337. ];
  338. }
  339. // 累加字段
  340. $resultList[$key]['实际产量'] += floatval($row['sczl_cl']);
  341. $resultList[$key]['装板实际工时'] += floatval($row['装板实际工时']);
  342. $resultList[$key]['装板补产工时'] += floatval($row['装板补产工时']);
  343. $resultList[$key]['保养工时'] += floatval($row['保养工时']);
  344. $resultList[$key]['打样总工时'] += floatval($row['打样总工时']);
  345. $resultList[$key]['打样补产工时'] += floatval($row['打样补产工时']);
  346. $resultList[$key]['异常总工时'] += floatval($row['异常总工时']);
  347. $resultList[$key]['异常补时'] += floatval($row['异常补时']);
  348. $resultList[$key]['运行工时'] += floatval($row['运行工时']);
  349. }
  350. // 汇总并计算目标/负荷产量及达成率
  351. $grouped = []; // [机台编号 => [班组数据...]]
  352. foreach ($resultList as $item) {
  353. $jtbh = $item['机台编号'];
  354. $grouped[$jtbh][] = $item;
  355. }
  356. $finalList = [];
  357. foreach ($grouped as $jtbh => $rows) {
  358. $sum = [
  359. '机台编号' => $jtbh,
  360. '班组' => '合计',
  361. '实际产量' => 0,
  362. '装板实际工时' => 0,
  363. '装板补产工时' => 0,
  364. '保养工时' => 0,
  365. '打样总工时' => 0,
  366. '打样补产工时' => 0,
  367. '异常总工时' => 0,
  368. '异常补时' => 0,
  369. '运行工时' => 0,
  370. '目标产量' => 0,
  371. '负荷产量' => 0,
  372. 'sczl_rq' => $rows[0]['sczl_rq'] ?? '',
  373. ];
  374. foreach ($rows as &$row) {
  375. // 计算目标 & 负荷产量
  376. $有效工时 = max(0, $row['运行工时'] - $row['保养工时'] - $row['装板补产工时'] - $row['异常总工时'] - $row['打样补产工时']);
  377. $row['目标产量'] = round($有效工时 * $row['小时产能'], 2);
  378. $row['负荷产量'] = round($有效工时 * $row['平均车速'], 2);
  379. // 计算达成率 & 利用率
  380. $row['目标达成'] = ($row['目标产量'] > 0)
  381. ? round($row['实际产量'] / $row['目标产量'] * 100, 2) . '%'
  382. : '0%';
  383. $row['综合利用率'] = ($row['负荷产量'] > 0)
  384. ? round($row['实际产量'] / $row['负荷产量'] * 100, 2) . '%'
  385. : '0%';
  386. $finalList[] = $row;
  387. // 合计累加
  388. $sum['实际产量'] += $row['实际产量'];
  389. $sum['装板实际工时'] += $row['装板实际工时'];
  390. $sum['装板补产工时'] += $row['装板补产工时'];
  391. $sum['保养工时'] += $row['保养工时'];
  392. $sum['打样总工时'] += $row['打样总工时'];
  393. $sum['打样补产工时'] += $row['打样补产工时'];
  394. $sum['异常总工时'] += $row['异常总工时'];
  395. $sum['异常补时'] += $row['异常补时'];
  396. $sum['运行工时'] += $row['运行工时'];
  397. $sum['目标产量'] += $row['目标产量'];
  398. $sum['负荷产量'] += $row['负荷产量'];
  399. }
  400. // 合计达成率
  401. $sum['目标达成'] = ($sum['目标产量'] > 0)
  402. ? round($sum['实际产量'] / $sum['目标产量'] * 100, 2) . '%'
  403. : '0%';
  404. $sum['综合利用率'] = ($sum['负荷产量'] > 0)
  405. ? round($sum['实际产量'] / $sum['负荷产量'] * 100, 2) . '%'
  406. : '0%';
  407. $finalList[] = $sum;
  408. }
  409. $this->success('汇总成功', $finalList);
  410. }
  411. /**
  412. * 1.5达成率统计 -> 按日期+工单统计生产明细
  413. */
  414. public function Machine_production_details()
  415. {
  416. if (!$this->request->isGet()) {
  417. $this->error('请求方式错误');
  418. }
  419. $param = $this->request->param();
  420. if (empty($param['jtbh']) || empty($param['rq'])) {
  421. $this->error('缺少必要参数:jtbh(机台编号)、rq(年月)');
  422. }
  423. $jtbh = $param['jtbh'];
  424. $rq = $param['rq'];
  425. $ym = substr($rq, 0, 4) . '-' . substr($rq, 4, 2);
  426. // 查询该月份内该机台的每日工单产量明细
  427. $records = Db::name('设备_产量计酬')->alias('a')
  428. ->field([
  429. 'a.sczl_jtbh as 机台编号',
  430. 'a.sczl_rq as 日期',
  431. 'a.sczl_bzdh as 班组',
  432. 'a.sczl_gdbh as 工单编号',
  433. 'b.yj_yjmc as 印件名称',
  434. 'a.sczl_yjno as 印件号',
  435. 'a.sczl_gxh as 工序号',
  436. 'a.sczl_gxmc as 工序名称',
  437. 'a.sczl_ls',
  438. 'SUM(a.sczl_cl) as 实际产量',
  439. 'SUM(a.sczl_装版总工时) as 装版实际工时',
  440. 'SUM(a.sczl_装版工时) as 装版补产工时',
  441. 'SUM(a.sczl_保养工时) as 保养工时',
  442. 'SUM(a.sczl_打样总工时) as 打样总工时',
  443. 'SUM(a.sczl_打样工时) as 打样补产工时',
  444. 'SUM(a.sczl_异常停机工时) as 异常总工时',
  445. 'SUM(a.sczl_异常工时1) as 异常补时',
  446. 'SUM(a.sczl_设备运行工时) as 运行工时',
  447. 'c.排单小时定额 as 小时产能',
  448. 'c.平均车速',
  449. 'd.工价系数 as 难度系数'
  450. ])
  451. ->join('工单_印件资料 b', 'a.sczl_gdbh = b.Yj_Gdbh AND a.sczl_yjno = b.Yj_YjNo', 'LEFT') // 添加印件号关联条件
  452. ->join('设备_基本资料 c', 'a.sczl_jtbh = c.设备编号')
  453. ->join('工单_工艺资料 d', 'a.sczl_gdbh = d.Gy0_gdbh AND a.sczl_yjno = d.Gy0_yjno AND a.sczl_gxh = d.Gy0_gxh', 'LEFT')
  454. ->where('a.sczl_jtbh', $jtbh)
  455. ->whereLike('a.sczl_rq', $ym . '%')
  456. ->group('a.sczl_rq, a.sczl_gdbh, a.sczl_yjno, a.sczl_gxh, a.sczl_jtbh ,a.sczl_bzdh') // 确保唯一性分组
  457. ->order('a.sczl_rq desc, a.sczl_bzdh')
  458. ->select();
  459. // 查询每个班组的运行工时
  460. $Operating_hours = \db('设备_产量计酬')
  461. ->field('sczl_rq as 日期,sczl_bzdh as 班组,sum(sczl_设备运行工时) as 设备运行工时')
  462. ->where('sczl_jtbh', $jtbh)
  463. ->whereLike('sczl_rq', $ym . '%')
  464. ->group('sczl_rq, sczl_bzdh')
  465. ->order('sczl_rq desc, sczl_bzdh')
  466. ->select();
  467. // 设备运行达成率设备运行工时计算规则:
  468. // 1.上报通电工时>8小时,设备运行工时=上报通电工时-1小时
  469. // 2.上报通电工时<8小时且上报通电工时>4小时,设备运行工时= 上报通电工时-0.5小时
  470. // 3.上报通电工时<4小时,设备运行工时 = 上报通电工时
  471. foreach ($Operating_hours as $k => $v) {
  472. if ($v['设备运行工时'] >= 8) {
  473. $Operating_hours[$k]['设备运行工时'] = $v['设备运行工时'] - 1;
  474. }elseif ($v['设备运行工时'] < 8 && $v['设备运行工时'] > 4) {
  475. $Operating_hours[$k]['设备运行工时'] = $v['设备运行工时'] - 0.5;
  476. }else{
  477. $Operating_hours[$k]['设备运行工时'] = $v['设备运行工时'];
  478. }
  479. }
  480. // 数据格式化与目标产量计算
  481. foreach ($records as $key => $row) {
  482. $records[$key]['日期'] = date('Y-m-d', strtotime($row['日期']));
  483. $records[$key]['印件工序'] = $row['印件号'] . '-' . $row['工序名称'];
  484. // 胶印设备换型工时(装版补产工时)计算规则:
  485. //1.按班次工单分开计算装版补产工时,基础计算规则:装版补产工时*1.7
  486. //2.当装版补产工时*1.7<实际装版工时*1.5时,按照装版补产工时*1.7计算
  487. //3.当装版补产工时*1.7>实际装版工时*1.5,按照实际装版工时*1.5计算
  488. //4.当装版补产工时>实际装版工时*1.5,按照装版补产工时计算
  489. if (strpos($row['机台编号'],'YJY') !== false) {
  490. $plate_hours = $row['装版补产工时'] * 1.7;
  491. $plate_mounting_hours = $row['装版实际工时'] * 1.5;
  492. if ($plate_hours < $plate_mounting_hours) {
  493. $records[$key]['装版补产工时'] = $plate_hours;
  494. }elseif ($plate_hours > $plate_mounting_hours) {
  495. $records[$key]['装版补产工时'] = $plate_mounting_hours;
  496. }elseif ($row['装版补产工时'] > $plate_mounting_hours) {
  497. $records[$key]['装版补产工时'] = $row['装版补产工时'];
  498. }else{
  499. $records[$key]['装版补产工时'] = $plate_hours;
  500. }
  501. }
  502. // 计算目标产量
  503. foreach ($Operating_hours as $k => $v) {
  504. if ($v['日期'] === $row['日期'] && $v['班组'] === $row['班组']) {
  505. //重新赋值运行工时
  506. $records[$key]['运行工时'] = $v['设备运行工时'];
  507. //计算目标产量
  508. $records[$key]['目标产量'] = round(
  509. max(0, $v['设备运行工时'] - $row['保养工时'] - $row['装版补产工时'] - $row['异常补时'] - $row['打样补产工时']) * $row['小时产能'],
  510. 2
  511. );
  512. // 计算负荷产量
  513. $records[$key]['负荷产量'] = round(
  514. max(0, $v['设备运行工时'] - $row['保养工时'] - $row['异常补时'] - $row['打样补产工时'] ) * $row['平均车速'],
  515. 2
  516. );
  517. // 计算目标达成率
  518. $records[$key]['目标达成'] = $records[$key]['目标产量'] > 0
  519. ? round($row['实际产量'] / $records[$key]['目标产量'] * 100, 2) . '%'
  520. : '0%';
  521. // 计算综合利用率
  522. $records[$key]['综合利用率'] = $records[$key]['负荷产量'] > 0
  523. ? round($row['实际产量'] / $records[$key]['负荷产量'] * 100, 2) . '%'
  524. : '0%';
  525. }
  526. }
  527. }
  528. $this->success('明细获取成功', $records);
  529. }
  530. /**
  531. * 1.6达成率统计->按时段导出Excel
  532. */
  533. public function Machine_date_excel()
  534. {
  535. if (!$this->request->isGet()) {
  536. $this->error('请求方式错误');
  537. }
  538. $param = $this->request->param();
  539. if (empty($param['start_rq']) || empty($param['end_rq']) || empty($param['bm'])) {
  540. $this->error('缺少参数:start_rq(开始日期)或 end_rq(结束日期)或 bm(部门)');
  541. }
  542. $start_rq = $param['start_rq'];
  543. $end_rq = $param['end_rq'];
  544. $bm = $param['bm'];
  545. // 1. 先查询设备_基本资料表,获取该部门下的所有设备编号(去重)
  546. $deviceIds = Db::name('设备_基本资料')
  547. ->where('使用部门', $bm)
  548. ->group('设备编号') // 去重
  549. ->column('设备编号');
  550. if (empty($deviceIds)) {
  551. $this->error('该部门下没有设备数据');
  552. }
  553. // 2. 查询设备_产量计酬表,筛选符合条件的记录
  554. $records = Db::name('设备_产量计酬')->alias('a')
  555. ->field([
  556. 'a.sczl_jtbh as 机台编号',
  557. 'a.sczl_rq as 日期',
  558. 'a.sczl_bzdh as 班组',
  559. 'a.sczl_gdbh as 工单编号',
  560. 'b.yj_yjmc as 印件名称',
  561. 'a.sczl_yjno as 印件号',
  562. 'a.sczl_gxh as 工序号',
  563. 'a.sczl_gxmc as 工序名称',
  564. 'a.sczl_ls',
  565. 'SUM(a.sczl_cl) as 实际产量',
  566. 'sczl_装版总工时 as 装板实际工时',
  567. 'sczl_装版工时 as 装板补产工时',
  568. 'sczl_保养工时 as 保养工时',
  569. 'sczl_打样总工时 as 打样总工时',
  570. 'sczl_打样工时 as 打样补产工时',
  571. 'sczl_异常停机工时 as 异常总工时',
  572. 'sczl_异常工时1 as 异常补时',
  573. 'sczl_设备运行工时 as 运行工时'
  574. ])
  575. ->join('工单_印件资料 b', 'a.sczl_gdbh = b.Yj_Gdbh')
  576. ->whereIn('a.sczl_jtbh', $deviceIds) // 使用设备编号列表筛选
  577. ->whereBetween('a.sczl_rq', [
  578. $start_rq . ' 00:00:00',
  579. $end_rq . ' 23:59:59'
  580. ])
  581. ->group('a.sczl_jtbh, a.sczl_rq, a.sczl_bzdh, a.sczl_gdbh') // 按设备、日期、班组、工单分组
  582. ->order('a.sczl_rq desc')
  583. ->select();
  584. // 格式化数据
  585. foreach ($records as &$row) {
  586. $row['日期'] = date('Y-m-d', strtotime($row['日期']));
  587. $row['印件工序'] = $row['印件号'] . '-' . $row['工序名称'];
  588. }
  589. $this->success('明细获取成功', $records);
  590. }
  591. /**
  592. * 01.产品年度投入产出率统计->左侧菜单
  593. */
  594. // public function left_Productyear() {
  595. // $list = \db('产品_基本资料')
  596. // ->field('客户编号,客户名称,Mod_rq')
  597. // ->group('客户编号,客户名称,Mod_rq')
  598. // ->where('客户编号','<>','')
  599. // ->order('客户编号')
  600. // ->select();
  601. //
  602. //
  603. // $data['翌星工单'] = [];
  604. // $data['MN工单'] = [];
  605. //
  606. // foreach ($list as $key => $value) {
  607. // $value['客户编号'] = rtrim($value['客户编号']);
  608. // $value['客户名称'] = rtrim($value['客户名称']);
  609. // if (empty($value['客户名称'])) {
  610. // continue;
  611. // }
  612. //
  613. // $name = $value['客户编号'] . '【' . $value['客户名称'] . '】';
  614. // $year = date('Y', strtotime($value['Mod_rq']));
  615. // $uniqueKey = $value['客户编号'] . '_' . $value['客户名称'] . '_' . $year;
  616. //
  617. // if (isset($seenEntries[$uniqueKey])) {
  618. // continue; // 如果已经存在,跳过重复项
  619. // }
  620. // $seenEntries[$uniqueKey] = true;
  621. //
  622. // if (strpos($value['客户编号'], 'J') !== false || strpos($value['客户编号'], 'Y') !== false) {
  623. // if (!isset($data['翌星工单'][$year])) {
  624. // $data['翌星工单'][$year] = [];
  625. // }
  626. // array_push($data['翌星工单'][$year], $name);
  627. // } else {
  628. // if (!isset($data['MN工单'][$year])) {
  629. // $data['MN工单'][$year] = [];
  630. // }
  631. // array_push($data['MN工单'][$year], $name);
  632. // }
  633. // }
  634. //
  635. // // 按年份排序(从最新到最旧)
  636. // krsort($data['翌星工单']);
  637. // krsort($data['MN工单']);
  638. //
  639. // // 对每个年份内的数据进行排序(可选)
  640. // foreach ($data['翌星工单'] as $year => &$items) {
  641. // sort($items);
  642. // }
  643. // foreach ($data['MN工单'] as $year => &$items) {
  644. // sort($items);
  645. // }
  646. // $this->success('成功', $data);
  647. // }
  648. public function left_Productyear() {
  649. $list = \db('产品_基本资料')
  650. ->field('客户编号,客户名称')
  651. ->group('客户编号,客户名称')
  652. ->where('客户编号','<>','')
  653. ->order('客户编号')
  654. ->select();
  655. $data['翌星工单'] = [];
  656. $data['MN工单'] = [];
  657. $seenEntries = []; // 添加这个变量来跟踪已处理的条目
  658. foreach ($list as $key => $value) {
  659. $value['客户编号'] = rtrim($value['客户编号']);
  660. $value['客户名称'] = rtrim($value['客户名称']);
  661. if (empty($value['客户名称'])) {
  662. continue;
  663. }
  664. // 获取工单信息,包含Sys_rq字段
  665. $productIng = \db('工单_基本资料')
  666. ->field('Sys_rq')
  667. ->where('Gd_cpdh|成品代号', 'LIKE', rtrim($value['客户编号']) . '%')
  668. ->order('Sys_rq DESC')
  669. ->find();
  670. // 如果没有找到相关工单,跳过
  671. if (!$productIng || empty($productIng['Sys_rq'])) {
  672. continue;
  673. }
  674. $name = $value['客户编号'] . '【' . $value['客户名称'] . '】';
  675. $year = date('Y', strtotime($productIng['Sys_rq']));
  676. $uniqueKey = $value['客户编号'] . '_' . $value['客户名称'] . '_' . $year;
  677. if (isset($seenEntries[$uniqueKey])) {
  678. continue; // 如果已经存在,跳过重复项
  679. }
  680. $seenEntries[$uniqueKey] = true;
  681. if (strpos($value['客户编号'], 'J') !== false || strpos($value['客户编号'], 'Y') !== false) {
  682. if (!isset($data['翌星工单'][$year])) {
  683. $data['翌星工单'][$year] = [];
  684. }
  685. array_push($data['翌星工单'][$year], $name);
  686. } else {
  687. if (!isset($data['MN工单'][$year])) {
  688. $data['MN工单'][$year] = [];
  689. }
  690. array_push($data['MN工单'][$year], $name);
  691. }
  692. }
  693. // 按年份排序(从最新到最旧)
  694. krsort($data['翌星工单']);
  695. krsort($data['MN工单']);
  696. // 对每个年份内的数据进行排序(可选)
  697. foreach ($data['翌星工单'] as $year => &$items) {
  698. sort($items);
  699. }
  700. foreach ($data['MN工单'] as $year => &$items) {
  701. sort($items);
  702. }
  703. $this->success('成功', $data);
  704. }
  705. /**
  706. * 01.产品年度投入产出率统计->数据汇总表
  707. */
  708. public function list_Productyear() {
  709. if ($this->request->isGet() === false) {
  710. $this->error('请求错误');
  711. }
  712. $param = $this->request->param();
  713. $rq = $param['rq'];
  714. $where = [];
  715. if (!empty($param['search'])){
  716. $where['产品代号|产品名称'] = ['like','%'.$param['search'].'%'];
  717. }
  718. if (!empty($param['khdh'])){
  719. $where['产品代号'] = ['like',$param['khdh'].'%'];
  720. }
  721. $qualityData = \db('工单_质量考核汇总')
  722. ->field('Gy0_gdbh, 客户代号, 入仓日期 as sys_rq, 实际投料, 入仓数量, 产品代号, 产品名称, 销售订单号, 订单数量,计量单位')
  723. ->where('YEAR(Sys_rq)', $rq)
  724. ->where($where)
  725. ->select();
  726. if (empty($qualityData)) {
  727. $this->success('未查询到数据', []);
  728. }
  729. // 第一步:按工单去重,每个工单只取一条记录
  730. $uniqueByGongdan = [];
  731. foreach ($qualityData as $data) {
  732. $gdbh = $data['Gy0_gdbh'];
  733. if (!isset($uniqueByGongdan[$gdbh])) {
  734. $uniqueByGongdan[$gdbh] = $data;
  735. }
  736. }
  737. // 第二步:按产品代号和月份分组并计算总和
  738. $productMap = [];
  739. foreach ($uniqueByGongdan as $gdbh => $data) {
  740. $productCode = $data['产品代号'];
  741. $sysRq = $data['sys_rq'];
  742. // 提取月份1-12 的月份数字
  743. $month = date('n', strtotime($sysRq));
  744. if (!isset($productMap[$productCode])) {
  745. $productMap[$productCode] = [
  746. 'sys_rq' => substr($data['sys_rq'], 0, 4),
  747. '计量单位' => $data['计量单位'],
  748. '成品编码' => $data['产品代号'],
  749. '成品名称' => $data['产品名称'],
  750. 'months' => [],
  751. '实际投料' => 0,
  752. '入仓数量' => 0,
  753. '工单列表' => [] // 记录包含的工单编号
  754. ];
  755. }
  756. if (!isset($productMap[$productCode]['months'][$month])) {
  757. $productMap[$productCode]['months'][$month] = [
  758. '实际投料' => 0,
  759. '入仓数量' => 0
  760. ];
  761. }
  762. //实际投料先乘以10000再累加
  763. $adjustedActual = round($data['实际投料'] * 10000);
  764. // 累加月度数据
  765. $productMap[$productCode]['months'][$month]['实际投料'] += $adjustedActual;
  766. $productMap[$productCode]['months'][$month]['入仓数量'] += $data['入仓数量'];
  767. // 累加年度总量(实际投料已经乘以10000)
  768. $productMap[$productCode]['实际投料'] += $adjustedActual;
  769. $productMap[$productCode]['入仓数量'] += $data['入仓数量'];
  770. // 记录工单编号
  771. $productMap[$productCode]['工单列表'][] = $data['Gy0_gdbh'];
  772. }
  773. //月份
  774. $monthNames = [
  775. 1 => '1月', 2 => '2月', 3 => '3月', 4 => '4月',
  776. 5 => '5月', 6 => '6月', 7 => '7月', 8 => '8月',
  777. 9 => '9月', 10 => '10月', 11 => '11月', 12 => '12月'
  778. ];
  779. //合并数据并计算合格率
  780. $result = [];
  781. foreach ($productMap as $productCode => $productData) {
  782. $resultItem = [
  783. 'sys_rq' => $productData['sys_rq'],
  784. '成品编码' => $productData['成品编码'],
  785. '成品名称' => $productData['成品名称'],
  786. '实际投料' => $productData['实际投料'],
  787. '入仓数量' => $productData['入仓数量'],
  788. '计量单位' => $productData['计量单位'],
  789. '工单数量' => count($productData['工单列表']),
  790. '工单列表' => implode(', ', $productData['工单列表'])
  791. ];
  792. // 初始化各月份数据
  793. foreach ($monthNames as $monthNum => $monthName) {
  794. $resultItem[$monthName] = '-';
  795. }
  796. // 处理该产品的月度数据
  797. if (isset($productData['months'])) {
  798. foreach ($productData['months'] as $month => $monthData) {
  799. $adjustedActual = $monthData['实际投料'];
  800. $delivery = $monthData['入仓数量'];
  801. // 计算月度合格率
  802. if ($adjustedActual > 0) {
  803. $monthlyRate = round(($delivery / $adjustedActual) * 100, 2);
  804. $resultItem[$monthNames[$month]] = $monthlyRate . '%';
  805. } else if ($delivery > 0) {
  806. $resultItem[$monthNames[$month]] = '100%';
  807. } else {
  808. $resultItem[$monthNames[$month]] = '0%';
  809. }
  810. }
  811. }
  812. // 计算年度综合合格率
  813. if ($resultItem['实际投料'] > 0) {
  814. $overallRate = round(($resultItem['入仓数量'] / $resultItem['实际投料']) * 100, 2);
  815. $resultItem['综合合格率'] = $overallRate . '%';
  816. } else if ($resultItem['入仓数量'] > 0) {
  817. $resultItem['综合合格率'] = '100%';
  818. } else {
  819. $resultItem['综合合格率'] = '0%';
  820. }
  821. $result[] = $resultItem;
  822. }
  823. $this->success('成功', $result);
  824. }
  825. /**
  826. * 01.产品年度投入产出率统计->数据明细表
  827. */
  828. public function list_Productmonth() {
  829. if ($this->request->isGet() === false) {
  830. $this->error('请求错误');
  831. }
  832. $param = $this->request->param();
  833. $productCode = $param['product_code'] ?? '';
  834. $year = $param['year'] ?? date('Y');
  835. if (empty($productCode)) {
  836. $this->error('请提供成品编码');
  837. }
  838. // 1. 查询对应的工单数据
  839. $qualityData = \db('工单_质量考核汇总')
  840. ->field('Gy0_gdbh as 工单编号, 订单数量, 入仓日期, 实际投料, 入仓数量, 客户代号, 客户名称, 产品代号, 产品名称, 销售订单号')
  841. ->where('产品代号', $productCode)
  842. ->where('YEAR(入仓日期)', $year)
  843. ->order('入仓日期','desc')
  844. ->select();
  845. if (empty($qualityData)) {
  846. $this->success('该产品无质量考核数据', []);
  847. }
  848. // 2. 先按工单去重,每个工单只取一条记录
  849. $uniqueByGongdan = [];
  850. foreach ($qualityData as $data) {
  851. $gdbh = $data['工单编号'];
  852. if (!isset($uniqueByGongdan[$gdbh])) {
  853. $uniqueByGongdan[$gdbh] = $data;
  854. }
  855. }
  856. // 3. 按月份分组累计数据
  857. $monthlyData = [];
  858. // $monthNames = [
  859. // 1 => '1月', 2 => '2月', 3 => '3月', 4 => '4月',
  860. // 5 => '5月', 6 => '6月', 7 => '7月', 8 => '8月',
  861. // 9 => '9月', 10 => '10月', 11 => '11月', 12 => '12月'
  862. // ];
  863. foreach ($uniqueByGongdan as $gdbh => $data) {
  864. $sysRq = $data['入仓日期'];
  865. $month = date('n', strtotime($sysRq)); // 1-12 的月份数字
  866. // 初始化月份数据
  867. if (!isset($monthlyData[$data['工单编号']])) {
  868. $monthlyData[$data['工单编号']] = [
  869. '月份' => $month,
  870. '订单数量' => 0,
  871. '实际投料' => 0,
  872. '入仓数量' => 0,
  873. '入仓日期' => $data['入仓日期'],
  874. '客户代号' => $data['客户代号'],
  875. '客户名称' => $data['客户名称'],
  876. '产品代号' => $data['产品代号'],
  877. '产品名称' => $data['产品名称'],
  878. '销售订单号' => $data['销售订单号']
  879. ];
  880. }
  881. $monthlyData[$data['工单编号']]['订单数量'] += round($data['订单数量'] * 10000);
  882. $monthlyData[$data['工单编号']]['实际投料'] += round($data['实际投料'] * 10000);
  883. $monthlyData[$data['工单编号']]['入仓数量'] += round($data['入仓数量']);
  884. // 记录工单编号
  885. $monthlyData[$data['工单编号']]['工单编号'] = $data['工单编号'];
  886. }
  887. // 4. 计算每个月的实际合格率并整理结果
  888. $detailList = [];
  889. foreach ($monthlyData as $month => $monthData) {
  890. // 计算实际合格率
  891. $actualRate = '-';
  892. if ($monthData['实际投料'] > 0) {
  893. $actualRate = round(($monthData['入仓数量'] / $monthData['实际投料']) * 100, 2) . '%';
  894. } else if ($monthData['入仓数量'] > 0) {
  895. $actualRate = '100%';
  896. } else {
  897. $actualRate = '0%';
  898. }
  899. $detailList[$month] = [
  900. '日期' => $monthData['月份'],
  901. '入仓日期' => substr($monthData['入仓日期'], 0, 10),
  902. '订单数量' => $monthData['订单数量'],
  903. '实际投料' => $monthData['实际投料'],
  904. '入仓数量' => $monthData['入仓数量'],
  905. '实际合格率' => $actualRate,
  906. '客户代号' => $monthData['客户代号'],
  907. '客户名称' => $monthData['客户名称'],
  908. '产品代号' => $monthData['产品代号'],
  909. '产品名称' => $monthData['产品名称'],
  910. '销售订单号' => $monthData['销售订单号'],
  911. '工单编号' => $monthData['工单编号']
  912. ];
  913. }
  914. $this->success('成功', array_values($detailList));
  915. }
  916. }