SCTMES_V5/mes_in_sct/app/action/SetTrayBinding.php
2025-06-14 18:55:09 +08:00

589 lines
27 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\action;
use Exception;
use libs\db\Db;
use libs\listener\Event;
/**
* 托盘绑定接口
* Class SetTrayBinding
* @package app\action
*/
class SetTrayBinding
{
public function execute($post)
{
// 验证数据
$param = check_valid($post['action'], [
['tray', 'string', '托盘号'],
['workingsubclass', 'string', '工序单元'],
['device_code', 'string', '设备编码'],
['battery_ids', 'array', '电池条码数组']
], $post['param']);
/**
* 托盘绑定
* 1 确认本托盘并未激活
* 2 确认输入的电池都有存在 battery map 查
* 3 确认电池之前的托盘已经停用
* 4 确认电池在之前托盘是激活状态
* 5 所有录入的电池的批次必须是一样的
* 6 所有的电池的process_code必须是一样的
* 7 tray map添加本托盘和工序的绑定
* 8 battery map里面添加本托盘和批次电池信息的绑定
* 9 复制process_log的信息并将tray改为本托盘
* 10 bkv表上复制battery的信息(顺序)并将tray改为本托盘
* 11 删除bkv表上原battery的信息
* 12 如果next_process_code=-1则把托盘active置为0并把电池active置为0
*/
try {
list($tray, $battery_ids) = [$param['tray'], $param['battery_ids']];
$currentTime = date('Y-m-d H:i:s');
// 赋予开始时间结果参数数组
$param['START_TIME'] = $currentTime;
// 赋予完成时间结果参数数组
$param['FINISH_TIME'] = $currentTime;
// 判断是否存在不是字符串'0'的情况,约束托盘空位值只能传字符串'0'而不是其他值
$filteredArray = array_filter($battery_ids, function ($value) {
return $value !== '0' && empty($value);
}, ARRAY_FILTER_USE_BOTH);
if (count($filteredArray) > 0) {
$keys = implode(',', array_keys($filteredArray));
throw new Exception("电池条码数组[battery_ids]以下位置[{$keys}]中存在不合法的值,如[0, '', null, NAN]等,电池条码值只能是[字符串0或者真实条码]");
}
// 判断电池是否存在重复值
$filteredArray = array_filter($battery_ids, function ($value) {
return !empty($value);
});
$repeat_batterys = array_keys(array_count_values($filteredArray), 2);
if (count($repeat_batterys) > 0) {
$repeat_keys = implode(',', array_values($repeat_batterys));
throw new Exception("电池条码数组[battery_ids]存在重复的电池条码[{$repeat_keys}],请检查!");
}
// 1 确认本托盘并未激活
$sql = sprintf(
"SELECT id
FROM hf_mes_production_tray_map
WHERE tray='%s' AND active=1 LIMIT 1;",
$tray
);
$ret = Db::fetch($sql);
if (!empty($ret)) {
throw new Exception("该托盘[$tray]已经激活", 4001);
}
list($batch, $process_code, $next_process_code, $date_log, $first_battery, $old_battery_arr) = [
'',
'',
-1,
array(),
'',
array()
];
// 记录第一个电池的挡位,用以判断全部电池的挡位是否一致
$is_classname_arr = [];
// 实际投入数
$actual_input_battery_count = 0;
//判断批次是否存在存在获取工艺信息
foreach ($battery_ids as $val) {
// 空电池直接跳出循环
if ($val === "0" || $val === 0 || $val === "") {
continue;
}
// 2 确认输入的电池都有存在 battery_map
$sql = sprintf(
"SELECT batch,subbatch,tray,lot
FROM hf_mes_production_battery_map
WHERE battery_id='%s' ORDER BY id DESC LIMIT 1;",
$val
);
$ret = Db::fetch($sql);
if (empty($ret)) {
throw new Exception("电池ID[$val]不存在", 4001);
}
list($old_batch, $old_subbatch, $old_tray, $old_lot) = [
$ret['batch'],
$ret['subbatch'],
$ret['tray'],
$ret['lot'],
];
array_push($old_battery_arr, [
'old_batch' => $old_batch,
'old_subbatch' => $old_subbatch,
'old_tray' => $old_tray,
'old_lot' => $old_lot,
'battery_id' => $val
]);
// 4 确认电池在之前托盘是激活状态
$sql = sprintf(
"SELECT id,process_code,classname
FROM \"%s\"
WHERE tray='%s' AND lot='%s' AND battery_id='%s' AND active=1 LIMIT 1;",
"hf_mes_tmp_bkv_{$old_subbatch}",
$old_tray,
$old_lot,
$val
);
$ret = Db::fetch($sql);
if (empty($ret)) {
throw new Exception("电池ID[$val]在原托盘[$old_tray]中不是激活状态", 4001);
}
// 判断全部电池的挡位是否一致
array_push($is_classname_arr, $ret['classname']);
$ret_process_code = $ret['process_code'];
if ($first_battery == "") {
$first_battery = $val;
}
// 5 所有录入的电池的批次必须是一样的
if ($batch == "") {
$batch = $old_batch;
}
if ($batch != $old_batch) {
throw new Exception("托盘混批了,电池" . $val . "的批次" . $old_batch . "与第一个电池[$first_battery]批次" . $batch . "不一致", 4001);
}
// 6 所有的电池的next_process_code必须是一样的
if ($process_code == "") {
$process_code = $ret_process_code;
} else if ($process_code != $ret_process_code) {
throw new Exception("电池[$val]工序编码[$ret_process_code]与第一个电池[$first_battery]工序编码[$process_code]不一致", 4001);
}
if ($batch == "") {
throw new Exception("批次不存在", 4001);
}
$sql = sprintf(
"SELECT a.flow_id, b.process
FROM hf_mes_production_planning_management_batch AS a
INNER JOIN hf_mes_technology_flow AS b ON b.id = a.flow_id
WHERE a.batch='%s' LIMIT 1;",
$batch
);
$ret = Db::fetch($sql);
if (empty($ret)) {
throw new Exception("该批次[{$batch}]不存在");
}
list($flow_id, $flow_process) = [$ret['flow_id'], json_decode($ret['process'], true)];
// 3 确认电池之前的托盘已经停用
if ($old_tray != '-1') {
$sql = sprintf(
"SELECT id, active, process_code, process_idx, next_process_code, date_log
FROM hf_mes_production_tray_map
WHERE batch='%s' AND subbatch='%s' AND tray='%s' AND lot='%s' LIMIT 1;",
$old_batch,
$old_subbatch,
$old_tray,
$old_lot
);
$ret = Db::fetch($sql);
if (!empty($ret)) {
if ($ret['active'] == 1) {
// throw new Exception("电池ID[$val]的原托盘[$old_tray]还是激活状态", 4001);
throw new Exception("电池ID[$val]当前仍绑定在托盘[$old_tray],该托盘处于激活状态!无法绑定至新托盘[$tray]。请先确认原托盘的绑定关系。", 4001);
}
}
$date_log = $ret['date_log'];
} else {
//直接重新生成date_log
$date_log = [];
// 拼接当前的process_code
$current_process_code = "{$flow_id}_{$param['workingsubclass']}";
foreach ($flow_process as $item) {
array_push($date_log, [
'idx' => $item[0],
'flow_process_id' => $item[1],
'flow_process_code' => $item[2],
'beginTime' => $current_process_code == $item[2] ? $param['START_TIME'] : '',
'endTime' => $current_process_code == $item[2] ? $param['FINISH_TIME'] : '',
'device_code' => $current_process_code == $item[2] ? $param['device_code'] : ''
]);
}
}
$actual_input_battery_count++;
}
// 找到process_idx和next_process_code
$sql = sprintf(
"SELECT a.batch, b.process as process
FROM hf_mes_production_planning_management_batch a
INNER JOIN hf_mes_technology_flow b ON b.id = a.flow_id
WHERE a.batch='%s' LIMIT 1;",
$batch
);
$ret = Db::fetch($sql);
$process_obj = json_decode($ret['process']);
$last_process_idx = -1;
foreach ($process_obj as $val) {
if ($val[2] == $process_code) {
$last_process_idx = $val[0];
}
}
if ($last_process_idx == -1) {
throw new Exception("电池不存在下个工序", 4001);
}
$process_idx = $last_process_idx;
if (!empty($process_obj[$last_process_idx + 1][2])) {
$next_process_code = $process_obj[$last_process_idx + 1][2];
}
// 特殊处理:构成下料需要绑定托盘时,重新赋予$process_code、$process_idx、$next_process_code
// $even_data = Event::emit('SetTrayBindingEvent.createNextProcessCode', [
// 'process_obj' => $process_obj,
// 'workingsubclass' => $param['workingsubclass'],
// 'date' => date('Y-m-d H:i:s'),
// 'device_code' => $param['device_code']
// ]);
// if (!empty($even_data)) {
// $process_code = $even_data['process_code'];
// $process_idx = $even_data['process_idx'];
// $next_process_code = $even_data['next_process_code'];
// $date_log = json_encode($even_data['date_log'], JSON_UNESCAPED_UNICODE);
// }
// 获取子批次
$sql = sprintf(
"SELECT a.subbatch,a.batch_id
FROM hf_mes_production_planning_management_subbatch AS a
INNER JOIN hf_mes_production_planning_management_batch b ON b.id = a.batch_id
WHERE b.batch='%s' ORDER BY a.id DESC LIMIT 1;",
$batch
);
$ret = Db::fetch($sql);
if (empty($ret)) {
throw new Exception("不存在子批次数据", 4001);
}
$subbatch = $ret['subbatch'];
} catch (Exception $e) {
throw new Exception($e->getMessage(), $e->getCode() ? $e->getCode() : 4001);
}
Db::beginTrans();
try {
$input_battery_count = count($battery_ids);
// 标记最后一条数据的状态
Event::emit('SetProcessLogEvent.updateLastStatus', $battery_ids);
// 7 tray map添加本托盘和工序的绑定
$lot = get_subtraction();
// $sql = sprintf(
// "SELECT lot
// FROM hf_mes_production_tray_map
// WHERE batch='%s' AND tray='%s' ORDER BY id DESC LIMIT 1;",
// $batch,
// $tray
// );
// $ret = Db::fetch($sql);
// if (!empty($ret)) {
// $lot = str_pad(intval($ret[0]['lot']) + 1, 4, "0", STR_PAD_LEFT);
// }
// 写入tray_map数据
$tray_map_id = Db::insert('hf_mes_production_tray_map', [
'tray_unique_value' => "{$batch}_{$subbatch}_{$tray}_{$lot}", // 数据库要做唯一索引,目的防止登录超时写入多条数据
'batch' => $batch,
'subbatch' => $subbatch,
'tray' => $tray,
'lot' => $lot,
'active' => 1,
'process_code' => $process_code,
'process_idx' => $process_idx,
'next_process_code' => $next_process_code,
'date_log' => is_array($date_log) ? json_encode($date_log, JSON_UNESCAPED_UNICODE) : $date_log,
'input_battery_count' => $input_battery_count,
'actual_input_battery_count' => $actual_input_battery_count
]);
if ($tray_map_id === NULL) {
throw new Exception("写入tray_map数据失败", 4001);
}
// 8 battery map里面添加本托盘和批次电池信息的绑定
// 9 复制process_log的信息并将tray改为本托盘
$sql = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE table_name = 'hf_mes_production_battery_map' ORDER BY ORDINAL_POSITION ASC";
$battery_map_ret = Db::query($sql);
$battery_map_key_arr = [];
foreach (array_column($battery_map_ret, 'column_name') as $val) {
if ($val != "id") {
$battery_map_key_arr[] = '"' . $val . '"';
}
}
$battery_map_sql_key_str = implode(",", $battery_map_key_arr);
$sql = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE table_name = 'hf_mes_bkv_batch_process_log' ORDER BY ORDINAL_POSITION ASC";
$process_log_ret = Db::query($sql);
$process_log_key_arr = [];
foreach (array_column($process_log_ret, 'column_name') as $val) {
if ($val != "id") {
$process_log_key_arr[] = '"' . $val . '"';
}
}
$process_log_sql_key_str = implode(",", $process_log_key_arr);
// 以电池条码为下标key
$old_battery_arr_column = array_column($old_battery_arr, null, 'battery_id');
$battery_map_sql_val_str = [];
$process_log_sql_val_str = [];
foreach ($battery_ids as $item1) {
// 空电池直接跳出循环
if ($item1 === "0" || $item1 === 0 || $item1 === "") {
continue;
}
// 处理battery_map的数据
$sql = sprintf(
"SELECT %s FROM hf_mes_production_battery_map WHERE batch='%s' AND subbatch='%s' AND tray='%s' AND lot='%s' AND battery_id='%s' LIMIT 1;",
$battery_map_sql_key_str,
$old_battery_arr_column[$item1]['old_batch'],
$old_battery_arr_column[$item1]['old_subbatch'],
$old_battery_arr_column[$item1]['old_tray'],
$old_battery_arr_column[$item1]['old_lot'],
$old_battery_arr_column[$item1]['battery_id']
);
$battery_map_insert_ret = Db::query($sql);
if (empty($battery_map_insert_ret)) {
throw new Exception("SELECT key failed:[hf_mes_production_battery_map]", 4001);
}
$battery_map_insert_ret['tray'] = $tray;
$battery_map_insert_ret['lot'] = $lot;
$battery_map_insert_ret['battery_unique_value'] = "{$batch}_{$subbatch}_{$tray}_{$lot}_{$item1}";
if (empty($battery_map_insert_ret['bom_source_id'])) {
$battery_map_insert_ret['bom_source_id'] = 0;
}
if (empty($battery_map_insert_ret['bom_id'])) {
$battery_map_insert_ret['bom_id'] = 0;
}
$arr = [];
foreach ($battery_map_insert_ret as $val1) {
array_push($arr, "'{$val1}'");
}
array_push($battery_map_sql_val_str, "(" . implode(',', $arr) . ")");
// 处理process_log的数据
$sql = sprintf(
"SELECT %s FROM hf_mes_bkv_batch_process_log WHERE batch='%s' AND subbatch='%s' AND tray='%s' AND lot='%s' AND item_id='%s' ORDER BY id DESC LIMIT 1;",
$process_log_sql_key_str,
$old_battery_arr_column[$item1]['old_batch'],
$old_battery_arr_column[$item1]['old_subbatch'],
$old_battery_arr_column[$item1]['old_tray'],
$old_battery_arr_column[$item1]['old_lot'],
$old_battery_arr_column[$item1]['battery_id']
);
$process_log_insert_ret = Db::query($sql);
if (empty($process_log_insert_ret)) {
throw new Exception("SELECT key failed:[hf_mes_bkv_batch_process_log]", 4001);
}
$process_log_insert_ret['tray'] = $tray;
$process_log_insert_ret['lot'] = $lot;
if (empty($process_log_insert_ret['start_time'])) {
$process_log_insert_ret['start_time'] = $process_log_insert_ret['finish_time'];
}
if (empty($process_log_insert_ret['bom_source_id'])) {
$process_log_insert_ret['bom_source_id'] = 0;
}
if (empty($process_log_insert_ret['bom_id'])) {
$process_log_insert_ret['bom_id'] = 0;
}
if (empty($process_log_insert_ret['item_quantity'])) {
$process_log_insert_ret['item_quantity'] = 0;
}
if (empty($process_log_insert_ret['input_finish_time'])) {
$process_log_insert_ret['input_finish_time'] = date('Y-m-d H:i:s');
}
if (isset($process_log_insert_ret['last_status'])) {
$process_log_insert_ret['last_status'] = 1;
}
$arr = [];
foreach ($process_log_insert_ret as $val1) {
array_push($arr, "'{$val1}'");
}
array_push($process_log_sql_val_str, "(" . implode(',', $arr) . ")");
}
// 新增battery_map的数据
$battery_map_sql_val_str = implode(",", $battery_map_sql_val_str);
$sql = "INSERT INTO hf_mes_production_battery_map ($battery_map_sql_key_str) VALUES $battery_map_sql_val_str";
$ret = Db::query($sql);
if ($ret === NULL) {
throw new Exception("插入[hf_mes_production_battery_map]表失败", 4001);
}
// 新增process_log的数据
$process_log_sql_val_str = implode(",", $process_log_sql_val_str);
$sql = "INSERT INTO hf_mes_bkv_batch_process_log ($process_log_sql_key_str) VALUES $process_log_sql_val_str";
$ret = Db::query($sql);
if ($ret === NULL) {
throw new Exception("插入[hf_mes_bkv_batch_process_log]表失败", 4001);
}
// 10 bkv表上复制battery的信息(顺序)并将tray改为本托盘
$sql = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE table_name = 'hf_mes_tmp_bkv_$subbatch' ORDER BY ORDINAL_POSITION ASC";
$ret = Db::query($sql);
$key_arr = [];
foreach (array_column($ret, 'column_name') as $val) {
if ($val != "id") {
$key_arr[] = '"' . $val . '"';
}
}
$key_str = implode(",", $key_arr);
foreach ($battery_ids as $bid) {
if ($bid !== 0 && $bid !== "0" && $bid !== "") {
$sql = "SELECT $key_str FROM \"hf_mes_tmp_bkv_$subbatch\" WHERE battery_id='$bid' AND active=1 LIMIT 1";
$ret = Db::query($sql);
if (count($ret) <= 0) {
throw new Exception("SELECT key failed:[hf_mes_tmp_bkv_$subbatch]", 4001);
}
$ret['lot'] = $lot;
$ret['tray'] = $tray;
$ret['process_code'] = $process_code;
$ret['process_idx'] = $process_idx;
$ret['next_process_code'] = $next_process_code;
$ret['active'] = 1;
$k_str = "";
$v_str = "";
foreach ($ret as $k => $v) {
$k_str .= "\"$k\",";
if ($v == '') {
$v_str .= "Null,";
} else {
$v_str .= "'$v',";
}
}
$k_str = rtrim($k_str, ",");
$v_str = rtrim($v_str, ",");
$sql = "INSERT INTO \"hf_mes_tmp_bkv_$subbatch\" ($k_str) VALUES ($v_str)";
$ret = Db::query($sql);
if ($ret === NULL) {
throw new Exception("Record INSERT failed:[hf_mes_tmp_bkv_$subbatch]", 4001);
}
} else {
if ($bid == "") {
$bid = "0";
}
$sql = "INSERT INTO \"hf_mes_tmp_bkv_$subbatch\" (battery_id, lot, tray,active ,process_code) VALUES ('$bid', '$lot' ,'$tray', 0,'$process_code')";
$ret = Db::query($sql);
if ($ret === NULL) {
throw new Exception("Record INSERT failed:[hf_mes_tmp_bkv_$subbatch]", 4001);
}
}
}
//11 删除bkv表上原battery的信息
foreach ($old_battery_arr as $battery_arr) {
// $sql = sprintf(
// "DELETE FROM hf_mes_production_battery_map
// WHERE batch='%s' AND subbatch='%s' AND tray='%s' AND lot='%s' AND battery_id='%s';",
// $battery_arr['old_batch'],
// $battery_arr['old_subbatch'],
// $battery_arr['old_tray'],
// $battery_arr['old_lot'],
// $battery_arr['battery_id']
// );
// $ret = Db::query($sql);
// if ($ret === NULL) {
// throw new Exception("Record DELETE failed:[hf_mes_production_battery_map", 4001);
// }
// $sql = sprintf(
// "DELETE FROM hf_mes_bkv_batch_process_log
// WHERE batch='%s' AND subbatch='%s' AND tray='%s' AND lot='%s' AND item_id='%s';",
// $battery_arr['old_batch'],
// $battery_arr['old_subbatch'],
// $battery_arr['old_tray'],
// $battery_arr['old_lot'],
// $battery_arr['battery_id']
// );
// $ret = Db::query($sql);
// if ($ret === NULL) {
// throw new Exception("Record DELETE failed:[hf_mes_bkv_batch_process_log", 4001);
// }
// $sql = sprintf(
// "DELETE FROM \"%s\"
// WHERE tray='%s' AND lot='%s' AND battery_id='%s';",
// "hf_mes_tmp_bkv_{$battery_arr['old_subbatch']}",
// $battery_arr['old_tray'],
// $battery_arr['old_lot'],
// $battery_arr['battery_id']
// );
// $ret = Db::query($sql);
// if ($ret === NULL) {
// throw new Exception("Record DELETE failed:[hf_mes_tmp_bkv_$batch]", 4001);
// }
$sql = sprintf(
"UPDATE \"%s\" SET active=0
WHERE tray='%s' AND lot='%s' AND battery_id='%s';",
"hf_mes_tmp_bkv_{$battery_arr['old_subbatch']}",
$battery_arr['old_tray'],
$battery_arr['old_lot'],
$battery_arr['battery_id']
);
$ret = Db::query($sql);
if ($ret === NULL) {
throw new Exception("Record DELETE failed:[hf_mes_tmp_bkv_$batch]", 4001);
}
}
if ($next_process_code == -1) {
// 最后一个工序将电池状态变为非激活active = 0
$sql = sprintf(
"UPDATE \"%s\" SET active=0
WHERE tray='%s' AND lot='%s';",
"hf_mes_tmp_bkv_{$subbatch}",
$tray,
$lot
);
$rt_battery_update = Db::query($sql);
if ($rt_battery_update === NULL) {
throw new Exception("PROCESS update failed:[tmp_battery_update]", 4001);
}
// 最后一个工序将托盘状态变为非激活active = 0
$sql = sprintf(
"UPDATE hf_mes_production_tray_map SET active=0
WHERE batch='%s' AND subbatch='%s' AND tray='%s' AND lot='%s';",
$batch,
$subbatch,
$tray,
$lot
);
$rt = Db::query($sql);
if ($rt === NULL) {
throw new Exception("Record Update failed:[tray_map]", 4001);
}
}
} catch (Exception $e) {
Db::rollBackTrans();
throw new Exception($e->getMessage());
}
Db::commitTrans();
return '';
}
}