/**
  * @param \PhpSigep\Model\CalcPrecoPrazo $params
  * @return \PhpSigep\Model\CalcPrecoPrazoRespostaIterator
  */
 public function calcPrecoPrazo(\PhpSigep\Model\CalcPrecoPrazo $params)
 {
     $retorno = array();
     $servicos = $params->getServicosPostagem();
     foreach ($servicos as $servico) {
         $valorFrete = mt_rand(30, 1000) / 10;
         // Valores entre 3 e 100
         $valorMaoPropria = 0;
         $valorAvisoRecebimento = 0;
         $valorValorDeclarado = 0;
         $servicoAdicionais = $params->getServicosAdicionais();
         foreach ($servicoAdicionais as $servicoAdicional) {
             if ($servicoAdicional->is(ServicoAdicional::SERVICE_AVISO_DE_RECEBIMENTO)) {
                 $valorAvisoRecebimento = mt_rand(1, 50) / 10;
                 // Valores entre 0.1 e 5
             } else {
                 if ($servicoAdicional->is(ServicoAdicional::SERVICE_MAO_PROPRIA)) {
                     $valorMaoPropria = mt_rand(1, 50) / 10;
                     // Valores entre 0.1 e 5
                 } else {
                     if ($servicoAdicional->is(ServicoAdicional::SERVICE_VALOR_DECLARADO)) {
                         $valorValorDeclarado = $servicoAdicional->getValorDeclarado() * 1 / 100;
                         //1% do valor declarado
                     }
                 }
             }
         }
         $valorMaoPropria = round($valorMaoPropria, 2);
         $valorAvisoRecebimento = round($valorAvisoRecebimento, 2);
         $valorValorDeclarado = round($valorValorDeclarado, 2);
         $valorFrete = round($valorFrete, 2);
         $total = $valorFrete + $valorValorDeclarado + $valorMaoPropria + $valorAvisoRecebimento;
         $item = new \PhpSigep\Model\CalcPrecoPrazoResposta(array('servico' => $servico, 'valor' => $total, 'prazoEntrega' => mt_rand(1, 9), 'valorMaoPropria' => $valorMaoPropria, 'valorAvisoRecebimento' => $valorAvisoRecebimento, 'valorValorDeclarado' => $valorValorDeclarado, 'entregaDomiciliar' => true, 'entregaSabado' => true));
         $retorno[] = $item;
     }
     return new \PhpSigep\Model\CalcPrecoPrazoRespostaIterator($retorno);
 }
 /**
  * @param \PhpSigep\Model\CalcPrecoPrazo $params
  *
  * @throws Exception
  * @throws \Exception
  * @return Result<\PhpSigep\Model\CalcPrecoPrazoRespostaIterator[]>
  */
 public function execute(\PhpSigep\Model\CalcPrecoPrazo $params)
 {
     $larguraMinima = 0;
     $alturaMinima = 0;
     $comprimentoMinimo = 16;
     $diametroMinimo = 0;
     $tipoEmbalagem = $params->getDimensao()->getTipo();
     $ehEnvelope = false;
     if ($tipoEmbalagem == Dimensao::TIPO_ENVELOPE) {
         $ehEnvelope = true;
         $formatoEncomenda = 3;
         $larguraMinima = 11;
     } else {
         if ($tipoEmbalagem == Dimensao::TIPO_PACOTE_CAIXA) {
             $formatoEncomenda = 1;
             $alturaMinima = 2;
             $larguraMinima = 11;
         } else {
             if ($tipoEmbalagem == Dimensao::TIPO_ROLO_CILINDRO) {
                 $formatoEncomenda = 2;
                 $comprimentoMinimo = 18;
                 $diametroMinimo = 5;
             } else {
                 throw new Exception('Tipo de embalagem "' . $tipoEmbalagem . '" não reconhecido.');
             }
         }
     }
     $maoPropria = false;
     $valorDeclarado = 0;
     $avisoRecebimento = false;
     $servicosAdicionais = $params->getServicosAdicionais();
     $servicosAdicionais = $servicosAdicionais ? $servicosAdicionais : array();
     foreach ($servicosAdicionais as $servicoAdicional) {
         if ($servicoAdicional->is(ServicoAdicional::SERVICE_MAO_PROPRIA)) {
             $maoPropria = true;
         } else {
             if ($servicoAdicional->is(ServicoAdicional::SERVICE_VALOR_DECLARADO)) {
                 if (!$servicoAdicional->getValorDeclarado()) {
                     throw new Exception('Para usar o serviço "valor declarado" é necessário declarar o valor da mercadoria.');
                 }
                 $valorDeclarado = $servicoAdicional->getValorDeclarado();
             } else {
                 if ($servicoAdicional->is(ServicoAdicional::SERVICE_AVISO_DE_RECEBIMENTO)) {
                     $avisoRecebimento = true;
                 }
             }
         }
     }
     $servivosDePostagem = array();
     /** @var $servivoDePostagem ServicoDePostagem */
     foreach ($params->getServicosPostagem() as $servivoDePostagem) {
         $servivosDePostagem[] = $servivoDePostagem->getCodigo();
     }
     $ajustarDimensaoMinima = $params->getAjustarDimensaoMinima();
     $comprimento = (int) $params->getDimensao()->getComprimento();
     $comprimento = $comprimento < $comprimentoMinimo && $ajustarDimensaoMinima ? $comprimentoMinimo : $comprimento;
     $altura = $ehEnvelope ? 0 : (int) $params->getDimensao()->getAltura();
     $altura = $altura < $alturaMinima && $ajustarDimensaoMinima ? $alturaMinima : $altura;
     $largura = (int) $params->getDimensao()->getLargura();
     $largura = $largura < $larguraMinima && $ajustarDimensaoMinima ? $larguraMinima : $largura;
     $diametro = (int) $params->getDimensao()->getDiametro();
     $diametro = $diametro < $diametroMinimo && $ajustarDimensaoMinima ? $diametroMinimo : $largura;
     $soapArgs = array('nCdEmpresa' => $params->getAccessData()->getCodAdministrativo(), 'sDsSenha' => $params->getAccessData()->getSenha(), 'nCdServico' => implode(',', $servivosDePostagem), 'sCepOrigem' => str_replace('-', '', $params->getCepOrigem()), 'sCepDestino' => str_replace('-', '', $params->getCepDestino()), 'nVlPeso' => $params->getPeso(), 'nCdFormato' => $formatoEncomenda, 'nVlComprimento' => $comprimento, 'nVlAltura' => $altura, 'nVlLargura' => $largura, 'nVlDiametro' => $diametro, 'sCdMaoPropria' => $maoPropria ? 'S' : 'N', 'nVlValorDeclarado' => $valorDeclarado, 'sCdAvisoRecebimento' => $avisoRecebimento ? 'S' : 'N');
     $cacheKey = md5(serialize($soapArgs));
     $cache = Bootstrap::getConfig()->getCacheInstance();
     if ($cachedResult = $cache->getItem($cacheKey)) {
         return unserialize($cachedResult);
     }
     $result = new Result();
     try {
         $r = SoapClientFactory::getSoapCalcPrecoPrazo()->calcPrecoPrazo($soapArgs);
     } catch (\Exception $e) {
         $message = $e->getMessage();
         if ($message == 'Service Unavailable') {
             if (!self::$calcPrecosPrazosServiceUnavailable) {
                 //Tenta mais uma vez
                 self::$calcPrecosPrazosServiceUnavailable = true;
                 sleep(1);
                 return $this->calcPrecoPrazo($params);
             }
         }
         if ($e instanceof \SoapFault) {
             $result->setIsSoapFault(true);
             $result->setErrorCode($e->getCode());
             $result->setErrorMsg(SoapClientFactory::convertEncoding($e->getMessage()));
         } else {
             $result->setErrorCode($e->getCode());
             $result->setErrorMsg($e->getMessage());
         }
     }
     //        if (class_exists('\StaLib_Logger')) {
     //            \StaLib_Logger::log('Retorno SIGEP: ' . print_r($r, true));
     //        }
     $retorno = array();
     if (is_object($r) && $r->CalcPrecoPrazoResult && is_object($r->CalcPrecoPrazoResult) && $r->CalcPrecoPrazoResult->Servicos && is_object($r->CalcPrecoPrazoResult->Servicos)) {
         if ($r->CalcPrecoPrazoResult->Servicos->cServico) {
             $servicos = $r->CalcPrecoPrazoResult->Servicos->cServico;
             $servicos = is_array($servicos) ? $servicos : array($servicos);
             foreach ($servicos as $servico) {
                 $valor = (double) str_replace(',', '.', str_replace('.', '', $servico->Valor));
                 $valorMaoPropria = str_replace('.', '', $servico->ValorMaoPropria);
                 $valorMaoPropria = (double) str_replace(',', '.', $valorMaoPropria);
                 $valorAvisoRecebimento = str_replace('.', '', $servico->ValorAvisoRecebimento);
                 $valorAvisoRecebimento = (double) str_replace(',', '.', $valorAvisoRecebimento);
                 $valorValorDeclarado = str_replace('.', '', $servico->ValorValorDeclarado);
                 $valorValorDeclarado = (double) str_replace(',', '.', $valorValorDeclarado);
                 $item = new \PhpSigep\Model\CalcPrecoPrazoResposta(array('servico' => new \PhpSigep\Model\ServicoDePostagem($servico->Codigo), 'valor' => $valor, 'prazoEntrega' => (int) $servico->PrazoEntrega, 'valorMaoPropria' => $valorMaoPropria, 'valorAvisoRecebimento' => $valorAvisoRecebimento, 'valorValorDeclarado' => $valorValorDeclarado, 'entregaDomiciliar' => $servico->EntregaDomiciliar == 'S', 'entregaSabado' => $servico->EntregaSabado == 'S'));
                 $item->setErroCodigo($servico->Erro);
                 if ($item->getErroCodigo() && ($item->getErroCodigo() != 10 || !$item->getValor())) {
                     // Se entrar aqui significa que tem Erro e que esse Erro é diferente de 10 ou o Erro é 10 mas não
                     // não foi retornando o Valor.
                     // O erro "10" é mais um aviso do que um erro. Se for erro 10 e tiver valor, não considera um erro.
                     $msgErro = $servico->MsgErro;
                     $msgErro = SoapClientFactory::convertEncoding($msgErro);
                     $item->setErroMsg($msgErro);
                 } else {
                     $item->setErroCodigo(null);
                 }
                 $retorno[] = $item;
             }
         } else {
             $result->setErrorCode(0);
             $result->setErrorMsg('A resposta do Correios não está no formato esperado. Detalhes do problema: "Faltando a entrada \'cServico\'."');
         }
     } else {
         $result->setErrorCode(0);
         if (is_object($r)) {
             $result->setErrorMsg('A resposta do Correios não está no formato esperado. Detalhes do problema: "A resposta recebida é um objeto, mas este objeto não possui todos as entradas necessárias."');
         } else {
             $result->setErrorMsg('A resposta do Correios não está no formato esperado. Resposta recebida: "' . $r . '"');
         }
     }
     $retornoIterator = new \PhpSigep\Model\CalcPrecoPrazoRespostaIterator($retorno);
     $result->setResult($retorno);
     if (!$result->hasError()) {
         if ($retornoIterator->todosTemErro()) {
             $erros = array();
             /** @var $retItem \PhpSigep\Model\CalcPrecoPrazoResposta */
             foreach ($retornoIterator as $retItem) {
                 $erros[$retItem->getErroCodigo()] = $retItem;
             }
             /** @var $exception \PhpSigep\Model\CalcPrecoPrazoResposta */
             $exception = null;
             $errosPrioritarios = array('999', '-3', '-2', '-4', '-33', '7');
             foreach ($errosPrioritarios as $erroPrioritario) {
                 if (isset($erros[$erroPrioritario])) {
                     $exception = $erros[$erroPrioritario];
                     break;
                 }
             }
             if (!$exception) {
                 $exception = reset($erros);
             }
             $result->setErrorCode($exception->getErroCodigo());
             $result->setErrorMsg($exception->getErroMsg());
         } else {
             $cache->setItem($cacheKey, serialize($result));
         }
     }
     return $result;
 }