'Porosity Gas', 'Oxides', 'Dross', 'Foreign Material', 'Shrinkage', 'Crack', 'Misrun', 'Coldshut', 'Overcleaned', 'Handling Damage', 'Broken Core', 'Sand Hole ', 'Sand Drop', 'Molding', 'Out of Dimension', 'Other', 'Machining', 'Saw Cut', 'Crack Wax', 'Wax Positive Defect', 'Bent', 'Blow', 'Crush', 'Short Pour', 'Run Out', 'Broken Wax', 'Set Up Bad', 'Dropped Tree', 'Broken Cup', 'Shell Spall', 'Shell Inclusion', 'Core Float', 'Targeting', 'Negative Parting Line', 'Shift', 'Core Drop', 'Buckle', 'Glue', 'Mechanical Failure', 'Slag', 'Mold Reaction', 'Core Reaction', 'No Test Bars', 'No Paperwork', 'Bad Weld', ); protected static $_sizeMap = array('s' => 'S', 'lg' => 'M', '2x' => 'L', '3x' => 'XL', '4x' => 'XXL'); protected $_stampObj; public function getScrapCodes() { return $this->_scrapCodes; } public static function getSizeMap() { return self::$_sizeMap; } public function getProcessById($processId) { return $this->tableProcess->search($processId); } public function getPartById($partId) { $select = $this->_db->select(); $select->join($this->pairPartVersion, 'PartVersion.id=Part.currentVersion'); $select->from($this->_getPair('Part')) ->where('Part.id = ?', $partId, Qs_Db::INT_TYPE); return $this->_db->fetchRow($select); } public function setProcessId($processId) { $this->_processId = $processId; return $this; } public function getProcessId() { return $this->_processId; } public function setPartId($partId) { $this->_partId = $partId; $this->_partObject = new App_Part_Obj(array('primaryKey' => $this->_partId)); return $this; } public function getPartId() { return $this->_partId; } public function getAnnotationRevision() { return $this->_annotationRev; } public function getUserCurrentRevision() { $revision = $this->_partObject->getData('revision'); return (isset($revision['id'])) ? $revision['id'] : null; } protected function _filterWhere(Zend_Db_Select $select) { $select = parent::_filterWhere($select); $revision = $this->_partObject->getData('revision'); $select->where('revisionStart <= ? AND (revisionEnd > ? OR revisionEnd IS NULL)', $revision['id']); return $select; } protected function _where4Sorter(Zend_Db_Select $select = null) { $select = parent::_where4Sorter($select); $select->where('processId = ?', $this->_processId, Qs_Db::INT_TYPE); $select->where('partId = ?', $this->_partId, Qs_Db::INT_TYPE); return $select; } public function delete() { $this->_preDeleteData = $this->_data; $data = array(); if (false !== ($data['revisionEnd'] = $this->_revisionPreCheck())) { $currentRevisionStart = $this->_getFromDb($this->_primaryKey, 'revisionStart'); if ($currentRevisionStart < $data['revisionEnd']) { $result = parent::update($data); } else { $result = parent::delete(); } $this->_revisionPostCheck(); } else { $result = true; } return $result; } protected function _deleteFiles($row = null) { if (is_array($this->_fileFields) && !empty($this->_fileFields)) { $adapter = new Qs_File_Transfer_Adapter_Db(); if (null === $row) { if (false !== ($row = $this->table->findRow($this->getPrimaryKey()))) { $row = $row->toArray(); } } if (is_array($row) && !empty($row)) { foreach ($this->_fileFields as $name) { if (isset($row[$name]) && !empty($row[$name])) { $adapter->delete($row[$name], $name); if ($name == App_Process_Media_AbstractObj::TYPE_IMAGE) { $svg_filename = pathinfo($row[$name], PATHINFO_FILENAME) . '.svg'; $destinationPath = WWW_PATH . '/' . Qs_ImageFs::WEB_PATH . '/'; if (file_exists($destinationPath . $svg_filename)) { Qs_ImageFs::delete(WWW_PATH . '/' . Qs_ImageFs::WEB_PATH . '/' . $svg_filename); } } } } } unset($adapter); } } public function update($data = null) { if (null === $data) { $data = $this->_data; $manualData = null; } else { $manualData = $data; } Qs_Db_Obj::setDisableHandleFiles(true); $dbData = $this->_getFromDb($this->_primaryKey); if (false !== ($data['revisionStart'] = $this->_revisionPreCheck($manualData))) { $currentRevisionStart = Qs_Array::get($dbData, 'revisionStart'); $data['sorter'] = Qs_Array::get($dbData, 'sorter'); if ($currentRevisionStart < $data['revisionStart']) { /** does not allow handleFiles method to delete existing files (save them for old revisions */ $session = new Qs_Session_Namespace(CURRENT_PAGE); unset($session->files); $this->table->updateByKey(array('revisionEnd' => $data['revisionStart']), $this->_primaryKey); $result = parent::insert($data); } else { Qs_Db_Obj::setDisableHandleFiles(null); $result = parent::update($data); } if (null !== $manualData) { $this->_annotationRev = $data['revisionStart']; } $this->_revisionPostCheck(); } else { $result = true; } Qs_Db_Obj::setDisableHandleFiles(null); return $result; } public function insert($data = null) { if (null === $data) { $data = $this->_data; } if (false !== ($data['revisionStart'] = $this->_revisionPreCheck())) { $result = parent::insert($data); $this->_revisionPostCheck(); } else { $result = true; } return $result; } protected function _revisionPreCheck($data = null) { if (isset($data['comments']) && isset($data['versionType'])) { $this->_data['comments'] = $data['comments']; $this->_data['versionType'] = $data['versionType']; } $blockedVersion = $this->_partObject->getData('blockedVersion'); if ($this->_data['versionType'] == App_Part_Obj::REVISION_CANCELED) { $this->_partObject->cancelRevision(); return false; } elseif (!$blockedVersion) { $blockedVersion = $this->_partObject->createRevision(null, $this->_data['comments']); } else { $this->_partObject->update(array('comments' => $this->_data['comments'], 'doNotUpdateProcess' => true)); } return $blockedVersion; } protected function _revisionPostCheck() { if ($this->_preDeleteData) { $this->_data = $this->_preDeleteData; } if ($this->_data['versionType'] == App_Part_Obj::REVISION_APPROVED) { $this->_partObject->approveRevision(); } } protected function _addDependenciesFromDb(&$data) { if (null !== $this->_partObject) { $data['comments'] = $this->_partObject->getData('comments'); } $data['versionType'] = App_Part_Obj::REVISION_LOCKED; return $this; } public function getComments() { return $this->_partObject->getData('comments'); } public function getReorderOptions($keyColumn, $titleColumn) { $select = $this->getListSelect(); $select = $this->_where4Sorter($select); $select->order($this->_tableAlias . '.sorter'); $list = $this->_db->fetchAll($select); $options = array(); $i = 1; foreach ($list as $row) { $options[$row[$keyColumn]] = ucfirst($row['type']) . ' ' . $i++; } return $options; } public function getDepartmentAliasById($id) { $department = $this->tableDepartment->search($id); $departmentId = $department['parentId'] ? $department['parentId'] : $department['id']; return App_Acl_Obj::DEPARTMENT_PREFIX . $departmentId; } public function getStampId() { if (null === $this->_stampId) { $this->setStampId(); } return $this->_stampId; } public function getMarks() { $session = new Qs_Session_Namespace('stamp-' . $this->getStampId()); return (array)$session->marks; } public function setStampId($id = null) { if (null === $id) { $id = md5(uniqid(mt_rand(), true)); } $this->_stampId = $id; $session = $this->getStampSession($id); $session->marks = (array)$session->marks; } public function getStampSession($stampId = null) { $stampId = null === $stampId ? $this->getStampId() : $stampId; return new Qs_Session_Namespace('stamp-' . $stampId); } public function addMark($mark) { $session = $this->getStampSession($this->getStampId()); $mark['id'] = md5(uniqid(mt_rand(), true)); reset($this->_scrapCodes); $defaultMark = array( 'size' => 's', 'color' => 'FF0000', 'type' => 'circle', 'scrapCode' => key($this->_scrapCodes), 'length' => '', 'width' => '', 'depth' => '', 'disposition' => 'rework', 'badWeld' => 'n', 'comments' => '', ); $mark = array_merge($defaultMark, $mark); $session->marks[$mark['id']] = $mark; return $mark; } public function updateMark($id, $mark) { $session = $this->getStampSession($this->getStampId()); $session->marks[$id] = array_merge($session->marks[$id], $mark); return $mark; } public function getMark($markId) { $marks = $this->getMarks(); return $marks[$markId]; } public function deleteMark($markId) { $session = $this->getStampSession($this->getStampId()); unset($session->marks[$markId]); return true; } /** * Read marks for edit stamp form * @return array */ public function readMarks() { $select = $this->_db->select(); $select->from($this->_getPair('Stamp'), array()); $select->join($this->_getPair('StampMark'), 'StampMark.stampId = Stamp.Id', array('*')); $select->where('Stamp.stampId = ?', $this->getStampId()); $select->order('StampMark.id'); $marks = $this->_db->fetchAssoc($select); $sizeMap = self::getSizeMap(); foreach ($marks as $id => &$mark) { $mark['_markId'] = $mark['id']; $mark['size'] = (false === ($size = array_search($mark['size'], $sizeMap))) ? 's' : $size; $mark['position'] = array( 'left' => (int) $mark['positionLeft'], 'top' => (int) $mark['positionTop'], ); $mark['length'] = (float) $mark['length']; $mark['width'] = (float) $mark['width']; $mark['depth'] = (float) $mark['depth']; $mark['scrapCode'] = array_search($mark['scrapCode'], $this->_scrapCodes); } $session = $this->getStampSession($this->getStampId()); $session->marks = $marks ? $marks : array(); return $this; } public function saveStamp() { $sizes = self::getSizeMap(); $stampId = $this->getStampObj()->getPrimaryKey(); try { $this->_db->beginTransaction(); $stampData = array( 'mediaId' => $this->_data['mediaId'], 'stampId' => $this->_data['stampId'], 'meltLotNumber' => substr($this->_data['meltLotNumber'], 0, 20), 'serialNumber' => substr($this->_data['serialNumber'], 0, 20), 'htCondition' => $this->_data['htCondition'], 'welderId' => substr($this->_data['welderId'], 0, 20), 'personWelding' => (int) $this->_data['personWelding'], 'weldRodLotNo' => substr($this->_data['weldRodLotNo'], 0, 50), 'timeCardLine' => $this->_data['timeCardLine'], 'quantity' => (float) $this->_data['quantity'], ); if ($stampId) { $oldData = $this->getStampObj()->getData(); $this->tableStamp->update($stampData, array('id = ?' => $stampId)); } else { $oldData = []; $stampId = $this->tableStamp->insert($stampData); } // we need start new numbering $partId = $this->getStampObj()->readPartId($stampId); $numberingChanged = (empty($oldData) || $oldData['partId'] != $partId || $oldData['serialNumber'] !== $stampData['serialNumber'] || $oldData['meltLotNumber'] !== $stampData['meltLotNumber']); $originalLatMarkNum = $lastMarkNum = (int) $this->getStampObj()->getLastMarkNum($partId, $stampData['serialNumber'], $stampData['meltLotNumber']); $lastUsedMarkNum = (int) $this->getStampObj()->readLastUsedMarkNo($partId, $stampData['serialNumber'], $stampData['meltLotNumber'], array('s.id != ?' => $stampId)); if ($numberingChanged && $originalLatMarkNum !== $lastUsedMarkNum && $lastUsedMarkNum < $originalLatMarkNum) { $lastMarkNum = $lastUsedMarkNum; } $stampIds = array(); foreach ($this->getMarks() as $mark) { $markData = array( 'stampId' => $stampId, 'type' => $mark['type'], 'size' => $sizes[$mark['size']], 'color' => $mark['color'], 'positionTop' => (int)$mark['position']['top'], 'positionLeft' => (int)$mark['position']['left'], 'scrapCode' => $this->_scrapCodes[$mark['scrapCode']], 'length' => $mark['length'], 'width' => $mark['width'], 'depth' => $mark['depth'], 'disposition' => substr($mark['disposition'], 0, 10), 'badWeld' => $mark['badWeld'] == 'y' ? 'y' : 'n', 'comments' => $mark['comments'], ); if (empty($mark['_markId'])) { $markData['num'] = ++$lastMarkNum; $stampIds[] = $this->tableStampMark->insert($markData); } else { $stampIds[] = $mark['_markId']; if ($numberingChanged) { $markData['num'] = ++$lastMarkNum; } $this->tableStampMark->update($markData, array('id = ?' => $mark['_markId'])); } } if ($originalLatMarkNum != $lastMarkNum) { $this->getStampObj()->updateLastMarkNum($lastMarkNum, $partId, $stampData['serialNumber'], $stampData['meltLotNumber']); } $deleteMarkCond = array('stampId = ?' => $stampId); if ($stampIds) { $deleteMarkCond['id NOT IN(?)'] = $stampIds; } $this->tableStampMark->delete($deleteMarkCond); $this->_db->commit(); } catch (Exception $e) { $this->_db->rollBack(); Qs_Debug::log($e->getMessage(), 3); return $e; } return $stampId; } protected function _prepareList(array &$list) { $revision = $this->_partObject->getData('revision'); $this->assignAnnotation($list, $revision['id']); return parent::_prepareList($list); } public function assignAnnotation(&$list, $maxRevisionId = null) { foreach ($list as &$mediaItem) { if ($mediaItem['type'] == App_Process_Media_AbstractObj::TYPE_IMAGE && $mediaItem['image']) { $revision = $this->getLastAnnotationRevision($mediaItem['image'], $maxRevisionId); $revisionSuffix = (!empty($revision)) ? '_rev_' . $revision : ''; $svg_filename = pathinfo($mediaItem['image'], PATHINFO_FILENAME) . $revisionSuffix . '.svg'; if (file_exists(WWW_PATH . '/' . Qs_ImageFs::WEB_PATH . '/' . $svg_filename)) { $mediaItem['annotation'] = $svg_filename; } } } return $this; } public static function assignStamps(&$list) { $mediaIds = Qs_Array::fetchCol($list, 'id'); if ($mediaIds) { $db = Qs_Db::getInstance(); $select = $db->select(); $select->from(Qs_Db::getPair('Stamp'), array('mediaId', 'id', 'stampId', 'added')); $select->where('Stamp.mediaId IN(?)', $mediaIds, Qs_Db::INT_TYPE); $select->order('Stamp.id DESC'); // [$mediaId => [['id' =>, 'added' =>], ...], ...] $stampList = $db->fetchAll($select, null, Zend_Db::FETCH_GROUP | Zend_Db::FETCH_ASSOC); } $stampList = empty($stampList) ? array() : $stampList; foreach ($list as &$row) { $row['stamps'] = (empty($stampList[$row['id']])) ? null : $stampList[$row['id']]; } return; } public static function getLastAnnotationRevision($image, $maxRevisionId = null) { $imageBaseName = pathinfo($image, PATHINFO_FILENAME); $filePath = WWW_PATH . '/' . Qs_ImageFs::WEB_PATH . '/'; $list = glob($filePath . $imageBaseName . '_rev_*.svg', GLOB_NOSORT); $revisions = array(); foreach($list as $item) { $itemRevision = str_replace( array($filePath . $imageBaseName, '_rev_', '.svg'), array('', '', ''), $item ); if (null === $maxRevisionId) { $revisions[] = $itemRevision; } elseif (empty($itemRevision) || $maxRevisionId >= $itemRevision) { $revisions[] = $itemRevision; } } rsort($revisions, SORT_NUMERIC); return reset($revisions); } public function getStampObj() { if (null == $this->_stampObj) { $this->_stampObj = new App_Process_Media_StampObj(); } return $this->_stampObj; } }