class Licitacao::Projeto < ApplicationRecord
	has_paper_trail
	include AASM
	include TradutorConcern
	include MensagemConcern
	include EnumModalidadeDeLicitacaoConcern

	attr_accessor :cadastrando_ata_da_carona

	attr_default :status, :aberto
	attr_default :envia_pro_sim, true
	attr_default :sbqc, false # Seleção Baseada na Qualidade e Custo (SBQC)
	attr_default :numero_confirmado, false
	self.inheritance_column = :fake_column

	delegate :unidades_orcamentarias, to: :pedido, :allow_nil => false
	delegate :elementos_de_despesa_do_orcamento, to: :pedido
	delegate :sub_elementos_de_despesa_do_orcamento, to: :pedido

	belongs_to :pedido, inverse_of: :projeto
	belongs_to :legislacao, class_name: 'Base::Legislacao'
	belongs_to :comissao
	belongs_to :orcamento, class_name: 'Orcamento'
	belongs_to :agente_publico_municipal , class_name: "Base::AgentePublicoMunicipal"
	belongs_to :responsavel_cotacao_sim, class_name: "Base::AgentePublicoMunicipal"
	belongs_to :responsavel_elaboracao_sim, class_name: "Base::AgentePublicoMunicipal"
	belongs_to :arquivo, class_name: "Tcm::Arquivo"
	belongs_to :estado, class_name: "Base::Estado"
	belongs_to :cidade, class_name: "Base::Cidade"

	has_many :atas_de_registro_de_precos, dependent: :destroy

	has_many :lotes, dependent: :destroy
	has_many :itens_do_lote, through: :lotes, class_name: 'Licitacao::ItemDoLote'
	has_many :itens_do_pedido_dos_lotes, through: :itens_do_lote, source: :item_do_pedido, class_name: 'Licitacao::ItemDoPedido'
	has_many :itens, through: :itens_do_pedido_dos_lotes, class_name: 'Base::Item'

	has_many :pessoas_do_projeto, dependent: :destroy, foreign_key: :projeto_id
	has_many :pessoas, through: :pessoas_do_projeto
	has_many :itens_do_projeto_por_pessoa, through: :pessoas_do_projeto
	has_many :contratos, class_name: 'Licitacao::Contrato', inverse_of: :projeto, dependent: :restrict_with_exception
	has_many :itens_dos_contratos, through: :contratos, source: 'itens_do_contrato', class_name: 'Licitacao::ItemDoContrato'
	has_many :contratados, through: :pessoas_do_projeto
	has_many :documentos_do_processo
	has_many :publicacoes
	has_many :membros_da_comissao, through: :comissao, class_name: 'Licitacao::MembroDaComissao'
	has_many :vistos, as: :vistoriavel, class_name: "Controladoria::Visto"

	has_many :solicitacoes_de_alteracoes_orcamentarias, class_name: 'Contabilidade::SolicitacaoDeAlteracaoOrcamentaria', dependent: :destroy
	has_many :empenhos, class_name: 'Contabilidade::Empenho', dependent: :restrict_with_exception
	has_many :empenhos_diretos, -> { where contrato_id: nil }, class_name: 'Contabilidade::Empenho', dependent: :restrict_with_exception
	has_many :itens_dos_empenhos_diretos, through: :empenhos_diretos, source: 'itens_do_empenho', class_name: 'Contabilidade::ItemDoEmpenho'
	has_many :passagens, class_name: 'Contabilidade::Passagem'
	has_many :orcamentos_da_despesa_por_projetos, class_name: "Licitacao::OrcamentoDaDespesaPorProjeto", dependent: :destroy
	has_many :sub_elementos_de_despesa, through: :orcamentos_da_despesa_por_projetos, class_name: "Contabilidade::SubElementoDeDespesa"
	has_many :orcamentos_da_despesa, through: :orcamentos_da_despesa_por_projetos, class_name: "Loa::OrcamentoDaDespesa"
	has_many :itens_dos_orcamentos_da_despesa_por_projeto, through: :orcamentos_da_despesa_por_projetos, source: :itens_do_orcamento_da_despesa_por_projeto, class_name: "Licitacao::ItemDoOrcamentoDaDespesaPorProjeto"
	has_many :fonte_de_recursos, through: :orcamentos_da_despesa,class_name: "Base::FonteDeRecursos"
	has_many :recursos, foreign_key: :projeto_id
	has_many :atas_das_sessoes, class_name: "Licitacao::AtaDaSessao", foreign_key: :projeto_id
	has_many :ocorrencias, foreign_key: :projeto_id
	has_many :operacoes_de_credito_do_projeto, class_name: 'Licitacao::OperacaoDeCreditoDoProjeto', dependent: :destroy
	has_many :operacoes_de_credito, through: :operacoes_de_credito_do_projeto, class_name: 'Obra::OperacaoDeCredito'
	has_many :componentes_da_operacao_de_credito, through: :operacoes_de_credito, class_name: 'Obra::ComponenteDaOperacaoDeCredito'
	has_many :acoes_do_componente, through: :componentes_da_operacao_de_credito, class_name: 'Obra::AcaoDoComponente'
	has_many :acoes_da_operacao_de_credito_do_projeto, through: :operacoes_de_credito_do_projeto, class_name: 'Licitacao::AcaoDaOperacaoDeCreditoDoProjeto'
	has_many :unidades_orcamentarias_por_pedido, through: :pedido, class_name: 'Licitacao::UnidadeOrcamentariaPorPedido'

	has_many :configuracoes_sim_do_projeto, class_name: 'Licitacao::ConfiguracaoSimDoProjeto', dependent: :destroy

	validates_presence_of :pedido_id, :data_do_projeto, :modalidade_do_processo, :modalidade_de_licitacao, :forma_de_agrupamento
	validates_presence_of :tipo_de_totalizacao, if: Proc.new{ pedido && self.pedido.projeto_simplificado.blank? }
	validates_presence_of :numero_do_processo, :comissao_id, on: :update, if: Proc.new{ self.status_was == "enviado_para_comissao" }
	validates_presence_of :horario_da_abertura, :data_da_sessao, on: :update, if: :tem_publicacoes?
	validates_presence_of :legislacao_id, if: Proc.new { (self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?) }
	validates_presence_of :lei_federal
	validates_presence_of :cidade_id, :estado_id, :ata_de_registro_de_precos_original, :orgao_gerenciador_da_ata, if: Proc.new { self.cadastrando_ata_da_carona.present? }

	validates_inclusion_of :registro_de_preco, in: [true, false], if: Proc.new { processo_licitatorio? && (pregao? || concorrencia_publica?) }

	validates_format_of :horario_da_abertura, with: /\A^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$\Z/, on: :update, if: :tem_publicacoes?

	validates_associated :pessoas_do_projeto

	validates :data_do_projeto, sabado_ou_domingo_ou_feriado: { flexivel: false }
	validates :pessoas_do_projeto, uniq_nested_attributes: { atributo: :pessoa_id, mensagem: "pessoa deve ser única dentro de um pedido" }
	validates :operacoes_de_credito_do_projeto, uniq_nested_attributes: { atributo: :operacao_de_credito_id, mensagem: "operação de crédito deve ser única dentro de um projeto" }

	validate :pedido_deve_estar_fechado
	#validate :nao_pode_ser_dispensa_ou_inexigibilidade_se_contem_unidades_convidadas
	validate :modalidade_da_licitacao_para_modalidade_do_processo
	validate :modalidade_da_licitacao_para_sbqc
	validate :forma_de_agrupamento_para_dispensa_ou_inexibilidade
	validate :forma_de_agrupamento_para_carona
	validate :forma_de_agrupamento_para_convite
	validate :tipo_de_totalizacao_para_dispensa_ou_inexibilidade
	validate :data_do_projeto_deve_ser_maior_ou_igual_a_data_do_pedido
	#validate :criterio_de_julgamento_para_dispensa_ou_inexibilidade
	validate :valida_criterio_de_julgamento_do_pregao
	validate :numero_do_processo_nao_atualiza_se_tiver_publicacoes, on: :update, if: Proc.new{ numero_do_processo_changed? }
	validate :valida_registro_de_preco, if: Proc.new{ pedido && pedido.projeto_simplificado.blank? }
	# Chamado #3428 - TIRAR VALIDAÇÃO DE DATA
	#validate :valida_data_da_sessao, on: :update, if: Proc.new{ tem_publicacoes? && self.publicacoes.last.data_da_publicacao.present? && self.data_da_sessao.present?}
	validate :valida_valor_orcamentario, if: Proc.new{ pedido.present? }
	validate :numero_do_processo_confirmado_deve_ser_unico, on: :update, if: Proc.new{ numero_do_processo_changed? || (numero_do_processo_was.to_s.blank? && !numero_do_processo.to_s.blank?) }
	validate :valida_forma_de_agrupamento_para_desconto
	validate :valida_exercicio_pelo_pedido

	accepts_nested_attributes_for :pessoas_do_projeto, reject_if: :all_blank, allow_destroy: true
	accepts_nested_attributes_for :operacoes_de_credito_do_projeto, allow_destroy: true

	alias_method :itens_dos_lotes, :itens_do_lote

	before_destroy :verifica_se_o_projeto_esta_andamento
	after_destroy :retorna_status_do_pedido

	before_save :nao_envia_pro_sim, on: :create, if: Proc.new { pedido && ((pedido.projeto_simplificado? && !bid_obra_ou_servico) || outro?)}
	before_save :marca_como_menor_valor, on: :create, if: Proc.new { pedido && pedido.projeto_simplificado? }
	before_save :redefinir_forma_de_agrupamento, on: :update, if: Proc.new{ self.persisted? && (!self.forma_de_agrupamento_was.nil? && self.forma_de_agrupamento_was != self.forma_de_agrupamento)}
	before_create :define_o_sim_da_dispensa, if: Proc.new { dispensa_de_licitacao? && inciso_permite_gerar_da_dispensa? }

	after_create do
		pedido.gerar_projeto!
	end

	after_create :criar_lote_inicial
	after_create :criar_cotacoes, if: Proc.new { self.pode_criar_cotacoes_e_definir_ganhador? && self.lei_8666_93? }
	after_create :define_ganhador, if: Proc.new { self.pode_criar_cotacoes_e_definir_ganhador? && self.lei_8666_93? }

	before_validation :deleta_lotes, if: Proc.new { self.forma_de_agrupamento_changed? && self.lotes.any? }
	after_update :criar_lote_inicial, if: Proc.new { self.forma_de_agrupamento_changed? }
	after_update :preencher_arquivo_id, if: Proc.new { self.arquivo_id_changed? }

	enum criterio_de_julgamento: {
		menor_preco: 1,
		melhor_tecnica: 2,
		tecnica_e_preco: 4,
		maior_desconto: 5,
		melhor_tecnica_ou_conteudo_artistico: 6,
		nao_se_aplica: 7,
		maior_retorno_economico: 8,
		conteudo_artistico: 9
	}

	enum status: {
		aberto: 0,
		enviado_para_comissao: 1,
		aguardando_publicacao: 2,
		em_sessao: 3,
		pos_sessao: 4,
		em_recurso: 5,
		fracassado: 6,
		suspenso: 7,
		revogado: 8,
		enviado_para_controladoria: 89,
		enviado_para_copfin: 90,
		aguardando_autorizacao: 91,
		desertado: 92,
		aguardando_homologacao: 93,
		adjudicado: 94,
		aguardando_parecer_final: 95,
		aguardando_parecer: 96,
		autorizado: 97,
		cancelado: 98,
		homologado: 99
	}

	enum tipo_de_totalizacao: {
		menor_valor: 0,
		valor_medio: 1,
		por_mediana: 2
	}

	enum modalidade_do_processo: {
		processo_licitatorio: 0,
		dispensa_de_licitacao: 1,
		inexigibilidade_de_licitacao: 2,
		parceria_osc: 3,
		outro: 4,
	}

	enum forma_de_agrupamento: {
		global: 0,
		por_lote: 1,
		por_item: 2
	}

	enum lei_federal: {
		lei_8666_93: 1, #8.666/93
		lei_14133_21: 2  #14.133/21
	}

	enum forma_de_contratacao_sim:{
		eletronico: "E",
		presencial: "P"
	}

	enum tipo_de_disputa_sim:{
		aberto_sim: "A",
		fechado_sim: "F",
		combinado_sim: "C"
  }

	aasm column: :status, enum: true, whiny_transitions: false do
		state :aberto, :initial => true
		state :enviado_para_controladoria
		state :enviado_para_copfin
		state :aguardando_autorizacao
		state :autorizado
		state :enviado_para_comissao
		state :aguardando_parecer
		state :aguardando_publicacao
		state :em_sessao
		state :suspenso
		state :pos_sessao
		state :em_recurso
		state :cancelado
		state :revogado
		state :fracassado
		state :desertado
		state :adjudicado
		state :aguardando_parecer_final
		state :aguardando_homologacao
		state :homologado

		event :encaminhar_para_controladoria do
			transitions from: :aberto, to: :enviado_para_controladoria do
				guard do
					if self.por_lote?
						self.lotes.each do |lote|
							lote.cria_sequencia_dos_itens_do_lote
						end
					end
					self.vistos.copfin.blank? && self.aberto? && (self.possui_termo_de_referencia? || !Configuracao.last.obriga_termo_de_referencia?) && Configuracao.last.envia_projeto_para_controladoria? && self.todos_os_lotes_possuem_tipo? && ((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas?
				end
			end
			transitions from: :aberto, to: :enviado_para_copfin do
				guard do
					self.vistos.copfin.present? && !aprovado_pelo_copfin? && self.aberto? && (self.possui_termo_de_referencia? || !Configuracao.last.obriga_termo_de_referencia?) && self.envia_pro_copfin? && self.todos_os_lotes_possuem_tipo? && ((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas?
				end
			end
			after do
				cria_mensagem_envia_projeto_para_controladoria
			end
		end

		event :encaminhar_para_comite_programacao_financeira do
			transitions from: :enviado_para_controladoria, to: :enviado_para_copfin do
				guard do
					self.aprovado_pela_controladoria? && self.envia_pro_copfin?
				end
			end
		end

		event :retorna_para_licitacao do
			transitions from: :enviado_para_controladoria, to: :aberto do
				guard do
					self.vistos.controladoria.present? && !aprovado_pela_controladoria?
				end
			end
			transitions from: :enviado_para_copfin, to: :aberto do
				guard do
					self.vistos.copfin.present? && !aprovado_pelo_copfin? && self.enviado_para_copfin?
				end
			end
			after do
				cria_mensagem_retorno_projeto_da_controladoria
			end
		end

		event :encaminhar_para_autorizacao do
			before do
				if self.por_lote?
					self.lotes.each do |lote|
						lote.cria_sequencia_dos_itens_do_lote
					end
				end
			end
			transitions from: :aberto, to: :aguardando_autorizacao do
				guard do
					if self.outro?
						((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas?
					else
						(self.possui_termo_de_referencia? || !Configuracao.last.obriga_termo_de_referencia?) && !Configuracao.last.envia_projeto_para_controladoria? && self.todos_os_lotes_possuem_tipo? &&
							((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas?
					end
				end
			end
			transitions from: :enviado_para_controladoria, to: :aguardando_autorizacao do
				guard do
					self.aprovado_pela_controladoria? && !self.envia_pro_copfin?
				end
			end
			transitions from: :enviado_para_copfin, to: :aguardando_autorizacao do
				guard do
					self.aprovado_pelo_copfin? && self.envia_pro_copfin? && self.enviado_para_copfin?
				end
			end
		end

		event :autorizar do
			transitions from: :aguardando_autorizacao, to: :autorizado do
				guard do
					self.aguardando_autorizacao? && (self.possui_autorizacao? || !Configuracao.last.obriga_documento_de_autorizacao?)
				end
			end
			after do
				cria_mensagem_projeto_autorizado
			end
		end

		event :encaminhar_para_comissao do
			transitions from: :aberto, to: :enviado_para_comissao do
				guard do
					self.pedido.projeto_simplificado? && self.todos_os_lotes_possuem_tipo? && dotacoes_validas? &&
						((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado))  &&
						(self.contratacao_consultoria_individual? || (self.bid_obra_ou_servico && (self.processo_licitatorio? && !self.carona?) || self.chamamento_publico? || self.chamada_publica? || self.dispensa_ou_inexigibilidade?))

				end
			end
			transitions from: :autorizado, to: :enviado_para_comissao do
				guard do
					self.autorizado? && self.todos_os_lotes_possuem_tipo?
				end
			end
			after do
				gerar_numero_do_processo
				cria_mensagem_de_projeto_encaminhado
			end
		end

		event :voltar_para_aberto do
			transitions from: :enviado_para_comissao, to: :aberto, before: :validate_comissao do
				guard do
					self.enviado_para_comissao?
				end
			end
		end

		event :enviar_para_parecer do
			transitions from: :enviado_para_comissao, to: :aguardando_parecer, before: :validate_comissao do
				guard do
					Configuracao.last.envia_parecer_inicial? && self.possui_documentos_necessarios_do_processo? && ((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas?
				end
			end
			transitions from: :aguardando_parecer, to: :aguardando_parecer do
				guard do
					Configuracao.last.envia_parecer_inicial? && self.ultimo_parecer_devolvido? && !self.documentos_do_processo.parecer.last.vistos_de_documentos_do_processo.last.aprovado?
				end
			end
			after do
				cria_parecer_com_status_enviado_ao_setor_juridico
				cria_mensagem_envia_projeto_para_parecer
			end
		end

		event :iniciar_processo do
			transitions from: :aguardando_parecer, to: :aguardando_publicacao do
				guard do
					(self.possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?) && (self.ultimo_parecer_devolvido? && self.documentos_do_processo.parecer.last.vistos_de_documentos_do_processo.last.aprovado?) && ((self.processo_licitatorio? && !self.carona?) || self.chamamento_publico? || self.chamada_publica?) && self.comissao_id.present?
				end
			end
			transitions from: :enviado_para_comissao, to: :aguardando_publicacao, before: :validate_comissao do
				guard do
					!Configuracao.last.envia_parecer_inicial? && self.possui_documentos_necessarios_do_processo? &&
						((self.processo_licitatorio? && !self.carona?) || self.chamamento_publico? || self.chamada_publica?) &&
							((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && (!Configuracao.last.configura_numero_do_processo? || self.numero_confirmado) && self.comissao_id.present?
				end
			end
			after do
				setar_data_inicial_do_processo
			end
		end

		event :ir_para_sessao do
			transitions from: :aguardando_publicacao, to: :em_sessao do
				guard do
					self.possui_publicacao?
				end
				after do
					atas_das_sessoes.create
				end
			end
		end

		event :suspender do
			transitions from: :em_sessao, to: :suspenso
		end

		event :fracassar_processo do
			transitions from: :em_sessao, to: :fracassado do
				guard do
					self.todos_os_lotes_estao_fracassados? || (self.possui_lote_fracassado? && !self.possui_lotes_ativos?)
				end
			end
		end

		event :desertar_processo do
			transitions from: :em_sessao, to: :desertado do
				guard do
					self.todos_os_lotes_estao_desertados?
				end
			end
		end

		event :concluir_sessao do
			transitions from: :em_sessao, to: :pos_sessao do
				guard do
					self.possui_lotes_ativos? && (self.envia_pro_sim == false || self.possui_data_e_hora_da_sessao?) &&
					!self.possui_recurso_aberto? && self.lances_fechados? && todos_os_lotes_tem_ganhador? && lances_finais_cadastrados?
				end
				after do
					cria_mensagem_unidade_principal && altera_lotes_desertos
				end
			end
		end

		event :abrir_recurso do
			transitions from: :em_sessao, to: :em_recurso
		end

		event :retomar_sessao do
			transitions from: :em_recurso, to: :em_sessao
			transitions from: :suspenso, to: :em_sessao
		end

		event :adjudicado do
			transitions from: :pos_sessao, to: :adjudicado do
				after do
					ocorrencias.create(data_da_ocorrencia: Date.today, horario_da_ocorrencia: Time.now.strftime("%H:%M"), tipo: "adjudicacao", motivo: "Processo foi adjudicado")
				end
			end
			transitions from: :enviado_para_comissao, to: :adjudicado, before: :validate_comissao do
				guard do
					self.lei_8666_93? && self.comissao_id.present? &&
					(self.possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?) && (eh_dispensa_ou_inexigibilidade? || self.carona? || self.outro?) && ((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas? &&
						(Configuracao.last.envia_parecer_final? || !obriga_documento_parecer?) &&  (!Configuracao.last.configura_numero_do_processo? || self.numero_confirmado) && self.todos_os_lotes_tem_ganhador?
				end
			end
			transitions from: :aguardando_parecer, to: :adjudicado do
				guard do
					(self.possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?) && (eh_dispensa_ou_inexigibilidade? || self.carona? || self.outro?) && self.ultimo_parecer_devolvido?  && ((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) && dotacoes_validas?
				end
			end
			after do
				seta_data_de_adjudicacao_do_processo
			end
		end

		event :encaminhar_parecer_final do
			transitions from: :adjudicado, to: :aguardando_parecer_final do
				guard do
					self.adjudicado? && Configuracao.last.envia_parecer_final?
				end
			end
			transitions from: :aguardando_parecer_final, to: :aguardando_parecer_final do
				guard do
					Configuracao.last.envia_parecer_final? && self.ultimo_parecer_devolvido? && !self.documentos_do_processo.parecer.last.vistos_de_documentos_do_processo.last.aprovado?
				end
			end
			after do
				cria_parecer_com_status_enviado_ao_setor_juridico
			end
		end

		event :enviar_para_homologacao do
			transitions from: :aguardando_parecer_final, to: :aguardando_homologacao do
				guard do
					self.ultimo_parecer_devolvido? && self.documentos_do_processo.parecer.last.vistos_de_documentos_do_processo.last.aprovado?
				end
			end
			transitions from: :adjudicado, to: :aguardando_homologacao do
				guard do
					self.adjudicado? && ((self.ultimo_parecer_devolvido? && !Configuracao.last.envia_parecer_final?) || !obriga_documento_parecer?) &&
						((self.envia_pro_sim? && possui_dados_do_sim?) || !self.envia_pro_sim?)
				end
			end
		end

		event :homologar do
			before do
				if self.pedido.projeto_simplificado?
					if self.por_lote?
						self.lotes.each do |lote|
							lote.cria_sequencia_dos_itens_do_lote
						end
					end
				end
			end
			transitions from: :aguardando_homologacao, to: :homologado
			transitions from: :em_sessao, to: :homologado do
				guard do
					self.pedido.projeto_simplificado? && self.bid_obra_ou_servico && self.pessoas_do_projeto.any? &&
						(!self.envia_pro_sim? || self.envia_pro_sim? && possui_dados_do_sim?) && todos_os_lotes_tem_ganhador?
				end
			end
			transitions from: :enviado_para_comissao, to: :homologado, before: :validate_comissao do
				guard do
					self.lei_14133_21? && (self.publicacoes.any? || eh_dispensa_ou_inexigibilidade? || self.outro?) && ((self.envia_pro_sim? && possui_dados_do_sim?) || !self.envia_pro_sim?) &&
						(self.possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?) &&
						(eh_dispensa_ou_inexigibilidade? || self.carona? || self.outro?) &&
						((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado)) &&
						dotacoes_validas? && (Configuracao.last.envia_parecer_final? || !obriga_documento_parecer?) &&
						(!Configuracao.last.configura_numero_do_processo? || self.numero_confirmado) && (self.todos_os_lotes_tem_ganhador? || self.inexigibilidade_de_licitacao? || self.outro? )
				end
			end
			transitions from: :aguardando_publicacao, to: :homologado do
				guard do
					self.pedido.projeto_simplificado? && self.contratacao_consultoria_individual?
				end
			end
			transitions from: :aberto, to: :homologado do
				guard do
					todos_os_lotes_possuem_tipo? && (self.pedido.projeto_simplificado? && ((self.bid_obra_ou_servico && (self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?)) || !self.bid_obra_ou_servico ) &&
						((!registro_de_preco? && self.contem_dotacoes?) || registro_de_preco?)) &&
							(!Configuracao.last.valida_saldo_da_dotacao_no_pb? || dotacoes_tem_saldo?) &&
								(!self.envia_pro_sim? || self.envia_pro_sim? && possui_dados_do_sim?) &&
									((!precisa_de_dotacao? && !contem_dotacoes?) || (dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado))
				end
				after do
					gerar_numero_do_processo
					setar_data_inicial_do_processo
				end
			end
			after do
				seta_data_homologacao_do_processo
				cria_mensagem_de_processo_homologado
			end
		end

		event :cancelar do
			transitions to: :cancelado
		end

		event :revogar do
			transitions to: :revogado
		end

		event :homologar_parcialmente do
			transitions from: [:em_sessao, :aberto], to: :homologado do
				guard do
					self.por_lote? && self.sim_esta_valido? && self.dotacoes_estao_validas? && self.lotes.any?{ |lote| lote.ganhador_id.present? } && self.algum_licitante_preencheu_a_proposta_final?
				end

				after do
					self.update_attribute(:homologado_parcialmente, true)
				end
			end
		end
	end

	#VISTOS
	def aprovado_pela_controladoria?
		self.vistos.controladoria.any? && vistos.controladoria.last.aprovado?
	end

	def aprovado_pelo_copfin?
		self.vistos.copfin.any? && vistos.copfin.last.aprovado?
	end

	# Esse método é utilizado no grid de visto para verificar se o mesmo pode ser editado
	def confirmado?
		!(aberto? || enviado_para_controladoria? || enviado_para_copfin?)
	end

	#VALORES
	def saldo_a_empenhar unidade_orcamentaria
		valor_dos_empenhos = Contabilidade::Empenho.where(projeto_id: self.id).sum(:valor)
		total_contratos = 0
			self.contratos.joins(:unidade_orcamentaria_por_pedido).where(licitacao_unidades_orcamentarias_por_pedido: {unidade_orcamentaria_id: unidade_orcamentaria}).each do |contrato|
				total_contratos += contrato.valor_total_do_contrato
			end
		saldo_do_projeto = self.saldo_do_projeto(unidade_orcamentaria)
		return saldo_do_projeto.to_f - (valor_dos_empenhos.to_f + total_contratos.to_f)
	end

	def saldo_do_projeto unidade_orcamentaria
		self.itens_do_lote.inject(0) do |total, item_do_lote|
			total + (item_do_lote.saldo * item_do_lote.preco_unitario)
		end
	end

	def valor_projeto_simplificado
		pedido.itens_do_pedido.sum(:preco_estimativo)
	end

	def valor_da_adjudicacao
		if data_de_adjudicacao.present?
			return self.valor_estimado_global
		else
			return 0
		end
	end

	def valor_da_homologacao
		if homologado?
			return self.valor_total
		else
			return 0
		end
	end

	def contratos_com_discriminacao_de_itens?
		contratos.present? && contratos.first.discriminacao_obrigatoria_de_itens?
	end

	def valor_estimado_global
		if global? && menor_valor? && pedido.projeto_simplificado.blank?
			pedido.menor_cotacao_global
		elsif global? && valor_medio? && pedido.projeto_simplificado.blank?
			pedido.cotacao_media_dos_itens
		elsif pedido.projeto_simplificado?
			pedido.menor_cotacao_dos_itens
		elsif menor_valor?
			pedido.menor_cotacao_dos_itens
		elsif valor_medio?
			pedido.cotacao_media_dos_itens
		elsif por_mediana?
			pedido.cotacao_dos_itens_por_mediana
		end
	end

	def valor_estimado_por_item
		if menor_valor?
			pedido.menor_cotacao_dos_itens
		elsif valor_medio?
			pedido.cotacao_media_dos_itens
		end
	end

	def valor_total
		return valor_estimado_global if simplificado? && bid_obra_ou_servico == false

		itens_do_lote.includes([:item_do_pedido, :lote]).itens_dos_lotes_ativos.sum(&:preco_final).round(2)
	end

	def valor_total_por_unidade(unidade_orcamentaria_id)
		itens_do_lote.inject(0) do |total, item_do_lote|
			total + item_do_lote.valor_total_por_unidade(unidade_orcamentaria_id)
		end
	end

	def itens_do_lote_por_unidade(unidade_orcamentaria_id)
		self.itens_do_lote.joins(item_do_pedido: [itens_do_pedido_por_unidade_orcamentaria: :unidade_orcamentaria_por_pedido]).where("licitacao_unidades_orcamentarias_por_pedido.unidade_orcamentaria_id = ?",unidade_orcamentaria_id).where("licitacao_itens_do_pedido_por_unidade_orcamentaria.quantidade > 0")
	end

	def itens_do_lote_por_valor_previsto_por_unidade(unidade_orcamentaria_id)
		self.itens_do_lote.joins(item_do_pedido: [itens_do_pedido_por_unidade_orcamentaria: :unidade_orcamentaria_por_pedido]).where("licitacao_unidades_orcamentarias_por_pedido.unidade_orcamentaria_id = ?",unidade_orcamentaria_id).where("licitacao_itens_do_pedido_por_unidade_orcamentaria.valor_previsto_desconto > 0")
	end

	def itens_do_lote_por_valor_previsto
		self.itens_do_lote.joins(item_do_pedido: :itens_do_pedido_por_unidade_orcamentaria).where("licitacao_itens_do_pedido_por_unidade_orcamentaria.valor_previsto_desconto > 0")
	end

	def valor_a_contratar
		total_a_contratar = valor_total - valor_total_contratado - empenhos_diretos.ativos.sum(&:definir_valor_do_empenho)
		return total_a_contratar < 0 ? 0.0 : total_a_contratar.to_f
	end

	def valor_a_empenhar_por_fornecedor(fornecedor_id)
		total = valor_total_por_fornecedor(fornecedor_id) - empenhos_diretos.where(pessoa_id: fornecedor_id).ativos.sum(&:definir_valor_do_empenho)
		return total.to_d
	end

	def valor_total_por_fornecedor(fornecedor_id)
		id_pessoa_do_projeto = pessoas_do_projeto.find_by(pessoa_id: fornecedor_id).id
		lotes_ganhos = lotes.where(ganhador_id: id_pessoa_do_projeto)
		valor_total = lotes_ganhos.sum(&:valor_total_da_menor_cotacao_dos_itens).to_d
	end

	def valor_total_contratado
		contratos.includes([:ata_de_registro_de_precos]).sum(&:valor_total_do_contrato)
	end

	def valor_total_utilizado
		valor_total.to_f - valor_a_contratar.to_f
	end

	def valor_comprometido
		valor_dos_empenhos = empenhos.where(projeto_id: self.id).sum(:valor)
		valor_dos_empenhos_diretos = empenhos_diretos.where(projeto_id: self.id).sum(:valor)
		orcamentos_da_despesa_por_projetos.sum(&:valor_comprometido_por_dotacao) - valor_dos_empenhos - valor_dos_empenhos_diretos
	end

	def quantidade_total_itens_dos_lotes_ativos
		itens_dos_lotes.itens_dos_lotes_ativos.inject(0) {|total, item_do_lote| total + item_do_lote.quantidade_total_requisitada}
	end

	def saldo_dotacoes
		(valor_estimado_global.round(2) - valor_total_das_dotacoes.to_f.round(2))
	end

	def valor_total_das_dotacoes
		orcamentos_da_despesa_por_projetos.sum(:valor)
	end

	def dispensa_com_controle_de_valor?
		self.legislacao.try(:eh_artigo_24_inciso_i?) || self.legislacao.try(:eh_artigo_24_inciso_ii?) || self.legislacao.try(:eh_artigo_75_inciso_i?) || self.legislacao.try(:eh_artigo_75_inciso_ii?)
	end

	def fracionamento_dispensas
		if self.dispensa_de_licitacao? && legislacao.present?
			atributos_fracionamento = Configuracao.last.attributes.select{|attr_name, attr_value| ["francionamento_de_dispensa_por_subelemento", "francionamento_de_dispensa_por_cnpj", "francionamento_de_dispensa_por_unidade_gestora"].include?(attr_name) && attr_value}
			dispensa_value = Licitacao::Projeto.modalidades_do_processo[:dispensa_de_licitacao]
			orcamento_atual = pedido.orcamento

			if self.lei_8666_93?
				valor_teto_inciso_dois = 17600 #Valor do teto: R$ 17.600,00
				valor_teto_inciso_um = 33000 #Valor do teto: R$ 33.000,00
				numero_lei_federal = 1
			else
				valor_teto_inciso_dois = 54020.41 #Valor do teto: R$ 54.020,41
				valor_teto_inciso_um = 108040.82 #Valor do teto: R$ 108.040,82
				numero_lei_federal = 2
			end

			elementos_que_passaram_do_teto_dois = []
			elementos_que_passaram_do_teto_um  = []

			# francionamento_de_dispensa_por_cnpj
			if atributos_fracionamento["francionamento_de_dispensa_por_cnpj"] && !atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && !atributos_fracionamento["francionamento_de_dispensa_por_subelemento"]
				pessoas_do_projeto_com_lotes_ganhos = orcamento_atual.pessoas_do_projeto.joins(:projeto, :lotes_ganhos).where(licitacao_projetos: {modalidade_do_processo: dispensa_value}).where(licitacao_projetos: {lei_federal: numero_lei_federal}).where(licitacao_pessoas_do_projeto: {pessoa_id: pessoa_ids})
				pessoas_do_projeto_com_lotes_ganhos.each do |pessoa_do_projeto|
					valor_total_pessoa_do_projeto_atual = pessoas_do_projeto.find_by_pessoa_id(pessoa_do_projeto.pessoa.id).lotes_ganhos.inject(0){ |total, lote| total + lote.ganhador.valor_total_final_do_lote(lote).to_f }
					valor_total = pessoa_do_projeto.lotes_ganhos.inject(0){ |total, lote| total + lote.ganhador.valor_total_final_do_lote(lote).to_f }
					elementos_que_passaram_do_teto_dois << {objeto: pessoa_do_projeto.empresa_nome, valor_total: valor_total} if valor_total + valor_total_pessoa_do_projeto_atual >= valor_teto_inciso_dois
					elementos_que_passaram_do_teto_um << {objeto: pessoa_do_projeto.empresa_nome, valor_total: valor_total} if valor_total + valor_total_pessoa_do_projeto_atual >= valor_teto_inciso_um
				end
			# francionamento_de_dispensa_por_subelemento
			elsif atributos_fracionamento["francionamento_de_dispensa_por_subelemento"] && !atributos_fracionamento["francionamento_de_dispensa_por_cnpj"] && !atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"]
				subelementos_de_despesa_por_projetos = orcamento_atual.projetos.homologado.where(modalidade_do_processo: dispensa_value).where(licitacao_projetos: {lei_federal: numero_lei_federal})
					.joins(orcamentos_da_despesa_por_projetos: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]])
						.joins(orcamentos_da_despesa_por_projetos: :sub_elemento_de_despesa)
							.where(contabilidade_sub_elementos_de_despesa: {id: sub_elemento_de_despesa_ids})
								.group(:unidade_orcamentaria_id, :sub_elemento_de_despesa_id).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')

				subelementos_de_despesa_por_projetos.each do |unidade_e_subelemento, valor_total|
					subelemento_id = unidade_e_subelemento.uniq[1]
					unidade_orcamentaria_id = unidade_e_subelemento.uniq[0]
					unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(unidade_orcamentaria_id)
					valor_total_subelemento_atual = orcamentos_da_despesa_por_projetos.joins(:sub_elemento_de_despesa).where(contabilidade_sub_elementos_de_despesa: {id: subelemento_id}).sum(:valor)
					subelemento_atual = Contabilidade::SubElementoDeDespesa.find(subelemento_id)
					elementos_que_passaram_do_teto_dois << {objeto: unidade_orcamentaria.unidade_gestora.codigo_e_nome << " / " << subelemento_atual.codigo_e_descricao, valor_total: valor_total} if valor_total + valor_total_subelemento_atual >= valor_teto_inciso_dois
					elementos_que_passaram_do_teto_um << {objeto: unidade_orcamentaria.unidade_gestora.codigo_e_nome << " / " << subelemento_atual.codigo_e_descricao, valor_total: valor_total} if valor_total + valor_total_subelemento_atual >= valor_teto_inciso_um
				end
			# francionamento_de_dispensa_por_unidade_gestora
			elsif atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && !atributos_fracionamento["francionamento_de_dispensa_por_subelemento"] && !atributos_fracionamento["francionamento_de_dispensa_por_cnpj"]
				# para dispensa, não é possível convidar unidades, portanto, cada projeto terá somente uma unidade gestora
				unidades_orcamentarias_por_projetos = orcamento_atual.projetos.homologado.where(modalidade_do_processo: dispensa_value).where(licitacao_projetos: {lei_federal: numero_lei_federal})
					.joins(orcamentos_da_despesa_por_projetos: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]])
						.where('loa_unidades_orcamentarias.id in (?)', unidades_orcamentarias.pluck(:id))
							.group(:unidade_orcamentaria_id).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')

				unidades_orcamentarias_por_projetos.each do |unidade_orcamentaria_id, valor_total|
					unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(unidade_orcamentaria_id)
					valor_total_por_unidade = orcamentos_da_despesa_por_projetos.joins(orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]])
						.where(loa_unidades_orcamentarias: {id: unidade_orcamentaria_id}).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')
					elementos_que_passaram_do_teto_dois << {objeto: unidade_orcamentaria.unidade_gestora.codigo_e_nome, valor_total: valor_total} if valor_total + valor_total_por_unidade >= valor_teto_inciso_dois
					elementos_que_passaram_do_teto_um << {objeto: unidade_orcamentaria.unidade_gestora.codigo_e_nome, valor_total: valor_total} if valor_total + valor_total_por_unidade >= valor_teto_inciso_um
				end
			elsif atributos_fracionamento["francionamento_de_dispensa_por_cnpj"]
				pessoas_do_projeto_com_lotes_ganhos = orcamento_atual.pessoas_do_projeto.joins(:projeto, :lotes_ganhos)
					.where(licitacao_projetos: {modalidade_do_processo: dispensa_value}).where(licitacao_projetos: {lei_federal: numero_lei_federal})
						.where(licitacao_pessoas_do_projeto: {pessoa_id: pessoa_ids})

				pessoas_do_projeto_com_lotes_ganhos.each do |pessoa_do_projeto|
					if atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && atributos_fracionamento["francionamento_de_dispensa_por_subelemento"]
						subelementos_de_despesa_por_projetos = orcamento_atual.projetos.where(modalidade_do_processo: dispensa_value).where(licitacao_projetos: {lei_federal: numero_lei_federal}).joins(:pessoas).where(base_pessoas: {id: pessoa_do_projeto.pessoa_id})
							.joins(orcamentos_da_despesa_por_projetos: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]])
								.where('loa_unidades_orcamentarias.id in (?)', unidades_orcamentarias.pluck(:id))
									.group(:unidade_orcamentaria_id).joins(orcamentos_da_despesa_por_projetos: :sub_elemento_de_despesa)
										.where(contabilidade_sub_elementos_de_despesa: {id: sub_elemento_de_despesa_ids})
											.group(:unidade_orcamentaria_id, :sub_elemento_de_despesa_id).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')

					elsif atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && !atributos_fracionamento["francionamento_de_dispensa_por_subelemento"]
						subelementos_de_despesa_por_projetos = orcamento_atual.projetos.where(modalidade_do_processo: dispensa_value).where(licitacao_projetos: {lei_federal: numero_lei_federal}).joins(:pessoas).where(base_pessoas: {id: pessoa_do_projeto.pessoa_id})
							.joins(orcamentos_da_despesa_por_projetos: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]])
								.where('loa_unidades_orcamentarias.id in (?)', unidades_orcamentarias.pluck(:id))
									.group(:unidade_orcamentaria_id).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')
					elsif !atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && atributos_fracionamento["francionamento_de_dispensa_por_subelemento"]
						subelementos_de_despesa_por_projetos = orcamento_atual.projetos.where(modalidade_do_processo: dispensa_value).where(licitacao_projetos: {lei_federal: numero_lei_federal}).joins(:pessoas).where(base_pessoas: {id: pessoa_do_projeto.pessoa_id})
							.joins(orcamentos_da_despesa_por_projetos: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]])
								.joins(orcamentos_da_despesa_por_projetos: :sub_elemento_de_despesa)
									.where(contabilidade_sub_elementos_de_despesa: {id: sub_elemento_de_despesa_ids})
										.group(:unidade_orcamentaria_id, :sub_elemento_de_despesa_id).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')
					end

					subelementos_de_despesa_por_projetos.each do |unidade_e_subelemento, valor_total|
						valor_total_subelemento_atual = 0
						if atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && !atributos_fracionamento["francionamento_de_dispensa_por_subelemento"]
							unidade_orcamentaria_id = unidade_e_subelemento
						else
							subelemento_id = unidade_e_subelemento.uniq[1]
							unidade_orcamentaria_id = unidade_e_subelemento.uniq[0]
						end
						unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(unidade_orcamentaria_id)
						if subelemento_id.present?
							valor_total_subelemento_atual = orcamentos_da_despesa_por_projetos.joins(:sub_elemento_de_despesa).where(contabilidade_sub_elementos_de_despesa: {id: subelemento_id}).sum(:valor)
							subelemento_atual = Contabilidade::SubElementoDeDespesa.ativos.find_by(elemento_de_despesa_id: subelemento_id)
						end
						texto_pessoa = pessoa_do_projeto.pessoa.nome
						texto_unidade = unidade_orcamentaria.present? ? (" / " + unidade_orcamentaria.unidade_gestora.codigo_e_nome) : ""
						texto_subelemento = subelemento_atual.present? ? (" / " + subelemento_atual.codigo_e_descricao) : ""
						texto_objeto = (texto_pessoa + texto_unidade +  texto_subelemento).to_s
						elementos_que_passaram_do_teto_dois << {objeto: texto_objeto, valor_total: valor_total} if valor_total + valor_total_subelemento_atual >= valor_teto_inciso_dois
						elementos_que_passaram_do_teto_um << {objeto: texto_objeto, valor_total: valor_total} if valor_total + valor_total_subelemento_atual >= valor_teto_inciso_um
					end
				end

			elsif atributos_fracionamento["francionamento_de_dispensa_por_unidade_gestora"] && atributos_fracionamento["francionamento_de_dispensa_por_subelemento"] && !atributos_fracionamento["francionamento_de_dispensa_por_cnpj"]
				subelementos_de_despesa_por_projetos = orcamento_atual.projetos.where(modalidade_do_processo: dispensa_value).where(licitacao_projetos: {lei_federal: numero_lei_federal})
					.joins(orcamentos_da_despesa_por_projetos: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]])
						.where('loa_unidades_orcamentarias.id in (?)', unidades_orcamentarias.pluck(:id))
							.group(:unidade_orcamentaria_id).joins(orcamentos_da_despesa_por_projetos: :sub_elemento_de_despesa)
								.where(contabilidade_sub_elementos_de_despesa: {id: sub_elemento_de_despesa_ids})
									.group(:unidade_orcamentaria_id, :sub_elemento_de_despesa_id).sum('licitacao_orcamentos_da_despesa_por_projetos.valor')

				subelementos_de_despesa_por_projetos.each do |unidade_e_subelemento, valor_total|
					subelemento_id = unidade_e_subelemento[1]
					unidade_orcamentaria_id = unidade_e_subelemento[0]
					unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(unidade_orcamentaria_id)
					valor_total_subelemento_atual = orcamentos_da_despesa_por_projetos.joins(:sub_elemento_de_despesa).where(contabilidade_sub_elementos_de_despesa: {id: subelemento_id}).sum(:valor)
					subelemento_atual = Contabilidade::SubElementoDeDespesa.ativos.find_by(elemento_de_despesa_id: subelemento_id)
					texto_unidade = unidade_orcamentaria.present? ? (unidade_orcamentaria.unidade_gestora.codigo_e_nome) : ""
					texto_subelemento = subelemento_atual.present? ? (" / " + subelemento_atual.codigo_e_descricao) : ""
					texto_objeto = (texto_unidade +  texto_subelemento).to_s
					elementos_que_passaram_do_teto_dois << {objeto: texto_objeto, valor_total: valor_total} if valor_total + valor_total_subelemento_atual >= valor_teto_inciso_dois
					elementos_que_passaram_do_teto_um << {objeto: texto_objeto, valor_total: valor_total} if valor_total + valor_total_subelemento_atual >= valor_teto_inciso_um
				end
			end

			if self.legislacao.try(:eh_artigo_24_inciso_i?) || self.legislacao.try(:eh_artigo_75_inciso_i?)
				return elementos_que_passaram_do_teto_um
			elsif self.legislacao.try(:eh_artigo_24_inciso_ii?) || self.legislacao.try(:eh_artigo_75_inciso_ii?)
				return elementos_que_passaram_do_teto_dois
			end
		end
	end

	def mostrar_fracionamento_dispensa_formatado
		retorno_fracionamento_dispensas = fracionamento_dispensas
		if !retorno_fracionamento_dispensas.blank?
			retorno_fracionamento_dispensas.map{|obj| p "[" << obj[:objeto] << ": " << obj[:valor_total].try(:real_contabil).to_s << "]"}.join(", ")
		end
	end

	def deleta_processo(com_pedido)
		ActiveRecord::Base.transaction do
			impugnacoes.destroy_all
			pessoas_do_projeto.destroy_all
			lotes.destroy_all
			ocorrencias.destroy_all
			orcamentos_da_despesa_por_projetos.destroy_all
			publicacoes.delete_all
			documentos_do_processo.destroy_all
			vistos.destroy_all
			passagens.destroy_all
			recursos.destroy_all
			atas_das_sessoes.destroy_all
			atas_de_registro_de_precos.destroy_all
			self.delete
			com_pedido.present? ? Licitacao::Pedido.delete(pedido_id) : Licitacao::Pedido.find(self.pedido.id).fechado!
		end
	end

	def fontes_de_recursos_de_operacao_de_credito
		fonte_de_recursos.select {|codigo_da_fonte| ["1130000000", "1230000000", "1920000000", "2230000000", "2920000000"].include?(codigo_da_fonte.codigo_completo)}
	end

	# BOOLEANS
	def pode_adicionar_licitante?
		(simplificado? && homologado?) || !homologado? || self.homologado_parcialmente?
	end

	def simplificado?
		pedido.projeto_simplificado?
	end

	def possui_dados_do_sim?
		!self.data_de_envio_pro_sim.blank? && !self.data_de_autuacao.blank? && !self.agente_publico_municipal.nil?
	end

	def todos_os_lotes_estao_desertados?
		lotes.nao_nulos.all? { |lote| lote.deserto? }
	end

	def lances_fechados?
		if self.inexigibilidade_de_licitacao?
			return true
		else
			lotes.ativo.all? { |lote| lote.lances_fechados?	}
		end
	end

	def possui_lances?
		lotes.ativo.joins(:lances).count > 0
	end

	def todos_os_lotes_tem_ganhador?
		lotes.ativos.all? { |lote| lote.ganhador.present? }
	end

	def lances_finais_cadastrados?
		itens_dos_lotes.itens_dos_lotes_ativos.all? { |item_do_lote| item_do_lote.itens_do_projeto_por_pessoa.finais.count >= 1 }
	end

	def pregao?
		pregao_eletronico? || pregao_presencial?
	end

	def possui_data_e_hora_da_sessao?
		(self.data_da_sessao.present? && self.horario_da_abertura.present?)
	end

	def precisa_de_dotacao?
		(self.registro_de_preco? && Configuracao.last.obriga_dotacao_para_registro_com_preco? ) || self.outro? || dotacao_parceria? || (dotacao_pregao_presencial? || dotacao_pregao_eletronico? || (convite? || contratacao_consultoria_individual? || rdc?))
	end

	# Todas as unidades orçamentárias possuem dotação cadastrada
	# Codigo comentado pelos problemas de unidades de um exercico em outro
	def dotacao_completa?
		# unidades_orcamentarias_com_dotacao = orcamentos_da_despesa_por_projetos.joins(
		# 	orcamento_da_despesa:[elemento_de_despesa_por_subacao: :subacao]
		# ).pluck("loa_subacoes.unidade_orcamentaria_id").uniq
		# unidades_orcamentarias_com_dotacao.sort! == unidades_orcamentarias.ids.sort!
		orcamentos_da_despesa_por_projetos.count >= unidades_orcamentarias.count
	end

	def unidade_principal_contem_dotacao?
		return orcamentos_da_despesa_por_projetos.any? { |dotacao| dotacao.unidade_orcamentaria.codigo_e_nome == self.pedido.unidade_orcamentaria.codigo_e_nome } rescue false
	end

	def contem_dotacoes?
		orcamentos_da_despesa_por_projetos.any?
	end

	def contem_solicitacoes_de_alteracoes_orcamentarias?
		solicitacoes_de_alteracoes_orcamentarias.any?
	end

	def dotacoes_tem_itens_validos?
		orcamentos_da_despesa_por_projetos.map { |o| o.itens_do_orcamento_da_despesa_por_projeto.size }.sum > 0 ? true : false
	end

	def dotacoes_validas?
		if contem_dotacoes?
			((self.dotacoes_tem_saldo? && Configuracao.last.valida_saldo_da_dotacao_no_pb?) || !Configuracao.last.valida_saldo_da_dotacao_no_pb? )
		else
			return true
		end
	end

	def dotacoes_tem_saldo?
		if contem_dotacoes?
			orcamentos_da_despesa_por_projetos.each do |orcamento_da_despesa_por_projeto|
				if orcamento_da_despesa_por_projeto.valor.to_f > orcamento_da_despesa_por_projeto.orcamento_da_despesa.saldo.to_f
					return false
				end
			end
			return true
		else
			return true
		end
	end

	def dotacoes_tem_saldo_disponivel_para_novos_processos?
		if contem_dotacoes?
			orcamentos_da_despesa_por_projetos.each do |orcamento_da_despesa_por_projeto|
				if orcamento_da_despesa_por_projeto.valor.to_f > orcamento_da_despesa_por_projeto.orcamento_da_despesa.saldo_disponivel_para_novos_processos
					return false
				end
			end
			return true
		else
			return true
		end
	end

	def possui_contratos?
		contratos.any?
	end

	def possui_empenhos?
		empenhos.any?
	end

	def possui_saldo_de_itens?
		if registro_de_preco?
			# TODO: implementar
		else
			itens_do_lote.any? { |item_do_lote| item_do_lote.possui_saldo? }
		end
	end

	def pode_revogar?
		!self.cancelado? && !self.revogado? && !self.fracassado? && !self.desertado? && self.contratos.size == 0 && self.atas_de_registro_de_precos.size == 0 && !self.empenhos.any?
	end

	def numero_pode_ser_configurado?
		!self.aberto? && !self.fracassado? && !self.suspenso? && !self.desertado? && !self.cancelado? && !self.revogado?
	end

	def todos_os_lotes_possuem_tipo?
		self.lotes.ativos.where(tipo: nil).empty?
	end

	def parecer_concluido?
		self.documentos_do_processo.parecer.any? && self.documentos_do_processo.parecer.all? { |parecer| parecer.concluido? }
	end

	def parecer_devolvido?
		self.documentos_do_processo.parecer.any? && self.documentos_do_processo.parecer.all? { |parecer| parecer.devolvido? }
	end

	def ultimo_parecer_devolvido?
		self.documentos_do_processo.parecer.any? && self.documentos_do_processo.parecer.last.devolvido?
	end

	def obriga_documento_parecer?
		Configuracao.last.envia_parecer_final? || Configuracao.last.envia_parecer_inicial?
	end

	def possui_documentos_necessarios_do_processo?
		if self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?
			(possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?)
		elsif self.processo_licitatorio?
			(possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?) && (possui_despacho? || !Configuracao.last.obriga_despacho.present?) &&
			(possui_minuta_de_contrato? || !Configuracao.last.obriga_minuta_de_contrato.present?) && (!registro_de_preco || (possui_minuta_de_ata_de_registro_de_preco? || !Configuracao.last.obriga_minuta_de_ata_de_registro_de_preco.present?))
		elsif self.parceria_osc?
			(possui_um_termo_gerado? || !Configuracao.last.obriga_termo_de_autuacao.present?) && (possui_despacho? || !Configuracao.last.obriga_despacho.present?) &&
			(possui_minuta_de_contrato? || !Configuracao.last.obriga_minuta_de_contrato.present?) && (!registro_de_preco || (possui_minuta_de_ata_de_registro_de_preco? || !Configuracao.last.obriga_minuta_de_ata_de_registro_de_preco.present?))
		end
	end

	def possui_autorizacao?
		self.documentos_do_processo.autorizacao.any?
	end

	def possui_termo_de_referencia?
		self.documentos_do_processo.termo_de_referencia.any? || pedido.possui_termo_de_referencia?
	end

	def possui_um_termo_gerado?
		self.documentos_do_processo.termo.any?
	end

	def possui_edital?
		self.documentos_do_processo.edital.any?
	end

	def possui_despacho?
		self.documentos_do_processo.despacho.any?
	end

	def possui_minuta_de_contrato?
		self.documentos_do_processo.minuta_de_contrato.any?
	end

	def possui_lotes_ativos?
		self.lotes.ativos.any?
	end

	def todos_os_lotes_estao_fracassados?
		self.lotes.nao_nulos.all? { |lote| lote.fracassado?	}
	end

	def possui_lote_fracassado?
		self.lotes.fracassado.any?
	end

	def possui_minuta_de_ata_de_registro_de_preco?
		self.registro_de_preco? && self.documentos_do_processo.minuta_de_ata_de_registro_de_preco.any?
	end

	def possui_minuta_do_edital?
		self.documentos_do_processo.minuta_do_edital.any?
	end

	def possui_publicacao?
		self.publicacoes.any?
	end

	def possui_recurso_aberto?
		self.recursos.where(situacao: 0).any?
	end

	def possui_recurso?
		self.recursos.any?
	end

	def processo_concluido?
		self.cancelado? || self.homologado?
	end

	def pode_editar?
		unless importado_do_tcm? || enviado_para_o_sim?
			if dispensa_ou_inexigibilidade? || dispensa_de_chamamento? || self.inexigibilidade_de_chamamento? || self.carona?
				self.fase_de_projeto? || self.aguardando_publicacao?
			else
				!self.sessao_iniciada?
			end
		else
			return false
		end
	end

	def pode_deletar?
		unless importado_do_tcm? || enviado_para_o_sim?
			if dispensa_ou_inexigibilidade? || dispensa_de_chamamento? || self.inexigibilidade_de_chamamento?
				self.fase_de_projeto? || self.aguardando_publicacao?
			else
				!self.sessao_iniciada? && !self.cancelado? && !self.revogado?
			end
		end
	end

	def pode_deletar_com_ou_sem_pedido?
		!self.revogado? && !self.possui_empenhos? && !self.possui_contratos? && !self.enviado_para_o_sim?
	end

	def pode_editar_documentos?
		!self.cancelado? && !self.revogado? && !self.fracassado? && !self.desertado? && !enviado_para_o_sim?
	end

	def fase_de_projeto?
		self.aberto? || self.enviado_para_controladoria? || self.enviado_para_copfin? || self.aguardando_autorizacao? || self.autorizado?
	end

	def sessao_iniciada?
		if eh_dispensa_ou_inexigibilidade? || self.carona?
			true
		else self.processo_licitatorio? || self.chamamento_publico? || self.chamada_publica?
			self.em_sessao? || self.pos_sessao? || self.em_recurso? || self.cancelado? || self.adjudicado? || self.aguardando_parecer_final? || self.aguardando_homologacao? || self.homologado?
		end
	end

	def processo_iniciado?
		if eh_dispensa_ou_inexigibilidade? || self.carona?
			false
		else self.processo_licitatorio? || self.chamamento_publico? || self.chamada_publica?
			self.aguardando_publicacao? || self.em_sessao? || self.pos_sessao? || self.em_recurso? || self.cancelado? || self.adjudicado? || self.aguardando_parecer_final? || self.aguardando_homologacao? || self.homologado?
		end
	end

	def pos_sessao_em_diante?
		self.pos_sessao? || self.em_recurso? || self.cancelado? || self.adjudicado? || self.aguardando_parecer_final? || self.aguardando_homologacao? || self.homologado?
	end

	def todos_os_lotes_possuem_ganhadores?
		lotes.where(ganhador: nil).blank?
	end

	def envia_pro_copfin?
		Configuracao.last.comite_programacao_financeira?
	end

	def tem_publicacoes?
		publicacoes.any?
	end

	def importado_do_tcm?
		self.arquivo_id == 0
	end

	def enviado_para_o_sim?
		self.arquivo_id.present? && self.arquivo_id > 0
	end

	def eh_dispensa_ou_inexigibilidade?
		self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao? || self.dispensa_de_chamamento? || self.inexigibilidade_de_chamamento?
	end

	def pode_criar_cotacoes_e_definir_ganhador?
		self.convite? || self.contratacao_consultoria_individual? || eh_dispensa_ou_inexigibilidade? || self.carona? || self.outro?
	end

	def dotacao_parceria?
		self.dispensa_de_chamamento? || self.chamamento_publico? || self.chamada_publica?
	end

	def dotacao_pregao_presencial?
		pregao_presencial? && !registro_de_preco?
	end

	def dotacao_pregao_eletronico?
		pregao_eletronico? && !registro_de_preco?
	end

	def dispensa_nao_deve_ir_pro_sim?
		# Dispensas com legislação do artigo 24, incisos I e II nunca vão para o SIM, nem projetos simplificados
		(self.pedido.projeto_simplificado? && !self.bid_obra_ou_servico) ||
			(self.dispensa_de_licitacao? && self.legislacao && self.legislacao.fixo? &&
				(self.legislacao.try(:eh_artigo_24_inciso_i?) || self.legislacao.try(:eh_artigo_24_inciso_ii?)))
	end

	def tem_fontes_de_recursos_de_operacao_de_credito?
		if fonte_de_recursos.any?
			fontes_iguais = fonte_de_recursos.map(&:codigo_completo).select {|codigo_da_fonte| ["1130000000", "1230000000", "1920000000", "2230000000", "2920000000"].include?(codigo_da_fonte)}.uniq
			fontes_iguais.empty? ? false : true
		end
	end

	def tem_lote_de_servico?
		lotes.each do |lote|
			return lote.servico?
		end
	end

	def atualiza_e_confirma_numero_do_processo(numero_do_processo, id_da_comissao)
		if !processo_eh_unico?(numero_do_processo)
			errors.add(:numero_do_processo, "Já existe um processo confirmado com esse número")
			return false
		else
			self.update_attributes(numero_do_processo: numero_do_processo, numero_confirmado: true)
			self.update_attributes(comissao_id: id_da_comissao)

			return true
		end
	end

	def processo_eh_unico? numero_do_processo
		Licitacao::Processo.where.not(id: self.id).where(numero_do_processo: numero_do_processo, numero_confirmado: true).empty?
	end

	# HELPERS
	def validade_do_projeto
		if self.pedido.vigencia.present?
			"#{self.pedido.vigencia.to_s}"
		else
			""
		end
	end

	def valida_adicionar_remover_licitante
		if self.homologado_parcialmente? == false && (self.pregao_presencial? || self.pregao_eletronico?)
			lotes.each do |lote|
				if lote.rodadas.count > 0
					raise "Não é possível adicionar ou remover licitantes, pois já existem lances abertos"
					return
				end
			end
		end
	end

	def todos_os_licitantes_possuem_cnpj_diferente? pessoas_ids
		cnpjs = []
		::Base::Pessoa.find(pessoas_ids).each do |pessoa|
			cnpjs <<  pessoa.cnpj unless cnpjs.include? pessoa.cnpj
		end

		if pessoas_ids.count != cnpjs.count
			errors.add(:pessoas_do_projeto, "Não é possível adicionar licitantes com mesmo cnpj")
			return false
		else
			return true
		end
	end

	def unidade_orcamentaria_atual unidade
		unidade_orcamentaria_do_exercicio_atual = orcamento.unidades_orcamentarias.joins(:unidades_orcamentaria_vinculada).find_by('loa_unidades_orcamentaria_vinculada.unidade_orcamentaria_vinculada_id = ?', unidade.id)
	end

	def dotacoes_da_unidade unidade
		if self.orcamento.id == self.pedido.orcamento.id
			dotacoes = self.orcamentos_da_despesa_por_projetos.joins(orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]).where("loa_unidades_orcamentarias.id =?", unidade.id)
		else
			unidade_orcamentaria_do_orcamento_do_projeto = self.orcamento.unidades_orcamentarias.joins(:orgao).find_by(loa_orgaos:{codigo: unidade.orgao.codigo}, codigo: unidade.codigo)
			dotacoes = self.orcamentos_da_despesa_por_projetos.joins(orcamento_da_despesa:[elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]).where("loa_unidades_orcamentarias.id =?", unidade_orcamentaria_do_orcamento_do_projeto.id)
		end

		return dotacoes
	end

	def modalidade_do_processo_e_modalidade_de_licitacao
		"#{self.localizar :modalidade_do_processo} (#{self.localizar :modalidade_de_licitacao})"
	end

	def ganhadores_dos_lotes
		ganhadores_lotes = self.lotes.ativo.pluck(:ganhador_id)
		Licitacao::PessoaDoProjeto.where(id: ganhadores_lotes)
	end

	def contratos_vigentes
		self.contratos.where('fim_da_vigencia >= ?', Date.today)
	end

	def lote_gerado_para_o_mes_de_referencia(data_de_referencia)
		if data_de_referencia.present?
			mes = data_de_referencia.to_date.month
			ano = data_de_referencia.to_date.year
			orcamento_da_data_referencia = Orcamento.find_by(exercicio: ano)
			#Ultima geracao do SIM para o mes_de_referencia
			geracao_do_lote_pro_sim = orcamento_da_data_referencia.lotes_do_tcm.licitacao.gerado.where(mes_de_referencia: mes).last if orcamento_da_data_referencia.present?
		end
	end

	def gerar_numero_do_processo
		configuracoes = Configuracao.last
		orcamento = self.orcamento
		if self.numero_do_processo.blank?
			if configuracoes.mascara_numero_do_processo.present?
				mascara = configuracoes.mascara_numero_do_processo
				# Neste momento, o objeto já foi persistido no banco.
				# Portanto, basta dar count para saber qual seria o próximo numero
				if mascara["D"] != nil
					proximo_numero = orcamento.processos.where(data_do_projeto: self.data_do_projeto).count
				else
					proximo_numero = orcamento.processos.count
				end

				mascara["D"] = self.data_do_projeto.strftime("%d")  if mascara["D"] != nil
				mascara["M"] = self.data_do_projeto.strftime("%m")  if mascara["M"] != nil
				mascara["A"] = self.data_do_projeto.strftime("%Y")  if mascara["A"] != nil
				mascara["S"] = proximo_numero.to_s.rjust(2, '0') if mascara["S"] != nil
				mascara["O"] = self.pedido.unidade_orcamentaria.orgao.sigla if mascara["O"] != nil
				mascara["X"] = self.sigla_da_modalidade if mascara["X"] != nil
				self.update_column(:numero_do_processo, "#{mascara}")
			else
				proximo_numero = orcamento.processos.where.not(numero_do_processo: nil).count + 1
				#proximo_numero = orcamento.processos.where("licitacao_projetos.numero_do_processo != null").count + 1
				if self.pedido.unidade_orcamentaria.present? && self.pedido.unidade_orcamentaria.orgao.present? && proximo_numero.present?
					self.update_column(:numero_do_processo, "#{self.data_do_projeto.strftime("%m")}#{self.data_do_projeto.strftime("%Y")}#{proximo_numero.to_s.rjust(4, '0')}/#{self.sigla_da_modalidade}")
				end
			end
		end
	end

	def reatribuir_numeracao_lotes
		proximo_numero = 1
		lotes.ativos.order(:numero).each do |lote|
			lote.update_column(:numero, proximo_numero)
			proximo_numero += 1
		end
	end

	def update_dados_do_sim
		valida_campos_do_sim
		if errors.any?
			false
		else
			self.update_columns(data_de_envio_pro_sim: self.data_de_envio_pro_sim, data_de_autuacao: self.data_de_autuacao, agente_publico_municipal_id: self.agente_publico_municipal_id, data_do_edital: self.data_do_edital, numero_do_edital: self.numero_do_edital, responsavel_cotacao_sim_id: self.responsavel_cotacao_sim_id, responsavel_elaboracao_sim_id: self.responsavel_elaboracao_sim_id, tipo_de_disputa_sim: self.tipo_de_disputa_sim, forma_de_contratacao_sim: self.forma_de_contratacao_sim, url_do_processo_eletronico: self.url_do_processo_eletronico, pncp_id: self.pncp_id.sim_descricao.delete('-/"'), pncp_id_ata_sim: self.pncp_id_ata_sim.sim_descricao.delete('-/"'))
			preencher_configuracao_do_sim
			true
		end
	end

	def nao_envia_para_sim
		self.update_columns(envia_pro_sim: false, data_de_envio_pro_sim: nil, agente_publico_municipal_id: nil)
	end

	# TCM
	def to_sim
		begin
			nome_da_prefeitura = Configuracao.last.nome_da_prefeitura
			exercicio = "Exercício de " + orcamento.exercicio.to_s
			estado = "Estado do " + Configuracao.last.estado.nome
			motivo_escolha_fornecedor = "O fornecedor beneficiado era o único que atendia aos Administrativo para Aquisição de critérios estabelecidos."
			justificativa_do_pedido = (pedido.justificativa.nil? ? "" : pedido.justificativa)
			comissao.valida_gestor_da_unidade
			pedido.unidade_orcamentaria.valida_gestor_da_unidade
			valida_data_de_autuacao
			texto = ""
			if self.parceria_osc?
				texto << "531".to_s.sim_preenche(3) + ","
				texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + ","
				texto << data_de_autuacao.sim_data + ","
				texto << numero_do_processo.sim_limite(15) + ","
				texto << sigla_da_modalidade_do_processo.sim_preenche(1) + ","
				texto << pedido.unidade_orcamentaria.unidade_gestora.gestores.atual.cpf.sim_preenche(11) + ","
				texto << pedido.unidade_orcamentaria.unidade_gestora.gestores.atual.nome.sim_limite(40) + ","
				texto << data_da_homologacao.sim_data + ","
				texto << comissao.unidade_gestora.gestores.atual.cpf.sim_preenche(11) + ","
				texto << comissao.data_de_criacao.to_date.sim_data + ","
				texto << comissao.numero.sim_preenche(2) + ","
				texto << sim_justificativa_parceria.gsub(/["\r\n]/, "").sim_limite(255) + ","
			else
				valida_responsavel_juridico
				texto << "501".to_s.sim_preenche(3) + "," #1
				texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + "," #2
				texto << data_de_autuacao.sim_data + "," #3
				texto << numero_do_processo.sim_limite(15) + "," #4
				texto << sigla_da_modalidade_do_processo.sim_preenche(1) + "," #5
				texto << pedido.objeto.gsub(/["\r\n]/, "").sim_limite(510) + "," #6
				texto << format("%.2f", valor_estimado_global.to_f.round(2)) + "," #7
				texto << (agente_publico_municipal.nil? ? "".sim_preenche(11) : agente_publico_municipal.cpf.sim_preenche(11)) + "," #8
				texto << (agente_publico_municipal.nil? ? "".sim_limite(40) : agente_publico_municipal.nome.sim_limite(40)) + "," #9
				texto << comissao.unidade_gestora.gestores.atual.cpf.sim_preenche(11) + "," #10
				texto << comissao.data_de_criacao.to_date.sim_data + "," #11
				texto << comissao.numero.sim_preenche(2) + "," #12
				texto << pedido.unidade_orcamentaria.unidade_gestora.gestores.atual.cpf.sim_preenche(11) + "," #13
				texto << pedido.unidade_orcamentaria.unidade_gestora.gestores.atual.nome.sim_limite(40) + "," #14
				texto << data_da_homologacao.sim_data + "," #15
				texto << ((self.processo_licitatorio? && !self.carona? && !pedido.projeto_simplificado? && !self.contratacao_consultoria_individual?) ? horario_da_abertura.sim_preenche(5) : "".sim_limite(1)) + "," #16
				texto << ((self.processo_licitatorio? && !self.carona? && !pedido.projeto_simplificado? && !self.contratacao_consultoria_individual?) ? data_da_sessao.sim_data : "0") + "," #17
				texto << sim_modalidade_da_licitacao.sim_preenche(1) + "," #18
				texto << sim_criterio_de_julgamento.sim_preenche(1) + "," #19
				texto << "0.00" + "," #20
				texto << (self.processo_licitatorio? && !sim_registro_de_preco? ? "".sim_limite(1) : justificativa_do_pedido.gsub(/["\r\n]/, "").sim_limite(510)) + "," #21
				texto << ((self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?) ? motivo_escolha_fornecedor.gsub(/["\r\n]/, "").sim_limite(255) : "".sim_limite(1)) + "," #22 esse campo deve ser o motivo da escolha do fornecedor quando dispensa
				texto << ((self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?) ? legislacao.titulo.gsub(/["\r\n]/, "").squish.sim_limite(255) : "".sim_limite(1)) + "," #23
				texto << ((self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao? || sim_registro_de_preco?) ? (pedido.unidade_orcamentaria.nome + ", " + nome_da_prefeitura + ", " + estado + ", " + exercicio).gsub(/["\r\n]/, "").sim_limite(255) : "".sim_limite(1)) + "," #24
				texto << self.data_de_envio_pro_sim.sim_data.first(6) + "," #25
				texto << (self.responsavel_cotacao_sim.cpf.to_s.sim_limite(11) rescue "") + "," #26
				texto << (self.responsavel_cotacao_sim.nome.to_s.sim_limite(40) rescue "") + "," #27
				texto << (self.responsavel_elaboracao_sim.cpf.to_s.sim_limite(11) rescue "") + "," #28
				texto << (self.responsavel_elaboracao_sim.nome.to_s.sim_limite(40) rescue "") + "," #29
				texto << (self.read_attribute_before_type_cast(:forma_de_contratacao_sim).sim_limite(1) rescue "") + "," #30
				texto << (self.read_attribute_before_type_cast(:tipo_de_disputa_sim).sim_limite(1) rescue "") + "," #31
				texto << (self.eletronico? ? self.url_do_processo_eletronico.to_s : "").sim_limite(50) + "," #32
				texto << (self.registro_de_preco? ? "S" : "N").sim_limite(1) + "," #33
				texto << (self.pncp_id.sim_limite(25) rescue '""') + "," #34
				texto << (self.pncp_id_ata_sim.sim_limite(31) rescue '""') #35
			end

			return texto
		rescue => e
			if e.class.to_s == "NoMethodError"
				atributo_falho = e.message.split(" ")[2]
				coluna = CSV.parse(texto, :headers => false).last.count
				raise e.mensagem_traduzida(self, self.numero_do_processo, atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def sigla_da_modalidade
		if self.dispensa_de_licitacao?
			abreviacao = "DL"
		elsif self.inexigibilidade_de_licitacao?
			abreviacao = "INX"
		else
			abreviacao = case self.modalidade_de_licitacao
				when "convite" then "C"
				when "tomada_de_precos" then "TP"
				when "concorrencia_publica" then "CP"
				when "pregao_presencial" then "PP"
				when "pregao_eletronico" then "PE"
				when "rdc" then "RD"
				when "chamamento_publico" then "PC"
				when "chamada_publica" then "PC"
				when "dispensa_de_chamamento" then "PD"
				when "inexigibilidade_de_chamamento" then "PI"
				when "carona" then "CA"
				when "contratacao_consultoria_individual" then "CCI"
				else " "
			end
		end
		return abreviacao
	end

	def sigla_da_modalidade_do_processo
		if self.carona?
			return "R"
		elsif self.processo_licitatorio? && !self.sbqc? && !self.contratacao_consultoria_individual?
			return "N"
		elsif self.dispensa_de_licitacao? || self.dispensa_de_chamamento?
			return "D"
		elsif self.inexigibilidade_de_licitacao? || self.inexigibilidade_de_chamamento?
			return "I"
		elsif self.chamamento_publico?
			return "C"
		else
			return"P"
		end
	end

	def sim_modalidade_da_licitacao
		codigo = case self.modalidade_de_licitacao
			when "convite" then "1"
			when "tomada_de_precos" then "2"
			when "carona" then "2"
			when "concorrencia_publica" && !self.sbqc? then "3"
			when "concurso" then "4"
			when "pregao_presencial" then "6"
			when "pregao_eletronico" then "6"
			when "rdc" then "7"
			when "dispensa_ou_inexigibilidade" then "9"
			else "9"
		end
	end

	def sim_criterio_de_julgamento
		if self.processo_licitatorio?
			codigo = case self.criterio_de_julgamento
				when "menor_preco" then "1"
				when "melhor_tecnica" then "2"
				when "tecnica_e_preco" then "3"
				when "maior_desconto" then "5"
				when "melhor_tecnica_ou_conteudo_artistico" then "8"
				else "9"
			end
		else
			"9"
		end
	end

	def sim_justificativa_parceria
		justificativa = case self.modalidade_de_licitacao
			when "chamamento_publico" then "Art. 24 da Lei 13.019 de 31 de julho de 2014"
			when "dispensa_de_chamamento" then "Art. 30 da Lei 13.019 de 31 de julho de 2014"
			when "inexigibilidade_de_chamamento" then "Art. 31 da Lei 13.019 de 31 de julho de 2014"
			else " "
		end
	end

	def sim_registro_de_preco?
		return true if carona?

		registro_de_preco?
	end

	def valores_de_dotacoes_correspondem_ao_valor_estimado
		#TODO: TESTAR ESSE MÉTODO, INCLUSIVE O GUARD
		valor_total_das_dotacoes.to_f.round(2) == valor_estimado_global.to_f.round(2)
	end

	def qtd_de_unidades_convidadas_sem_dotacao
		qtd_sem_dotacao = 0
			unidades_orcamentarias_por_pedido.where.not(unidade_orcamentaria_id: pedido.unidade_orcamentaria_id).each do |unidade_orcamentaria_por_pedido|
				if dotacoes_da_unidade(unidade_orcamentaria_por_pedido.unidade_orcamentaria).empty?
					qtd_sem_dotacao = 1
				end
			end
		return qtd_sem_dotacao
	end

	def pode_imprimir_autorizacao?
		self.registro_de_preco? ? true : self.unidade_principal_contem_dotacao?
	end


	def deleta_lotes
		self.lotes.destroy_all
	end

	def define_o_sim_da_dispensa
		configuracao = Configuracao.last
		self.envia_pro_sim = configuracao.try(:mandar_dispensa_art_75_i_e_ii_ao_sim) || configuracao.try(:mandar_dispensa_art_24_i_e_ii_ao_sim)
	end

	def responsavel_no_periodo
		pedido.unidade_orcamentaria.ordenadores_de_despesas_ativos(data_do_projeto).last.agente_publico rescue nil
	end

	def nome_do_responsavel
		responsavel_no_periodo.nil? ? 'Sem responsável' : responsavel_no_periodo.nome
	end

	def sim_esta_valido?
		!self.envia_pro_sim? || ( self.envia_pro_sim? && possui_dados_do_sim? )
	end

	def dotacoes_estao_validas?
		( (!precisa_de_dotacao? && !contem_dotacoes? ) || ( dotacao_completa? && valores_de_dotacoes_correspondem_ao_valor_estimado ) )
	end

	def algum_licitante_preencheu_a_proposta_final?
		self.pessoas_do_projeto.any?{ |pessoa_do_projeto| pessoa_do_projeto.proposta_final > 0 }
	end

	def responsavel_no_periodo
		pedido.unidade_orcamentaria.ordenadores_de_despesas_ativos(data_do_projeto).last.agente_publico rescue nil
	end

	def nome_do_responsavel
		responsavel_no_periodo.nil? ? 'Sem responsável' : responsavel_no_periodo.nome
	end

	def inciso_permite_gerar_da_dispensa?
		legislacao.try(:eh_artigo_75_inciso_i?) || legislacao.try(:eh_artigo_75_inciso_ii?) ||
		legislacao.try(:eh_artigo_24_inciso_i?) || legislacao.try(:eh_artigo_24_inciso_ii?)
	end

	private
		# AASM
		def altera_lotes_desertos
			self.lotes.ativo.each do |lote|
				unless lote.ganhador.present?
					lote.deserto!
				end
			end
		end

		def setar_data_inicial_do_processo
			self.data_inicial_do_processo = Date.today
			self.save(validate: false)
		end

		def seta_data_homologacao_do_processo
			self.data_da_homologacao = Date.today
			self.save(validate: false)
		end

		def seta_data_de_adjudicacao_do_processo
			self.data_de_adjudicacao = Date.today
			self.save(validate: false)
		end

		def cria_parecer_com_status_pendente
			parecer = self.documentos_do_processo.new(tipo_de_documento: "parecer", status_parecer: "pendente", data_do_documento: Date.today, titulo_personalizado: "Parecer")
			parecer.save(validate: false)
		end

		def cria_parecer_com_status_enviado_ao_setor_juridico
			parecer = self.documentos_do_processo.new(tipo_de_documento: "parecer", status_parecer: "enviado_ao_setor_juridico", data_do_documento: Date.today, titulo_personalizado: "Parecer")
			parecer.save(validate: false)
		end

		# Callbacks
		def verifica_se_o_projeto_esta_andamento
			unless self.pode_deletar?
				raise Exception.new("Não é possivel deletar um projeto nessa etapa.")
				return false
			end
		end

		def retorna_status_do_pedido
			self.pedido.status = "aberto"
			self.pedido.save(validate: false)
		end

		def nao_envia_pro_sim
			self.envia_pro_sim = false
			nil
		end

		def marca_como_menor_valor
			self.tipo_de_totalizacao = "menor_valor"
			nil
		end

		def criar_lote_inicial
			if self.por_item?
				self.pedido.itens_do_pedido.where(valido: true).each do |item_do_pedido|
					criterio_de_julgamento = if self.melhor_tecnica? || self.tecnica_e_preco?
						self.melhor_tecnica? ? 'melhor_tecnica' : 'tecnica_e_preco'
					else
						item_do_pedido.por_preco? ? 'menor_preco' : 'maior_desconto'
					end
					tipo_produto_servico = (item_do_pedido.item.categoria.try(:codigo) == "36" || item_do_pedido.item.categoria.try(:servico?)) ? 1 : 0
					lote = self.lotes.build(criterio_de_julgamento: criterio_de_julgamento, tipo: tipo_produto_servico)
					lote.itens_do_lote.build(item_do_pedido: item_do_pedido)
				end
			else
				if self.pedido.contem_itens_por_preco?
					lote = self.lotes.build
					self.pedido.itens_do_pedido.where(valido: true, tipo: 0).each do |item_do_pedido|
						if Configuracao.last.ordencacao_de_itens_pela_sequencia?
							lote.itens_do_lote.build(item_do_pedido: item_do_pedido, sequencia: item_do_pedido.sequencia, ordem: item_do_pedido.sequencia)
						else
							lote.itens_do_lote.build(item_do_pedido: item_do_pedido)
						end
						lote.criterio_de_julgamento = self.criterio_de_julgamento if self.criterio_de_julgamento.present?
						if self.criterio_de_julgamento.present?
							lote.criterio_de_julgamento = self.criterio_de_julgamento
						else
							lote.criterio_de_julgamento = 'menor_preco'
						end
					end
				end

				if self.pedido.contem_itens_por_desconto?
					lote = self.lotes.build
					self.pedido.itens_do_pedido.where(valido: true, tipo: 1).each do |item_do_pedido|
						if Configuracao.last.ordencacao_de_itens_pela_sequencia?
							lote.itens_do_lote.build(item_do_pedido: item_do_pedido, sequencia: item_do_pedido.sequencia, ordem: item_do_pedido.sequencia)
						else
							lote.itens_do_lote.build(item_do_pedido: item_do_pedido)
						end
						lote.criterio_de_julgamento = 'maior_desconto'
					end
				end
			end

			unless Rails.env.test?
				itens_dos_lotes = self.lotes.map { |lote| lote.itens_do_lote }.flatten
				itens_dos_lotes.group_by { |item_do_lote| [item_do_lote.item_do_pedido.por_valor_previsto, item_do_lote.item_do_pedido.tipo] }.each do |agrupamento|
					itens_agrupados = agrupamento[1]
					atributos_do_lote = agrupamento[1].last.lote.attributes.reject{ |atributo| atributo == "id" || atributo == "created_at" || atributo == "updated_at" }
					tipo_de_agrupamento = agrupamento[0].include?(true) ? "#{agrupamento[0][1]}_e_valor_previsto" : "#{agrupamento[0][1]}_e_quantidade"

					if self.por_item?
						itens_agrupados.each do |item_do_lote|
							novo_lote = Licitacao::Lote.create!(atributos_do_lote.merge(tipo_de_agrupamento: tipo_de_agrupamento))
							novo_lote.itens_do_lote.create(item_do_lote.attributes.reject{ |atributo| atributo == "id" || atributo == "created_at" || atributo == "updated_at" })
						end
					else
						novo_lote = Licitacao::Lote.create!(atributos_do_lote.merge(tipo_de_agrupamento: tipo_de_agrupamento))
						itens_agrupados.each do |item_do_lote|
							novo_lote.itens_do_lote.create(item_do_lote.attributes.reject{ |atributo| atributo == "id" || atributo == "created_at" || atributo == "updated_at" })
						end
					end
				end
			else
				self.lotes.each do |lote|
					lote.save()
				end
			end

			lotes.reload
		end

		def preencher_configuracao_do_sim
			configuracao = Licitacao::ConfiguracaoSimDoProjeto.where(projeto_id: self.id, arquivo_id: nil)

			if configuracao.any? && configuracao.last.arquivo_id.nil?
				configuracao.last.update_column('data_de_envio', self.data_de_envio_pro_sim)
			else
				Licitacao::ConfiguracaoSimDoProjeto.create(projeto_id: self.id, data_de_envio: self.data_de_envio_pro_sim, primeiro_envio: true)
			end
		end

		def preencher_arquivo_id
			configuracao = Licitacao::ConfiguracaoSimDoProjeto.find_by(projeto_id: self.id)

			if configuracao.any?
				Licitacao::ConfiguracaoSimDoProjeto.update_column('arquivo_id', self.arquivo_id)
			else
				Licitacao::ConfiguracaoSimDoProjeto.create(projeto_id: self.id, data_de_envio: self.data_de_envio, primeiro_envio: true, arquivo_id: self.arquivo_id)
			end
		end

		def criar_cotacoes
			pedido.pessoas_do_pedido.validos.each do |pessoa_do_pedido|
				if (global? && pessoa_do_pedido.cotou_todos_itens?) || (!global? && pessoa_do_pedido.cotado?)
					pessoa_do_projeto = pessoas_do_projeto.create!(
						pessoa_id: pessoa_do_pedido.pessoa.id,
						cpf_do_responsavel: pessoa_do_pedido.cpf_do_responsavel,
						nome_do_responsavel: pessoa_do_pedido.nome_do_responsavel,
						tipo_de_responsavel: pessoa_do_pedido.tipo_de_responsavel
					)

					itens_do_lote.validos.each do |item_do_lote|
						ipp = pessoa_do_pedido.itens_do_pedido_por_pessoa.validos.find_by(item_do_pedido: item_do_lote.item_do_pedido.id)
						ipp.marca = '-' if ipp.present? && ipp.marca.blank?
						pessoa_do_projeto.itens_do_projeto_por_pessoa.create!( item_do_lote_id: item_do_lote.id, marca: ipp.marca, preco: ipp.preco_de_cotacao ) if ipp
					end
				end
			end
		end

		def define_ganhador
			#para dispensa ou inexigibilidade ou convite o agrupamento sempre é por item, ou seja, o ganhador é por item específico
			lotes.reload.each do |lote|
				if lote.itens_do_projeto_por_pessoa.iniciais.validos.any?
					if lote.primeiro_colocado.present?
						primeiro_colocado = lote.primeiro_colocado
						lote.update(ganhador_id: primeiro_colocado[:pessoa_do_projeto].try(:id))
						lote.cria_proposta_final
					end
				end
			end
		end

		def redefinir_forma_de_agrupamento
			ActiveRecord::Base.transaction do
				begin
					#deleta os pessoas_do_projeto e lotes antigos
					pessoas_do_projeto.destroy_all
					lotes.destroy_all
					self.update_column(:forma_de_agrupamento, self.forma_de_agrupamento)
					#cria novamente
					criar_lote_inicial
					if pode_criar_cotacoes_e_definir_ganhador?
						criar_cotacoes
						define_ganhador
					end
				rescue => e
					errors.add(:base, e.message)
					raise
					raise ActiveRecord::Rollback, "Alguns erros foram encontrados."
				end
			end
		end

		# VALIDAÇÔES
		def valida_campos_do_sim
			errors.add(:data_de_envio_pro_sim, "não pode ficar em branco") if self.data_de_envio_pro_sim.blank?
			errors.add(:data_de_autuacao, "não pode ficar em branco") if self.data_de_autuacao.blank?
			errors.add(:agente_publico_municipal_id, "não pode ficar em branco") if self.agente_publico_municipal_id.blank? && !self.parceria_osc?
			errors.add(:data_do_edital, "não pode ficar em branco") if self.data_do_edital.blank? && self.parceria_osc?
			errors.add(:numero_do_edital, "não pode ficar em branco") if self.numero_do_edital.blank? && self.parceria_osc?
			errors.add(:responsavel_cotacao_sim_id, "não pode ficar em branco") if self.responsavel_cotacao_sim_id.blank?
			errors.add(:responsavel_elaboracao_sim_id, "não pode ficar em branco") if self.responsavel_elaboracao_sim_id.blank?
			errors.add(:tipo_de_disputa_sim, "não pode ficar em branco") if self.tipo_de_disputa_sim.blank?
			errors.add(:forma_de_contratacao_sim, "não pode ficar em branco") if self.forma_de_contratacao_sim.blank?
			errors.add(:url_do_processo_eletronico, "não pode ficar em branco") if self.eletronico? && self.url_do_processo_eletronico.blank?
			errors.add(:url_do_processo_eletronico, "URL Inválida") if self.eletronico? && !self.url_do_processo_eletronico.blank? && !url_valida?(url_do_processo_eletronico)
			errors.add(:pncp_id, "Inválido") if !self.pncp_id.blank? && self.pncp_id.sim_descricao.delete('-/"').size != 25
			errors.add(:pncp_id_ata_sim, "Inválido") if !self.pncp_id_ata_sim.blank? && self.pncp_id_ata_sim.sim_descricao.delete('-/"').size != 31

			#verifica se já tem lote gerado para a data de envio pro sim informada
			lote_gerado = lote_gerado_para_o_mes_de_referencia(self.data_de_envio_pro_sim)
			errors.add(:data_de_envio_pro_sim, "Já existe geração do lote do SIM para: #{lote_gerado.exercicio_e_nome_do_mes}") if lote_gerado.present?
		end

		def pedido_deve_estar_fechado
			errors.add(:pedido_id, "Deve estar fechado") unless pedido && (pedido.fechado? || pedido.projeto_gerado?)
		end

		def numero_do_processo_confirmado_deve_ser_unico
			errors.add(:numero_do_processo, "Deve ser único") if !processo_eh_unico? (numero_do_processo)
		end

		# Validação removida a pedido da equipe de consultoria
		def nao_pode_ser_dispensa_ou_inexigibilidade_se_contem_unidades_convidadas
			errors.add(:modalidade_de_licitacao, "Não pode ser dispensa ou inexigibilidade quando contém mais de uma unidade") if dispensa_ou_inexigibilidade? && pedido.contem_unidades_convidadas?
		end

		def valida_registro_de_preco
			modalidades_de_licitacao_validas = ["pregao_presencial","pregao_eletronico","concorrencia_publica", "carona", "dispensa_ou_inexigibilidade" ]
			
			if registro_de_preco?
				unless modalidades_de_licitacao_validas.include? self.modalidade_de_licitacao.to_s
					errors.add(:registro_de_preco, "Registro de preço só pode ser marcado para Pregão Presencial, Pregão Eletrônico, Concorrência Pública, Dispensa ou Carona")
				end
			end
		end

		def valida_criterio_de_julgamento_do_pregao
			if (self.pregao_eletronico? || self.pregao_presencial?) && self.criterio_de_julgamento.present? && (self.criterio_de_julgamento != "menor_preco" && self.criterio_de_julgamento != "maior_desconto")
				errors.add(:criterio_de_julgamento, "Para a modalidade de pregão critério de julgamento deve ser menor preço ou maior desconto")
			end
		end

		def data_do_projeto_deve_ser_maior_ou_igual_a_data_do_pedido
			if self.pedido.present? && self.data_do_projeto.present?
				errors.add(:data_do_projeto, "Data do projeto deve ser igual ou maior a data do pedido") if self.data_do_projeto.to_date < self.pedido.data_do_pedido.to_date
			end
		end

		def valida_forma_de_agrupamento_para_desconto
			if self.pedido != nil && self.pedido.contem_itens_por_preco_e_desconto_ao_mesmo_tempo? && self.global?
				errors.add(:forma_de_agrupamento, "não pode ser global pois existem itens no pedido com tipos diferente (por preço e por desconto)")
			end
			if self.pedido != nil && self.pedido.contem_itens_por_desconto? && !self.pedido.contem_itens_por_preco? && (self.global? || self.por_lote?)
				errors.add(:forma_de_agrupamento, "Para itens com desconto selecione o agrupamento 'por item'")
			end
		end

		def modalidade_da_licitacao_para_modalidade_do_processo
			if self.modalidade_do_processo.present? && self.modalidade_de_licitacao.present?
				if (self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?) && !self.dispensa_ou_inexigibilidade?
					errors.add(:modalidade_de_licitacao, "Deve ser selecionado 'não se aplica' para dispensa ou inexigibilidade")
				end

				if self.processo_licitatorio? && self.dispensa_ou_inexigibilidade?
					errors.add(:modalidade_de_licitacao, "Deve ser selecionado uma modalidade quando escolhido processo licitatório")
				end
			end
		end

		def modalidade_da_licitacao_para_sbqc
			if self.sbqc && !self.concorrencia_publica?
				errors.add(:modalidade_de_licitacao, "Para regras própias de organismos internacionais, deve ser um Processo Licitatório com a modalidade Concorrência Pública")
			end
		end

		def forma_de_agrupamento_para_dispensa_ou_inexibilidade
			if pedido && !pedido.projeto_simplificado? && eh_dispensa_ou_inexigibilidade?
				if self.global? && !pedido.possui_fornecedor_com_todos_os_itens_cotados?
					errors.add(:forma_de_agrupamento, "Para dispensa ou inexibilidade que não há fornecedor com cotação para todos os itens, deve ser 'por item'.")
				end
			end
		end

		def forma_de_agrupamento_para_carona
			if pedido && !pedido.projeto_simplificado? && self.carona?
				if !self.por_item? && !self.global?
					errors.add(:forma_de_agrupamento, "Para carona deve ser 'por item' ou 'global'")
				end
			end
		end

		def forma_de_agrupamento_para_convite
			if pedido && !pedido.projeto_simplificado? && self.convite? && !self.por_item?
				errors.add(:forma_de_agrupamento, "Para convite deve ser 'por item'")
			end
			if pedido && !pedido.projeto_simplificado? && self.contratacao_consultoria_individual? && !self.por_item?
				errors.add(:forma_de_agrupamento, "Para contratação de consultoria individual deve ser 'por item'")
			end
		end

		# Foi removida para poder cadastrar Dispensa maior desconto
		# def criterio_de_julgamento_para_dispensa_ou_inexibilidade
		# 	if pedido && !pedido.projeto_simplificado? && (self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?) && self.criterio_de_julgamento.present? && self.criterio_de_julgamento != "menor_preco"
		# 		errors.add(:criterio_de_julgamento, "Para dispensa ou inexibilidade deve ser menor preço")
		# 	end
		# end

		def tipo_de_totalizacao_para_dispensa_ou_inexibilidade
			unless self.lei_14133_21?
				if pedido && !pedido.projeto_simplificado? && (self.dispensa_de_licitacao? || self.inexigibilidade_de_licitacao?) && !self.menor_valor?
					errors.add(:tipo_de_totalizacao, "Para dispensa ou inexibilidade deve ser menor preço")
				end
			end
		end

		def valida_data_da_sessao
			if self.lei_14133_21? && self.dispensa_de_licitacao?
				data_da_sessao_maior_que_publicacao(3)
			elsif self.lei_14133_21? && (self.pregao_eletronico? || self.pregao_presencial?)
				if self.tem_lote_de_servico? #se for de serviço
					data_da_sessao_maior_que_publicacao(10)
				else
					data_da_sessao_maior_que_publicacao(8)
				end
			elsif self.pregao_eletronico? || self.pregao_presencial? # 4 dias úteis durante a lei do COVID depois volta pra 8
				data_da_sessao_maior_que_publicacao(4)
			elsif (self.convite? || self.contratacao_consultoria_individual?) # 5 dias úteis
				data_da_sessao_maior_que_publicacao(5)
			elsif self.tomada_de_precos?
				if self.melhor_tecnica? || self.tecnica_e_preco? # 30 dias corridos
					data_da_sessao_maior_que_publicacao_corridos(30)
				else # Demais casos = 15 dias corridos
					data_da_sessao_maior_que_publicacao_corridos(15)
				end
			elsif self.concorrencia_publica?
				if self.melhor_tecnica? || self.tecnica_e_preco? # 45 dias corridos
					data_da_sessao_maior_que_publicacao_corridos(45)
				else # Demais casos = 30 dias corridos
					data_da_sessao_maior_que_publicacao_corridos(30)
				end
			elsif self.concurso? # 45 dias corridos
				data_da_sessao_maior_que_publicacao_corridos(45)
			else
				if data_da_sessao < publicacoes.last.data_da_publicacao
					errors.add(:data_da_sessao, "Data da sessão deve ser maior ou igual à data de publicação")
				end
			end
		end

		def data_da_sessao_maior_que_publicacao(dias_uteis)
			if data_da_sessao < (dias_uteis.business_day.after(publicacoes.last.data_da_publicacao))
				errors.add(:data_da_sessao, "Data da sessão deve ter #{dias_uteis} dias úteis a mais do que à data de publicação")
			end
		end

		def data_da_sessao_maior_que_publicacao_corridos(dias_corridos)
			if (data_da_sessao - publicacoes.last.data_da_publicacao).to_i < dias_corridos
				errors.add(:data_da_sessao, "Data da sessão deve ter #{dias_corridos} dias corridos a mais do que à data de publicação") unless self.sbqc?
			end
		end

		def numero_do_processo_nao_atualiza_se_tiver_publicacoes
			if possui_publicacao?
				errors.add(:numero_do_processo, "Número do processo só pode ser editado se não houver publicações.")
			end
		end

		def valida_data_de_autuacao
			if self.data_de_autuacao.blank?
				raise "Não existe data de autuação para o processo: " << "#{self.numero_do_processo}" << " (id: " << "#{self.id.to_s})"
			end
		end

		def valida_responsavel_juridico
			if self.agente_publico_municipal.nil?
				raise "Não existe Responsável Jurídico para o processo: " << "#{self.numero_do_processo}"
			end
		end

		def valida_exercicio_pelo_pedido
			if self.data_do_projeto && !importado_do_tcm?
				if self.orcamento.exercicio < self.pedido.orcamento.exercicio
						errors.add(:base, "Exercício do projeto deve ser o mesmo do pedido ou superior.")
				end
			end
		end

	def url_valida?(url)
		regex = /\Awww\..+\.(com|br)\z/
		!!(url =~ regex)
	end
	def validate_comissao
		unless self.comissao.present?
			errors.add(:comissao_id, "Nenhuma comissão foi selecionada! Por favor, selecione uma comissão!")
			throw(:abort)
		end
	end

		# Aguardando definições de Obras e Serviços de Engenharia de acordo com a Categoria do Pedido
		def valida_valor_orcamentario
			# if self.pedido.obras? || self.pedido.servicos_de_engenharia?
			# 	if self.dispensa_de_licitacao?
			# 		errors.add(:modalidade_do_processo, "O Valor Total excedeu o limite para a modalidade de Dispensa, que deve ser até R$ 15.000,00 (quinze mil reais) para Obras ou Serviços de Engenharia.") if self.pedido.menor_cotacao_dos_itens > 15000
			# 	elsif self.convite?
			# 		errors.add(:modalidade_de_licitacao, "O Valor Total excedeu o limite para a modalidade de Convite, que deve ser até R$ 150.000,00 (cento e cinquenta mil reais) para Obras ou Serviços de Engenharia.") if self.pedido.menor_cotacao_dos_itens > 150000
			# 	elsif self.tomada_de_precos?
			# 		errors.add(:modalidade_de_licitacao, "O Valor Total excedeu o limite para a modalidade de Tomada de Preços, que deve ser até R$ 1.500.000,00 (um milhão e quinhentos mil reais) para Obras ou Serviços de Engenharia.") if self.pedido.menor_cotacao_dos_itens > 1500000
			# 	elsif self.concorrencia_publica?
			# 		errors.add(:modalidade_de_licitacao, "O Valor Total não atingiu o limite para a modalidade de Concorrência, que deve ser acima de R$ 1.500.000,00 (um milhão e quinhentos mil reais) para Obras ou Serviços de Engenharia.") if self.pedido.menor_cotacao_dos_itens < 1500000
			# 	end
			# else
			# 	if self.dispensa_de_licitacao?
			# 		errors.add(:modalidade_do_processo, "O Valor Total excedeu o limite para a modalidade de Dispensa, que deve ser até R$ 8.000,00 (oito mil reais) para demais compras e serviços.") if self.pedido.menor_cotacao_dos_itens > 8000
			# 	elsif self.convite?
			# 		errors.add(:modalidade_de_licitacao, "O Valor Total excedeu o limite para a modalidade de Convite, que deve ser até R$ 80.000,00 (oitenta mil reais) para demais compras e serviços.") if self.pedido.menor_cotacao_dos_itens > 80000
			# 	elsif self.tomada_de_precos?
			# 		errors.add(:modalidade_de_licitacao, "O Valor Total excedeu o limite para a modalidade de Tomada de Preços, que deve ser até R$ 650.000,00 (seiscentos e cinquenta mil reais) para demais compras e serviços.") if self.pedido.menor_cotacao_dos_itens > 650000
			# 	elsif self.concorrencia_publica?
			# 		errors.add(:modalidade_de_licitacao, "O Valor Total não atingiu o limite para a modalidade de Concorrência, que deve ser acima de R$ 650.000,00 (seiscentos e cinquenta mil reais) para demais compras e serviços.") if self.pedido.menor_cotacao_dos_itens < 650000
			# 	end
			# end
		end
end
