class Contabilidade::Obra < ApplicationRecord
	include TradutorConcern
	include MensagemConcern
	has_paper_trail
	include GeradorDeEventosContabeis

	attr_accessor :mesmo_contrato
	attr_accessor :formulario_de_estudos

	attr_default :abrangencia, false
	attr_default :possui_garantia, false
	attr_default :possui_estudos_projetos, false
	attr_default :envia_pro_sim, false
	attr_default :valor_estudos, 0.00

	belongs_to :orcamento, required: true
	belongs_to :tipo_de_administracao, required: true, class_name: 'Base::TipoDeAdministracao'
	belongs_to :contrato, class_name: 'Licitacao::Contrato', required: true
	belongs_to :contrato_estudos, class_name: 'Licitacao::Contrato', foreign_key: 'contrato_estudos_id'
	belongs_to :cidade, class_name: 'Base::Cidade'
	belongs_to :classificacao_do_bem, class_name: 'Contabilidade::Conta', foreign_key: "conta_id"
	belongs_to :conta_pcasp, class_name: 'Contabilidade::Conta', foreign_key: 'conta_pcasp_id'
	belongs_to :arquivo, class_name: 'Tcm::Arquivo', required: false

	has_many :medicoes_da_obra, dependent: :restrict_with_exception
	has_many :engenheiros_da_obra, dependent: :restrict_with_exception
	has_many :empresas_da_obra, dependent: :restrict_with_exception
	has_many :situacoes_da_obra, dependent: :destroy
	has_many :ordens_de_servico, class_name: "Obra::OrdemDeServico", dependent: :restrict_with_exception
	has_many :documentos_da_obra, class_name: 'Obra::DocumentoDaObra', dependent: :destroy
	has_many :contratos_da_obra, class_name: 'Obra::ContratoDaObra', dependent: :destroy
	has_many :contratos, through: :contratos_da_obra, class_name: 'Licitacao::Contrato'
	has_many :contratados, through: :contratos, class_name: 'Licitacao::Contratado'
	has_many :fiscalizacoes, class_name: 'Obra::Fiscalizacao', dependent: :destroy
	has_many :verificacoes_da_fiscalizacao, through: :fiscalizacoes
	has_many :fotos_da_fiscalizacao, through: :fiscalizacoes
	has_many :anexos_da_fiscalizacao, through: :fotos_da_fiscalizacao
	has_many :garantias_da_obra, class_name: 'Obra::GarantiaDaObra', dependent: :destroy
	has_many :diarios_de_obra, class_name: 'Obra::DiarioDeObra', dependent: :destroy

	has_many :empenhos, through: :contratos, class_name: 'Contabilidade::Empenho'
	has_many :liquidacoes, through: :empenhos
	has_many :pagamentos, through: :liquidacoes
	has_many :contas_bancarias_por_pagamento, through: :pagamentos

	has_many :orcamentos_da_despesa, through: :empenhos, source: :orcamento_da_despesa
	has_many :fontes_de_recursos, through: :orcamentos_da_despesa, source: :fonte_de_recursos

	has_many :transferencias, class_name: 'Obra::Transferencia', dependent: :destroy
	has_many :operacoes_de_credito, class_name: "Obra::OperacaoDeCredito", dependent: :destroy

	has_many :servicos_da_obra, class_name: "Obra::ServicoDaObra", dependent: :destroy
	has_many :itens_do_servico_da_obra, through: :servicos_da_obra, class_name: "Obra::ItemDoServicoDaObra"

	accepts_nested_attributes_for :servicos_da_obra, reject_if: :all_blank, allow_destroy: true

	before_save :buscar_valor_do_contrato_estudos_e_projetos, if: Proc.new { self.contrato_estudos_id.present? && self.contrato_estudos_id != self.contrato_id }
	before_save :definir_data_sim

	before_create :atribui_proximo_codigo_disponivel, if: Proc.new { |objeto| objeto.codigo.nil? }

	after_create :cria_contrato_da_obra
	after_create :adiciona_empresa_do_contrato_nas_empresas_da_obra, if: Proc.new { contrato.present? }
	after_create :altera_status_da_obra
	after_create :verifica_se_obra_foi_classificada
	

	validates_presence_of :codigo, :contrato_id, :orcamento_id, :tipo_de_obra, :tipo_de_administracao_id, :numero_do_crea, :fonte_de_origem
	validates_presence_of :data_de_inicio, :data_prevista_de_termino, :descricao, :valor
	validates_presence_of :classificacao_do_bem, if: Proc.new { Configuracao.last.try(:utiliza_evento_contabil?) }
	validates_presence_of :contrato_estudos_id, on: :update, if: Proc.new { self.possui_estudos_projetos.present? && self.formulario_de_estudos.present? }
	validates_presence_of :valor_estudos, if: Proc.new {contrato_estudos_id.present?}
	validates_presence_of :conta_pcasp_id, if: Proc.new { uso_do_bem.present? }
	validates_presence_of :uso_do_bem, if: Proc.new {conta_pcasp_id.present? }
	validates_uniqueness_of :codigo, scope: :orcamento_id, case_sensitive: false, :unless => :codigos_sao_de_diferentes_tipos?, message: "Codigo já esá em uso"

	validates_uniqueness_of :contrato_id

	validates_length_of :codigo, maximum: 4
	validates_length_of :orgao_licenca, maximum: 80
	validates_length_of :tombo_do_terreno, :tombo_da_construcao, maximum: 20
	validates_length_of :licenca_ambiental, maximum: 12
	validates_length_of :cei, maximum: 12
	validates_length_of :numero_do_crea, maximum: 25
	validates_length_of :programa_de_trabalho, maximum: 20

	validates_length_of :apelido_da_obra, maximum: 100
	validates_length_of :numero_logradouro, maximum: 8
	validates_length_of :logradouro, maximum: 120
	validates_length_of :complemento, maximum: 80
	validates_length_of :bairro, maximum: 60

	validates_length_of :cep, is: 8, allow_blank: true

	validate :data_prevista_de_termino_nao_pode_ser_anterior_a_data_de_inicio_da_obra
	validate :data_de_inicio_e_termino_da_obra_deve_estar_entre_o_periodo_de_vigencia_do_contrato
	validate :data_da_licenca_deve_ser_antes_do_inicio_da_obra
	validate :valor_da_obra_nao_pode_ser_menor_que_o_valor_dos_servicos
	# validate :verifica_classificacao_do_bem_para_servico
	validate :valor_estudos_nao_pode_ser_maior_que_saldo_do_contrato, if: Proc.new { self.contrato_estudos_id_changed? && self.valor_estudos_changed? }

	validates_numericality_of :valor, greater_than: 0
	validates_numericality_of :valor_estudos, greater_than: 0, if: Proc.new {contrato_estudos_id.present?}

	validates :data_de_inicio, date: true
	validates :data_prevista_de_termino, date: true
	validates :data_da_licenca, date: { allow_blank: true }

	scope :concluidas_e_garantias_nao_devolvidas, -> { joins(:garantias_da_obra).where(obra_garantias_da_obra: {situacao: 1}) }

	enum fonte_de_origem: {
		origem_cef: 0,
		origem_bid: 1,
		origem_proprio: 2,
		origem_operacao_de_credito: 3,
		origem_convenio_estado: 4,
		origem_convenio_uniao: 5
	}

	enum fonte_de_contrapartida: {
		contrapartida_cef: 0,
		contrapartida_bid: 1,
		contrapartida_proprio: 2,
		contrapartida_operacao_de_credito: 3
	}

	enum tipo_de_obra: {
		obra: 1,
		servico: 2
	}

	enum uso_do_bem: {
		especial: 1,
		dominical: 2,
		comum_do_povo: 3
	}

	scope :iniciadas_e_nao_concluidas, -> { joins(:situacoes_da_obra).merge(Contabilidade::SituacaoDaObra.iniciadas_e_nao_concluidas).select(&:iniciada_e_nao_concluida?) }
	scope :paralisadas, -> { joins(:situacoes_da_obra).merge(Contabilidade::SituacaoDaObra.paralisadas).select(&:esta_paralisada?) }
	scope :concluidas, -> { joins(:situacoes_da_obra).merge(Contabilidade::SituacaoDaObra.concluidas).select(&:esta_concluida?) }
	scope :nao_iniciadas, -> { joins(:situacoes_da_obra).merge(Contabilidade::SituacaoDaObra.nao_iniciadas).select(&:nao_iniciada?) }

	def valor_da_obra_nao_pode_ser_menor_que_o_valor_dos_servicos
		errors.add(:base, "valor dos serviços #{valor_total_dos_servicos_da_obra.try(:real_contabil)} não podem ser maiores que o valor da obra #{contrato.valor_total_do_contrato.try(:real_contabil)}") if contrato.present? && valor_da_obra_menor_que_valor_dos_servicos?
	end

	def verifica_classificacao_do_bem_para_servico
		conta_pj = "332319900"
		conta_pf = "332219900"
		if self.servico?
			errors.add(:classificacao_do_bem, "A classificação deve ser para a conta PF: 3.3.2.2.1.99.00") if classificacao_do_bem.present? && classificacao_do_bem.codigo.eql?(conta_pj) && contrato.present? && contrato.pessoa.pessoa_fisica?
			errors.add(:classificacao_do_bem, "A classificação deve ser para a conta PJ: 3.3.2.3.1.99.00") if classificacao_do_bem.present? && classificacao_do_bem.codigo.eql?(conta_pf) && contrato.present? && contrato.pessoa.pessoa_juridica?
		end
	end

	def data_prevista_de_termino_nao_pode_ser_anterior_a_data_de_inicio_da_obra
		unless data_de_inicio.nil? || data_prevista_de_termino.nil?
			errors.add(:data_prevista_de_termino, "deve ser maior que a data de início da obra") if data_prevista_de_termino <= data_de_inicio
		end
	end

	def data_de_inicio_e_termino_da_obra_deve_estar_entre_o_periodo_de_vigencia_do_contrato
		unless data_de_inicio.nil? || data_prevista_de_termino.nil? || self.contrato_id.nil?
			if contrato.inicio_da_vigencia > data_de_inicio || contrato.data_final_de_acordo_com_aditivos < data_prevista_de_termino
				mensagem = "deve ser entre o período de vigência do contrato: #{contrato.inicio_da_vigencia} a #{contrato.data_final_de_acordo_com_aditivos}"
				errors.add(:data_prevista_de_termino, mensagem)
				errors.add(:data_de_inicio, mensagem)
			end
		end
	end

	def data_da_licenca_deve_ser_antes_do_inicio_da_obra
		unless data_da_licenca.nil? || data_de_inicio.nil?
			errors.add(:data_da_licenca, "deve ser menor que a data de início da obra") if data_da_licenca >= data_de_inicio
		end
	end

	def codigos_sao_de_diferentes_tipos?
		if self.codigo.present? && self.orcamento.present? && tipo_de_obra.present?
			obra_existente = Contabilidade::Obra.where(tipo_de_obra: self.tipo_de_obra, codigo: self.codigo, orcamento_id: self.orcamento_id).where.not(id: self.id)
			if obra_existente.present?
				return false
			elsif obra_existente.blank?
				return true
			end
		else
			return true
		end
	end

	def self.proximo_codigo_disponivel orcamento_id
		codigos_utilizados = where(orcamento_id: orcamento_id).order(:codigo).pluck(:codigo).map{ |codigo| codigo.to_i }
		return '0001' if codigos_utilizados.empty?
		codigos_disponiveis = (1..codigos_utilizados.last + 1).to_a - codigos_utilizados
		codigos_disponiveis.first.digitos(4)
	end

	def atribui_proximo_codigo_disponivel
		self.codigo = Contabilidade::Obra::proximo_codigo_disponivel orcamento_id if self.codigo.blank?
	end

	def update_data_de_envio_pro_sim(data)
		if data.blank?
			self.update_column(:data_de_envio_pro_sim, nil)
			errors.add(:data_de_envio_pro_sim, "não pode ficar em branco")
		else
			self.update_column(:data_de_envio_pro_sim, data.to_date)
		end
	end

	def enviado_ao_sim?
		arquivo_id.present? && arquivo_id > 0 && arquivo.lote.lote_processado_ou_enviado?
	end

	def cria_contrato_da_obra
		self.contratos_da_obra.create(contrato_id: contrato_id)
	end

	def altera_status_da_obra
		if !situacoes_da_obra.any?
			tipo_de_status = Contabilidade::SituacaoDaObra.tipos_de_status_da_obra[:nao_iniciada] #status: não iniciada
			situacacao_inicial_da_obra = situacoes_da_obra.create(data_da_situacao: self.data_de_inicio, tipo_de_status_da_obra: tipo_de_status, observacoes: self.descricao ) if tipo_de_status.present?
		end
	end

	def adiciona_empresa_do_contrato_nas_empresas_da_obra
		empresa_do_contrato_da_obra = self.empresas_da_obra.create(pessoa_id: contrato.contratado.pessoa.id)
		empresa_do_contrato_da_obra.save(validate: false)
	end

	def quantidade_de_convenios_e_operacoes_de_credito
		transferencias.convenio.count + operacoes_de_credito.count
	end

	def saldo_para_medicoes
		valor_total_atualizado.to_d - total_das_medicoes
	end

	def total_das_medicoes
		medicoes_da_obra.contabilizadas.sum(:valor).to_d
	end

	def porcentagem_total_das_medicoes
		total = medicoes_da_obra.contabilizadas.inject(0) { |total, medicao_da_obra|
			total + medicao_da_obra.porcentagem.to_d
		}
	end


	def empenhos_sem_duplicata(empenhos_confirmados)
		empenhos_confirmados = empenhos.confirmado
		empenhos_sem_duplicata = []
		empenhos_selecionados = []
	
		empenhos_confirmados.each do |empenho|
			if empenho.empenho_origem_id.present?
				if empenhos_selecionados.exclude?(empenho.empenho_origem_id)
					empenhos_sem_duplicata << empenho
					empenhos_selecionados << empenho.empenho_origem_id
				end
			else
				empenhos_id_origem = empenhos_confirmados.where(empenho_origem_id: empenho.id).pluck(:id)
				if empenhos_id_origem.empty?
					empenhos_sem_duplicata << empenho
				end
			end
		end
		empenhos_sem_duplicata
	end
	
	def valor_total_empenhado
		empenhos_sem_duplicata = empenhos_sem_duplicata(empenhos.confirmado)
		empenhos_sem_duplicata.to_a.sum(&:valor_total_do_empenho).to_d - empenhos_sem_duplicata.to_a.sum(&:valor_anulado).to_d
	end
	

	def valor_total_liquidado
		empenhos_sem_duplicata = empenhos_sem_duplicata(empenhos.confirmado)
		
		liquidacoes_confirmadas = liquidacoes.confirmadas_ate_autorizadas.do_orcamento.where(empenho: empenhos_sem_duplicata).where('estornada <> true')
		valor_liquidado = liquidacoes_confirmadas.sum(:valor).to_d
		
		valor_liquidado
	end

	def valor_total_pago
		empenhos_sem_duplicata = empenhos_sem_duplicata(empenhos.confirmado)
		
		liquidacoes_confirmadas = liquidacoes.confirmadas_ate_autorizadas.do_orcamento.where(empenho: empenhos_sem_duplicata)
		valor_pago = pagamentos.confirmados_ou_superior.do_orcamento.where(liquidacao: liquidacoes_confirmadas)
		valor_pago.sum(:valor).to_d

	end

	def valor_total_estudos_e_projetos
		if contrato_estudos_id == contrato_id
			self.valor_total_atualizado.to_f - self.valor_estudos.to_f
		else
			self.valor_total_atualizado.to_f
		end
	end

	def buscar_valor_do_contrato_estudos_e_projetos
		if contrato_estudos_id.present? && mesmo_contrato == 'false'
			contrato = Licitacao::Contrato.where(id: contrato_estudos_id).first
			self.valor_estudos = contrato.valor_total_do_contrato.to_f
		else
			self.contrato_estudos_id = self.contrato_id
		end
	end

	def empenhos_sem_duplicata_por_fonte( fonte_de_recursos_id )
		empenhos_por_fonte = empenhos.confirmado.joins(orcamento_da_despesa: :fonte_de_recursos).where(base_fontes_de_recursos: {id: fonte_de_recursos_id})
		empenhos_sem_duplicata = []
		empenhos_selecionados = []
	
		empenhos_por_fonte.each do |empenho|
			if empenho.empenho_origem_id.present?
				if empenhos_selecionados.exclude?(empenho.empenho_origem_id)
					empenhos_sem_duplicata << empenho
					empenhos_selecionados << empenho.empenho_origem_id
				end
			else
				empenhos_id_origem = empenhos_por_fonte.where(empenho_origem_id: empenho.id).pluck(:id)
				if empenhos_id_origem.empty?
					empenhos_sem_duplicata << empenho
				end
			end
		end
		empenhos_sem_duplicata
	end
	

	def valor_empenhado_por_fonte(fonte_de_recursos_id)

		empenhos_sem_duplicata = empenhos_sem_duplicata_por_fonte(fonte_de_recursos_id)
		valor_total_empenho = empenhos_sem_duplicata.sum(&:valor_total_do_empenho).to_d
		valor_anulado_empenho = empenhos_sem_duplicata.sum(&:valor_anulado).to_d
		valor_total_empenho - valor_anulado_empenho

	end

	def valor_liquidado_por_fonte( fonte_de_recursos_id )
		
		empenhos_sem_duplicata = empenhos_sem_duplicata_por_fonte(fonte_de_recursos_id)
		liquidacoes_confirmadas = liquidacoes.confirmadas_ate_autorizadas.do_orcamento.where(empenho: empenhos_sem_duplicata)
		valor_liquidado = liquidacoes_confirmadas.sum(:valor).to_d
		valor_liquidado

	end

	def valor_pago_por_fonte(fonte_de_recursos_id)
		
		empenhos_sem_duplicata = empenhos_sem_duplicata_por_fonte(fonte_de_recursos_id)
		liquidacoes_confirmadas = liquidacoes.confirmadas_ate_autorizadas.do_orcamento.where(empenho: empenhos_sem_duplicata)
		pagamentos_por_empenho = pagamentos.confirmados_ou_superior.do_orcamento.where(liquidacao: liquidacoes_confirmadas)
		pagamentos_por_fonte = pagamentos_por_empenho.joins(liquidacao: [empenho: [orcamento_da_despesa: :fonte_de_recursos]]).where(base_fontes_de_recursos: { id: fonte_de_recursos_id })
		pagamentos_por_fonte.sum(:valor).to_d

	end
	
	def porcentagem_em_relacao_ao_valor_total valor_param
		return 0 if valor_param == 0
		porcentagem = (( valor_param * 100).to_f / valor_total_atualizado.to_f)
		porcentagem.cap_at 100
	end

	def prazo_de_execucao_atualizado
		(contrato.data_final_de_acordo_com_aditivos - ordens_de_servico.order(:id).first.data_de_inicio).to_i if ordens_de_servico.any?
	end

	def engenheiro_responsavel
		engenheiros_da_obra.order(:id).last
	end

	def responsavel_na_empresa
		engenheiros_da_obra.responsavel_na_empresa.order(:id).last
	end

	def preposto_da_obra
		engenheiros_da_obra.preposto.order(:id).last
	end

	def fiscal_da_obra
		engenheiros_da_obra.fiscal.order(:id).last
	end

	def pode_editar_fiscal_da_obra
		if self.medicoes_da_obra.present?
			self.medicoes_da_obra.each do |medicao|
				if medicao.responsavel_da_prefeitura == self.fiscal_da_obra.pessoa_id
					return true
				end
			end
		end
	end

	def pode_editar_engenheiro_responsavel
		if self.medicoes_da_obra.present?	
			self.medicoes_da_obra.each do |medicao|
				if medicao.responsavel_da_empresa == self.responsavel_na_empresa.pessoa_id
					return true
				end
			end
		end
	end

	def empresa_responsavel
		empresas_da_obra.order(:id).last
	end

	def situacao_atual
		situacoes_da_obra.order(:id).last
	end

	def paralizacoes
		situacoes_da_obra.paralisada
	end

	def porcentagem_do_saldo_de_dias
		diferenca = (Date.today - self.data_de_inicio).to_i.to_whole
		porcentagem = (( diferenca * 100).to_f / (self.data_prevista_de_termino - self.data_de_inicio).to_whole).round(2)
		porcentagem.cap_at 100
	end

	def tempo_restante
		(self.data_prevista_de_termino - Date.today).to_whole
	end

	def valor_total_dos_servicos_da_obra
		total = servicos_da_obra.inject(0) { |total, servico_da_obra|
			total + servico_da_obra.valor_total_dos_itens_do_servico_da_obra.to_f
		}
	end

	def valor_total_de_servicos_a_distribuir
		(self.contrato.valor_total_do_contrato - valor_total_dos_servicos_da_obra).to_f
	end

	# BOOLEANS
	def possui_medicoes?
		self.medicoes_da_obra.size > 0 ? true : false
	end

	def possui_pagamentos?
		pagamentos.any?
	end

	def esta_concluida?
		situacoes_da_obra.last.try(:concluida_definitiva?) || situacoes_da_obra.last.try(:tombada?)
	end

	def esta_tombada?
		situacoes_da_obra.last.try(:tombada?) || situacoes_da_obra.last.try(:tombo_do_bem?).present?
	end

	def esta_concluida_provisoria?
		situacoes_da_obra.last.try(:concluida_provisoria?)
	end

	def esta_paralisada?
		situacoes_da_obra.last.try(:paralisada?)
	end

	def nao_iniciada?
		situacoes_da_obra.last.try(:nao_iniciada?)
	end

	def em_andamento?
		situacoes_da_obra.last.try(:em_andamento?)
	end

	def iniciada_e_nao_concluida?
		situacoes_da_obra.last.try(:em_andamento?) || situacoes_da_obra.last.try(:concluida_provisoria?)
	end

	def enviado_para_o_sim?
		self.arquivo_id.present? && self.arquivo_id > 0
	end

	def pode_ser_excluida?
		nao_iniciada? && !contrato.enviado_para_o_sim? && !enviado_para_o_sim?
	end

	def teve_termo_de_paralisacao_nos_ultimos_120_dias?
		(documentos_da_obra.termo_de_paralisacao.any? && documentos_da_obra.termo_de_paralisacao.any? { |termo| termo.data_do_documento >= Date.today - 120 })
	end

	def teve_medicao_nos_ultimos_120_dias?
		(possui_medicoes? && medicoes_da_obra.any?{ |medicao| medicao.data_inicial.present? && (medicao.data_inicial >= Date.today - 120) || medicao.data_final.present? && (medicao.data_final >= Date.today - 120) }) ? true : false
	end

	def teve_pagamento_nos_ultimos_120_dias?
		(possui_pagamentos? && empenhos.any? { |empenho| empenho.pagamentos.any? { |pagamento| pagamento.data >= Date.today - 120 } }) ? true : false
	end

	def teve_movimentacoes_nos_ultimos_120_dias?
		(teve_medicao_nos_ultimos_120_dias? || teve_pagamento_nos_ultimos_120_dias?) && !self.esta_paralisada? ? true : false
	end

	def deve_ser_criado_um_termo_de_reinicio?
		termo_de_paralisacao = documentos_da_obra.termo_de_paralisacao.last
		esta_paralisada? && termo_de_paralisacao.present? && termo_de_paralisacao.data_fim_paralisacao.present? && termo_de_paralisacao.data_fim_paralisacao >= Date.today
	end

	def contem_contratos_da_obra?
		contratos_da_obra.count > 1
	end

	def obra_concluida_sem_tombo_do_terreno_informado?
		tombo_do_terreno.blank? && esta_concluida?
	end

	def tem_garantias_nao_devolvidas?
		garantias_da_obra.aberta.any?
	end

	def prazo_de_conclusao_menor_que_50_dias?
		(contrato.data_final_de_acordo_com_aditivos - Date.today).to_i <= 50 ? true : false
	end

	def obra_iniciada?
		situacoes_da_obra.where.not(tipo_de_status_da_obra: Contabilidade::SituacaoDaObra.tipos_de_status_da_obra["nao_iniciada"]).any?
	end

	def porcentagem_de_medicao_da_obra_menor_ou_igual_a_50_por_cento?
		porcentagem_total_das_medicoes <= 50 ? true : false
	end

	def porcentagem_de_vigencia_da_obra_maior_ou_igual_a_80_por_cento?
		self.contrato.porcentagem_do_saldo_vigencia >= 80 ? true : false
	end

	def valor_da_obra_menor_que_valor_dos_servicos?
		self.contrato.valor_total_do_contrato < valor_total_dos_servicos_da_obra
	end

	def validade_do_alvara_faltando_30_dias_ou_menos?
		(data_de_validade_do_alvara - Date.today).to_whole <= 30
	end

	def descricao_da_obra
		if apelido_da_obra.present?
			"#{codigo}.#{self.data_de_inicio.year.to_s.last(2)} - #{self.apelido_da_obra}"
		else
			"#{codigo}.#{self.data_de_inicio.year.to_s.last(2)}"
		end
	end

	def codigo_corrigido(contabilidade_atual)
		if contabilidade_atual == true
			"#{codigo}.#{self.data_de_inicio.year.to_s.last(2)}"
		else
			"#{codigo}"
		end
	end

	def codigo_e_tipo
		"#{codigo} - #{localizar(:tipo_de_obra)}"
	end

	def status_atual_da_obra
		if esta_concluida?
			style = "success"
			status = 'Concluída'
		elsif esta_concluida_provisoria?
			style = "primary"
			status = 'Provisoriamente Concluída'
		elsif esta_paralisada?
			style = "danger"
			status = 'Paralisada'
		elsif em_andamento?
			style = "info"
			status = 'Em Andamento'
		elsif nao_iniciada?
			style = "warning"
			status = 'Não Iniciada'
		end
			"<span data-placement=bottom title='A última Atualização de status foi em:  #{situacao_atual.try(:data_da_situacao).to_s}'class=\"label label-#{style}\">#{status}</span>".html_safe
	end

	def endereco_completo
		if numero_logradouro.present? && complemento.present? && bairro.present? && cep.present?
			"#{logradouro}, #{numero_logradouro}, #{complemento}, #{bairro}, #{cidade.try(:nome)} - #{cidade.try(:estado).try(:nome)}, CEP: #{cep.try(:as_cep)}"
		elsif numero_logradouro.present? && bairro.present? && cep.present?
			"#{logradouro}, #{numero_logradouro}, #{bairro}, #{cidade.try(:nome)} - #{cidade.try(:estado).try(:nome)}, CEP: #{cep.try(:as_cep)}"
		elsif numero_logradouro.present? && cep.present?
			"#{logradouro}, #{numero_logradouro}, #{cidade.try(:nome)} - #{cidade.try(:estado).try(:nome)}, CEP: #{cep.try(:as_cep)}"
		else
			"#{logradouro}, #{cidade.try(:nome)} - #{cidade.try(:estado).try(:nome)}" if logradouro.present? || cidade.present?
		end
	end

	def pcasp_do_orcamento orcamento_desejado
		Contabilidade::Conta.where(orcamento: orcamento_desejado, codigo: self.conta_pcasp.try(:codigo)).first
	end

	## Métodos usados no acompanhamento da obra/ Relatório de Fiscalização
	def valor_total_atualizado
		
		contrato.valor_do_contrato.to_d + contrato.valor_dos_apostilamentos + contrato.valor_dos_aditivos.to_d +
		(contrato.total_reajuste_de_valor_acrescimo - contrato.total_reajuste_de_valor_decrescimo).to_d + contrato.valor_dos_aditivos_de_prorrogacao.to_d
	end

	def valor_aditivado
		contrato.valor_dos_aditivos.to_f
	end

	def prazo_de_conclusao
		(data_prevista_de_termino - data_de_inicio).to_whole + 1
	end

	def dias_percorridos
		(Date.today - data_de_inicio).to_i
	end

	def quantidade_de_dias_de_execucao_da_obra
		if ordens_de_servico.any?
			if ordens_de_servico.first.data_de_inicio <= Date.today
				(Date.today - ordens_de_servico.first.data_de_inicio).to_i + 1
			end
		end
	end

	def prazo_da_obra_em_dias
		(self.data_prevista_de_termino - self.data_de_inicio).to_whole
	end

	def paralisacoes_em_dias
		situacoes_da_obra.paralisada.sum(&:tempo_transcorrido)
	end

	def prazo_aditado_em_dias
		contrato.prazo_aditado.to_whole
	end

	def data_de_validade_do_alvara
		(self.data_do_alvara + self.validade_do_alvara) + 1
	end

	def documento_da_obra_concluida_definitiva
		documentos_da_obra.last
	end

	def foi_classificada?
		return !self.uso_do_bem.nil? && self.conta_pcasp.present?
	end

	def verifica_se_obra_foi_classificada
		if !self.foi_classificada?
			cria_mensagem_sobre_obra_nao_classificada(self)
		end
	end

	def definir_data_sim
		self.data_de_envio_pro_sim = self.data_de_inicio.end_of_month
	end

	def tipo_para_o_sim
		if obra?
			return "O"
		elsif servico?
			return "S"
		end
	end

	def to_sim
		begin
			unidade_orcamentaria = contrato.unidade_orcamentaria_do_exercicio

			texto = ""
			texto << "901".to_s.sim_preenche(3) + "," #1
			texto << Configuracao.first.codigo_do_municipio_no_tcm.to_s.sim_preenche(3) + "," #2
			texto << data_de_inicio.sim_data + "," #3
			texto << tipo_para_o_sim.sim_limite(1)+ "," #4
			texto << codigo.sim_limite(4)+ "," #5
			texto << orcamento.exercicio.to_s.sim_limite(4, "00") + "," #6
			texto << unidade_orcamentaria.orgao.codigo.sim_preenche(2) + "," #7
			texto << unidade_orcamentaria.codigo.codigo_uo_to_sim + "," #8
			texto << descricao.gsub(/["\r\n]/, "").sim_limite(510) + "," #9
			texto << classificacao_do_bem.codigo.sim_limite(9) + "," #10
			texto << tipo_de_administracao.sigla.sim_limite(1) + "," #11
			texto << data_prevista_de_termino.sim_data + "," #12
			texto << valor.to_f.to_s.sim_valor + "," #13
			texto << numero_do_crea.sim_limite(15) + "," #14
			texto << engenheiro_responsavel.numero_do_crea.sim_limite(15) + "," #15
			texto << engenheiro_responsavel.pessoa.nome.sim_limite(40) + "," #16
			texto << engenheiro_responsavel.pessoa.cpf.sim_limite(11) + "," #17
			texto << engenheiro_responsavel.data_de_inicio.sim_data + "," #18
			texto << empresa_responsavel.try(:pessoa).try(:cpf_ou_cnpj_sem_sinalizacao).to_s.sim_limite(25) + "," #19
			texto << empresa_responsavel.try(:pessoa).try(:nome).to_s.sim_limite(60) + "," #20
			texto << empresa_responsavel.try(:numero_do_crea).to_s.sim_limite(25) + "," #21
			texto << empresa_responsavel.try(:pessoa).try(:telefone).to_s.sim_limite(11) + "," #22
			texto << empresa_responsavel.try(:pessoa).try(:endereco_completo).to_s.sim_limite(255) + "," #23
			texto << empresa_responsavel.try(:pessoa).try(:cep).to_s.sim_limite(8) + "," #24
			texto << empresa_responsavel.try(:pessoa).try(:cidade).try(:nome).to_s.sim_limite(30) + "," #25
			texto << empresa_responsavel.try(:pessoa).try(:cidade).try(:estado).try(:uf).to_s.sim_limite(2) + "," #26
			texto << tombo_do_terreno.sim_limite(20) + "," #27
			texto << tombo_da_construcao.sim_limite(20) + "," #28
			texto << licenca_ambiental.to_s.sim_limite(12) + "," #29
			texto << orgao_licenca.sim_limite(80) + "," #30
	
			if data_da_licenca.present?
				texto << data_da_licenca.sim_data + "," #31
			else
				texto << "0,"#31
			end

			if cei.present?
				texto << cei.to_s.sim_limite(12) #32
			else
				texto << '""'#32
			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.codigo, atributo_falho, coluna)
			else
				raise e
			end
		end
	end

	def valor_estudos_nao_pode_ser_maior_que_saldo_do_contrato
		saldo_do_contrato = self.contrato_estudos.try(:valor_total_do_contrato).to_f
		if self.valor_estudos.to_f > saldo_do_contrato
			errors.add(:valor_estudos, "Não pode ser maior que o saldo do contrato #{saldo_do_contrato.real_contabil}")
		end
	end

	def foi_tombada?
		self.situacoes_da_obra.any? {|situacao_da_obra| situacao_da_obra.tombada? }
	end

	def concluida?
		ultima_situacao_da_obra = self.situacoes_da_obra.try(:last)
		(ultima_situacao_da_obra.try(:concluida_provisoria?) || ultima_situacao_da_obra.try(:concluida_definitiva?))
	end

	def preencheu_dados_do_tombamento?
		self.tombo_do_terreno.present? && self.tombo_da_construcao.present?
	end

	def pode_tombar_a_obra?
		self.concluida? && self.documentos_da_obra.any?{ |documento_da_obra| documento_da_obra.termo_de_conclusao? } && self.preencheu_dados_do_tombamento?
	end

	def tombar_a_obra
		if self.pode_tombar_a_obra?
			begin
				Contabilidade::SituacaoDaObra.create!(obra_id: self.id, engenheiro_da_obra_id: self.engenheiro_responsavel.id, tipo_de_status_da_obra: "tombada", data_da_situacao: Date.today)
			rescue => e
				raise e.message
			end
		end
	end 
	
	def valor_estudos_nao_pode_ser_maior_que_saldo_do_contrato
		saldo_do_contrato = self.contrato_estudos.try(:valor_total_do_contrato).to_f
		if self.valor_estudos.to_f > saldo_do_contrato
			errors.add(:valor_estudos, "Não pode ser maior que o saldo do contrato #{saldo_do_contrato.real_contabil}")
		end
	end

	def verifica_cadastro_de_status_mensal(data)
		status_no_mes = self.situacoes_da_obra.where('data_da_situacao BETWEEN ? AND ?', data, data.end_of_month).count
		raise "#{self.tipo_de_obra_i18n} (id: #{self.id} - código: #{self.codigo}.#{self.data_de_inicio.year.to_s.last(2)}) não possui nenhum status cadastrado nesse mês" if status_no_mes == 0 && ((self.nao_iniciada? && self.medicoes_da_obra.any?) || (self.em_andamento?)) 
	end
end
