/**
  * Set the reception code for a respondent and cascade non-success codes to the
  * tracks / surveys.
  *
  * @param string $patientId   Can be empty if $respondentId is passed
  * @param int $organizationId
  * @param string $newCode     String or \Gems_Util_ReceptionCode
  * @param int $respondentId   Pass when at hand, is looked up otherwise
  * @param string $oldCode     Pass when at hand as tring or \Gems_Util_ReceptionCode, is looked up otherwise
  * @return \Gems_Util_ReceptionCode The new code reception code object for further processing
  */
 public function setReceptionCode($patientId, $organizationId, $newCode, $respondentId = null, $oldCode = null)
 {
     if ($newCode instanceof \Gems_Util_ReceptionCode) {
         $code = $newCode;
         $newCode = $code->getCode();
     } else {
         $code = $this->util->getReceptionCode($newCode);
     }
     $userId = $this->currentUser->getUserId();
     // Perform actual save, but not for simple stop codes.
     if ($code->isForRespondents()) {
         if (null === $oldCode) {
             $oldCode = $this->getReceptionCode($patientId, $organizationId, $respondentId);
         }
         if ($oldCode instanceof \Gems_Util_ReceptionCode) {
             $oldCode = $oldCode->getCode();
         }
         // If the code wasn't set already
         if ($oldCode !== $newCode) {
             $values['gr2o_reception_code'] = $newCode;
             $values['gr2o_changed'] = new \MUtil_Db_Expr_CurrentTimestamp();
             $values['gr2o_changed_by'] = $userId;
             if ($patientId) {
                 // Update though primamry key is prefered
                 $where = 'gr2o_patient_nr = ? AND gr2o_id_organization = ?';
                 $where = $this->db->quoteInto($where, $patientId, null, 1);
             } else {
                 $where = 'gr2o_id_user = ? AND gr2o_id_organization = ?';
                 $where = $this->db->quoteInto($where, $respondentId, null, 1);
             }
             $where = $this->db->quoteInto($where, $organizationId, null, 1);
             $this->db->update('gems__respondent2org', $values, $where);
         }
     }
     // Is the respondent really removed
     if (!$code->isSuccess()) {
         // Only check for $respondentId when it is really needed
         if (null === $respondentId) {
             $respondentId = $this->util->getDbLookup()->getRespondentId($patientId, $organizationId);
         }
         // Cascade to tracks
         // the responsiblilty to handle it correctly is on the sub objects now.
         $tracks = $this->loader->getTracker()->getRespondentTracks($respondentId, $organizationId);
         foreach ($tracks as $track) {
             if ($track->setReceptionCode($code, null, $userId)) {
                 $this->addChanged();
             }
         }
     }
     if ($code->isForRespondents()) {
         $this->handleRespondentChanged($patientId, $organizationId, $respondentId);
     }
     return $code;
 }
 /**
  * Return the \Gems_Util_ReceptionCode object
  *
  * @return \Gems_Util_ReceptionCode reception code
  */
 public function getReceptionCode()
 {
     return $this->util->getReceptionCode($this->_gemsData['gr2o_reception_code']);
 }
 /**
  * Set the reception code for this respondent track and make sure the
  * necessary cascade to the tokens and thus the source takes place.
  *
  * @param string $code The new (non-success) reception code or a \Gems_Util_ReceptionCode object
  * @param string $comment Comment for tokens. False values leave value unchanged
  * @param int $userId The current user
  * @return int 1 if the token has changed, 0 otherwise
  */
 public function setReceptionCode($code, $comment, $userId)
 {
     // Make sure it is a \Gems_Util_ReceptionCode object
     if (!$code instanceof \Gems_Util_ReceptionCode) {
         $code = $this->util->getReceptionCode($code);
     }
     $changed = 0;
     // Apply this code both only when it is a track code.
     // Patient level codes are just cascaded to the tokens.
     //
     // The exception is of course when the exiting values must
     // be overwritten, e.g. when cooperation is retracted.
     if ($code->isForTracks() || $code->isOverwriter()) {
         $values['gr2t_reception_code'] = $code->getCode();
     }
     $values['gr2t_comment'] = $comment;
     $changed = $this->_updateTrack($values, $userId);
     // Stopcodes have a different logic.
     if ($code->isStopCode()) {
         // Cascade stop to tokens
         foreach ($this->getTokens() as $token) {
             if ($token->hasSuccesCode() && !$token->isCompleted()) {
                 $changed += $token->setReceptionCode($code, $comment, $userId);
             }
         }
         $changed = max($changed, 1);
         // Update token count / completion
         $this->_checkTrackCount($userId);
     } elseif (!$code->isSuccess()) {
         // Cascade code to tokens
         foreach ($this->getTokens() as $token) {
             if ($token->hasSuccesCode()) {
                 $token->setReceptionCode($code, $comment, $userId);
             }
         }
     }
     return $changed;
 }
 /**
  * Set the reception code for this token and make sure the necessary
  * cascade to the source takes place.
  *
  * @param string $code The new (non-success) reception code or a \Gems_Util_ReceptionCode object
  * @param string $comment Comment False values leave value unchanged
  * @param int $userId The current user
  * @return int 1 if the token has changed, 0 otherwise
  */
 public function setReceptionCode($code, $comment, $userId)
 {
     // Make sure it is a \Gems_Util_ReceptionCode object
     if (!$code instanceof \Gems_Util_ReceptionCode) {
         $code = $this->util->getReceptionCode($code);
     }
     $values['gto_reception_code'] = $code->getCode();
     if ($comment) {
         $values['gto_comment'] = $comment;
     }
     // \MUtil_Echo::track($values);
     $changed = $this->_updateToken($values, $userId);
     if ($changed) {
         if ($code->isOverwriter() || !$code->isSuccess()) {
             $survey = $this->getSurvey();
             // Update the consent code in the source
             if ($survey->inSource($this)) {
                 $survey->updateConsent($this);
             }
         }
     }
     return $changed;
 }
 /**
  * Should handle execution of the task, taking as much (optional) parameters as needed
  *
  * The parameters should be optional and failing to provide them should be handled by
  * the task
  *
  * @param array $row Row to save
  */
 public function execute($row = null, $noToken = \Gems_Model_Translator_AnswerTranslatorAbstract::TOKEN_ERROR, $tokenCompletion = \Gems_Model_Translator_AnswerTranslatorAbstract::TOKEN_ERROR)
 {
     // \MUtil_Echo::track($row);
     if ($row) {
         $answers = $row;
         $double = false;
         $token = null;
         $tracker = $this->loader->getTracker();
         $userId = $this->loader->getCurrentUser()->getUserId();
         // \Gems_Tracker::$verbose = true;
         $batch = $this->getBatch();
         $batch->addToCounter('imported');
         // Remove all "non-answer" fields
         unset($answers['token'], $answers['patient_id'], $answers['organization_id'], $answers['track_id'], $answers['survey_id'], $answers['completion_date'], $answers['gto_id_token']);
         if (isset($row['survey_id'])) {
             $model = $tracker->getSurvey($row['survey_id'])->getAnswerModel('en');
             foreach ($answers as $key => &$value) {
                 if ($value instanceof \Zend_Date) {
                     $value = $value->toString($model->getWithDefault($key, 'storageFormat', 'yyyy-MM-dd HH:mm:ss'));
                 }
             }
         }
         if (isset($row['token']) && $row['token']) {
             $token = $tracker->getToken($row['token']);
             if ($token->exists && $token->isCompleted() && $token->getReceptionCode()->isSuccess()) {
                 $currentAnswers = $token->getRawAnswers();
                 $usedAnswers = array_intersect_key($answers, $currentAnswers);
                 // \MUtil_Echo::track($currentAnswers, $answers, $usedAnswers);
                 if ($usedAnswers) {
                     foreach ($usedAnswers as $name => $value) {
                         if (null === $answers[$name] || $answers[$name] == $this->targetModel->get($name, 'default')) {
                             // There is no value to set, so do not set the value
                             unset($answers[$name]);
                         } elseif (!(null === $value || $value == $this->targetModel->get($name, 'default'))) {
                             // The value was already set
                             $double = true;
                             // But no break because of previous unsets
                             // break;
                         }
                     }
                 }
             }
         }
         if (!($token && $token->exists)) {
             if (!(isset($row['track_id']) && $row['track_id'])) {
             }
             // create token?
         }
         if ($answers) {
             if ($double) {
                 if (\Gems_Model_Translator_AnswerTranslatorAbstract::TOKEN_OVERWRITE == $tokenCompletion) {
                     $code = $this->util->getReceptionCode('redo');
                     $oldComment = "";
                     if ($token->getComment()) {
                         $oldComment .= "\n\n";
                         $oldComment .= $this->_('Previous comments:');
                         $oldComment .= "\n";
                         $oldComment .= $token->getComment();
                     }
                     $newComment = sprintf($this->_('Token %s overwritten by import.'), $token->getTokenId());
                     $replacementTokenId = $token->createReplacement($newComment . $oldComment, $userId);
                     $count = $batch->addToCounter('overwritten', 1);
                     $batch->setMessage('overwritten', sprintf($this->plural('%d token overwrote an existing token.', '%d tokens overwrote existing tokens.', $count), $count));
                     $oldToken = $token;
                     $token = $tracker->getToken($replacementTokenId);
                     // Add the old answers to the new answer set as the new answers OVERWRITE the old data
                     $answers = $answers + $currentAnswers;
                     // Make sure the Next token is set right
                     $oldToken->setNextToken($token);
                     $oldToken->setReceptionCode($code, sprintf($this->_('Token %s overwritten by import.'), $token->getTokenId()) . $oldComment, $userId);
                 } else {
                     $oldComment = "";
                     if ($token->getComment()) {
                         $oldComment .= "\n\n";
                         $oldComment .= $this->_('Previous comments:');
                         $oldComment .= "\n";
                         $oldComment .= $token->getComment();
                     }
                     $newComment = sprintf($this->_('More answers for token %s by import.'), $token->getTokenId());
                     $replacementTokenId = $token->createReplacement($newComment . $oldComment, $userId);
                     $count = $batch->addToCounter('addedAnswers', 1);
                     $batch->setMessage('addedAnswers', sprintf($this->plural('%d token was imported as a new extra token.', '%d tokens were imported as a new extra token.', $count), $count));
                     $oldToken = $token;
                     $token = $tracker->getToken($replacementTokenId);
                     // Make sure the Next token is set right
                     $oldToken->setNextToken($token);
                     $oldToken->setReceptionCode($oldToken->getReceptionCode(), sprintf($this->_('Additional answers in imported token %s.'), $token->getTokenId()) . $oldComment, $userId);
                 }
             }
             // There are still answers left to save
             // Make sure the token is known
             $token->getUrl($this->locale->getLanguage(), $userId);
             $token->setRawAnswers($answers);
             if (isset($row['completion_date']) && $row['completion_date']) {
                 $token->setCompletionTime($row['completion_date'], $userId);
             } elseif (!$token->isCompleted()) {
                 $token->setCompletionTime(new \MUtil_Date(), $userId);
             }
             $token->getRespondentTrack()->checkTrackTokens($userId, $token);
             $count = $batch->addToCounter('changed', 1);
             $batch->setMessage('changed', sprintf($this->plural('%d token imported.', '%d tokens imported.', $count), $count));
         }
     }
 }