require 'csv'

class Tableless::EncerramentoPcasp
	include ActiveModel::Model

	attr_accessor :orcamento

	# def encerrar_conta_pcasp(evento, codigo_da_conta_debito, codigo_da_conta_credito, lancar_se_invertido = false, conta_a_verificar = 1)
	# 	conta1 = self.orcamento.contas.where(codigo: codigo_da_conta_debito).first
	# 	conta2 = self.orcamento.contas.where(codigo: codigo_da_conta_credito).first

	# 	if conta_a_verificar == 1
	# 		saldo_conta = conta1.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
	# 		tipo_de_saldo_conta = conta1.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
	# 		movimentacoes = conta1.movimentacoes_do_plano_de_contas
	# 	else
	# 		saldo_conta = conta2.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
	# 		tipo_de_saldo_conta = conta2.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
	# 		movimentacoes = conta2.movimentacoes_do_plano_de_contas
	# 	end
		
	# 	if saldo_conta != 0
	# 		movimentacoes = movimentacoes.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).all

	# 		data_de_lancamento = Date.new(self.orcamento.exercicio.to_i, 12, 31)

	# 		grupos = movimentacoes.group_by{ |i| [
	# 			i.tipo_de_lancamento,
	# 			i.unidade_orcamentaria, 
	# 			i.sub_conta_pcasp,
	# 			i.ic_po,
	# 			i.ic_fp,
	# 			i.ic_dc,
	# 			i.ic_fr,
	# 			i.ic_co,
	# 			i.ic_cf,
	# 			i.ic_nr,
	# 			i.ic_nd,
	# 			i.ic_fs,
	# 			i.ic_es,
	# 			i.ic_ai
	# 			] }
			
	# 		puts "ENCERRANDO PAR DE CONTAS PCASP #{conta1.codigo} - #{conta2.codigo}"
	# 		bar = RakeProgressbar.new(grupos.size)

	# 		grupos.each do |grupo, movimentacoes|
	# 			total_debitos = movimentacoes.filter{ |i| 
	# 				i.tipo_de_lancamento == "debito" &&
	# 				i.unidade_orcamentaria_id == grupo[1]&.id &&
	# 				i.sub_conta_pcasp_id == grupo[2]&.id &&
	# 				i.ic_po == grupo[3] &&
	# 				i.ic_fp == grupo[4] &&
	# 				i.ic_dc == grupo[5] &&
	# 				i.ic_fr == grupo[6] &&
	# 				i.ic_co == grupo[7] &&
	# 				i.ic_cf == grupo[8] &&
	# 				i.ic_nr == grupo[9] &&
	# 				i.ic_nd == grupo[10] &&
	# 				i.ic_fs == grupo[11] &&
	# 				i.ic_es == grupo[12] &&
	# 				i.ic_ai == grupo[13]
	# 			}.sum(&:valor)

	# 			total_creditos = movimentacoes.filter{ |i| 
	# 				i.tipo_de_lancamento == "credito" &&
	# 				i.unidade_orcamentaria_id == grupo[1]&.id &&
	# 				i.sub_conta_pcasp_id == grupo[2]&.id &&
	# 				i.ic_po == grupo[3] &&
	# 				i.ic_fp == grupo[4] &&
	# 				i.ic_dc == grupo[5] &&
	# 				i.ic_fr == grupo[6] &&
	# 				i.ic_co == grupo[7] &&
	# 				i.ic_cf == grupo[8] &&
	# 				i.ic_nr == grupo[9] &&
	# 				i.ic_nd == grupo[10] &&
	# 				i.ic_fs == grupo[11] &&
	# 				i.ic_es == grupo[12] &&
	# 				i.ic_ai == grupo[13]
	# 			}.sum(&:valor)

	# 			if lancar_se_invertido == true
	# 				if tipo_de_saldo_conta == 'D'
	# 					saldo_final = total_debitos - total_creditos
	# 					if saldo_final >= 0
	# 						movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo)
	# 						self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao) if movimentacao.present?
	# 					else
	# 						movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :credito, grupo)
	# 						self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao) if movimentacao.present?
	# 					end
	# 				elsif tipo_de_saldo_conta == 'C'
	# 					saldo_final = total_creditos - total_debitos
	# 					if saldo_final >= 0
	# 						movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo)
	# 						self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao) if movimentacao.present?
	# 					else
	# 						movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :debito, grupo)
	# 						self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao) if movimentacao.present?
	# 					end
	# 				end
	# 			else
	# 				if conta_a_verificar == 1
	# 					saldo_final = total_creditos - total_debitos

	# 					movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo)
	# 					movimentacao2 = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao) if movimentacao.present?

	# 					# temporario - ver abaixo
	# 					if saldo_final < 0
	# 						movimentacao.update_column(:tipo_de_lancamento, :credito)
	# 						movimentacao2.update_column(:tipo_de_lancamento, :debito)
	# 					end
	# 				else
	# 					saldo_final = total_debitos - total_creditos
						
	# 					movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo)
	# 					movimentacao2 = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao) if movimentacao.present?

	# 					# temporário (por que o saldo está invertido no grupo e a conta não fecha) ver com o icaro e o isaac, conta 621310100
	# 					# select codigo_da_conta, ic_po, ic_fp, ic_dc, ic_fr, ic_co, ic_cf, ic_nr, ic_nd, ic_fs, ic_es, ic_ai, sum(valor)
	# 					# from contabilidade_movimentacoes_do_plano_de_contas
	# 					# where codigo_da_conta = '621310100' and lancamento_manual is null
	# 					# group by codigo_da_conta, tipo_de_lancamento, ic_po, ic_fp, ic_dc, ic_fr, ic_co, ic_cf, ic_nr, ic_nd, ic_fs, ic_es, ic_ai
	# 					# order by codigo_da_conta, tipo_de_lancamento, ic_po, ic_fp, ic_dc, ic_fr, ic_co, ic_cf, ic_nr, ic_nd, ic_fs, ic_es, ic_ai;
	# 					if saldo_final < 0
	# 						movimentacao.update_column(:tipo_de_lancamento, :debito)
	# 						movimentacao2.update_column(:tipo_de_lancamento, :credito)
	# 					end
	# 				end
	# 			end

	# 			bar.inc
	# 		end

	# 		bar.finished

	# 	end

	# 	conta1.update_column(:saldo, conta1.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	# 	conta2.update_column(:saldo, conta2.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	# end

	def encerrar_conta_pcasp_na_abertura(evento, codigo_da_conta_debito, codigo_da_conta_credito, lancar_se_invertido = false, conta_a_verificar = 1)
		data_de_lancamento = Date.new(self.orcamento.exercicio.to_i, 1, 2)

		conta1 = self.orcamento.contas.where(codigo: codigo_da_conta_debito).first
		conta2 = self.orcamento.contas.where(codigo: codigo_da_conta_credito).first

		if conta_a_verificar == 1
			saldo_conta = conta1.saldo_da_conta(data_de_lancamento).to_d
			tipo_de_saldo_conta = conta1.tipo_de_saldo(data_de_lancamento)
			movimentacoes = conta1.movimentacoes_do_plano_de_contas
		else
			saldo_conta = conta2.saldo_da_conta(data_de_lancamento).to_d
			tipo_de_saldo_conta = conta2.tipo_de_saldo(data_de_lancamento)
			movimentacoes = conta2.movimentacoes_do_plano_de_contas
		end

		if saldo_conta != 0
			movimentacoes = movimentacoes.where("data_de_lancamento >= ? and coalesce(lancamento_manual, 0) = 999", Date.new(self.orcamento.exercicio.to_i, 1, 1)).all

			grupos = movimentacoes.group_by{ |i| [
				i.tipo_de_lancamento,
				i.unidade_orcamentaria, 
				i.sub_conta_pcasp,
				i.ic_po,
				i.ic_fp,
				i.ic_dc,
				i.ic_fr,
				i.ic_co,
				i.ic_cf,
				i.ic_nr,
				i.ic_nd,
				i.ic_fs,
				i.ic_es,
				i.ic_ai
				] }

			array_grupos = []
			grupos.each do |grupo, movimentacoes|
				array_grupos << {
					tipo_de_lancamento: grupo[0],
					unidade_orcamentaria: grupo[1],
					sub_conta_pcasp: grupo[2],
					ic_po: grupo[3],
					ic_fp: grupo[4],
					ic_dc: grupo[5],
					ic_fr: grupo[6],
					ic_co: grupo[7],
					ic_cf: grupo[8],
					ic_nr: grupo[9],
					ic_nd: grupo[10],
					ic_fs: grupo[11],
					ic_es: grupo[12],
					ic_ai: grupo[13],
					total: movimentacoes.sum(&:valor)
				}
			end

			puts "ENCERRANDO PAR DE CONTAS PCASP #{conta1.codigo} - #{conta2.codigo}"
			bar = RakeProgressbar.new(grupos.size)

			array_grupos.group_by{ |i| [
				i[:unidade_orcamentaria], 
				i[:sub_conta_pcasp],
				i[:ic_po],
				i[:ic_fp],
				i[:ic_dc],
				i[:ic_fr],
				i[:ic_co],
				i[:ic_cf],
				i[:ic_nr],
				i[:ic_nd],
				i[:ic_fs],
				i[:ic_es],
				i[:ic_ai]
				] }.each do |grupo, a2|
					grupo = grupo.unshift(nil) # preencher tipo com vazio para passar a array grupo com a quantidade correta de elementos

					total_debitos = a2.filter{ |i| i[:tipo_de_lancamento] == 'debito' }.inject(0) {|t, a| t + a[:total].to_d }.to_d
					total_creditos = a2.filter{ |i| i[:tipo_de_lancamento] == 'credito' }.inject(0) {|t, a| t + a[:total].to_d }.to_d
				
					if conta_a_verificar == 1
						saldo_final = total_creditos - total_debitos

						movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, nil, :abertura)
						movimentacao2 = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao, :abertura) if movimentacao.present?

						if saldo_final < 0
							movimentacao.update_column(:tipo_de_lancamento, :credito)
							movimentacao2.update_column(:tipo_de_lancamento, :debito)
						end
					else
						saldo_final = total_debitos - total_creditos
						
						movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, nil, :abertura)
						movimentacao2 = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao, :abertura) if movimentacao.present?

						if saldo_final < 0
							movimentacao.update_column(:tipo_de_lancamento, :debito)
							movimentacao2.update_column(:tipo_de_lancamento, :credito)
						end
					end

				bar.inc
			end

			bar.finished

		end

		conta1.update_column(:saldo, conta1.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
		conta2.update_column(:saldo, conta2.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	end

	def encerrar_conta_pcasp(evento, codigo_da_conta_debito, codigo_da_conta_credito, lancar_se_invertido = false, conta_a_verificar = 1)
		data_de_lancamento = Date.new(self.orcamento.exercicio.to_i, 12, 31)

		conta1 = self.orcamento.contas.where(codigo: codigo_da_conta_debito).first
		conta2 = self.orcamento.contas.where(codigo: codigo_da_conta_credito).first

		if conta_a_verificar == 1
			saldo_conta = conta1.saldo_da_conta(data_de_lancamento).to_d
			tipo_de_saldo_conta = conta1.tipo_de_saldo(data_de_lancamento)
			movimentacoes = conta1.movimentacoes_do_plano_de_contas
		else
			saldo_conta = conta2.saldo_da_conta(data_de_lancamento).to_d
			tipo_de_saldo_conta = conta2.tipo_de_saldo(data_de_lancamento)
			movimentacoes = conta2.movimentacoes_do_plano_de_contas
		end
		
		if saldo_conta != 0
			movimentacoes = movimentacoes.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).all

			grupos = movimentacoes.group_by{ |i| [
				i.tipo_de_lancamento,
				i.unidade_orcamentaria, 
				i.sub_conta_pcasp,
				i.ic_po,
				i.ic_fp,
				i.ic_dc,
				i.ic_fr,
				i.ic_co,
				i.ic_cf,
				i.ic_nr,
				i.ic_nd,
				i.ic_fs,
				i.ic_es,
				i.ic_ai
				] }

			array_grupos = []
			grupos.each do |grupo, movimentacoes|
				array_grupos << {
					tipo_de_lancamento: grupo[0],
					unidade_orcamentaria: grupo[1],
					sub_conta_pcasp: grupo[2],
					ic_po: grupo[3],
					ic_fp: grupo[4],
					ic_dc: grupo[5],
					ic_fr: grupo[6],
					ic_co: grupo[7],
					ic_cf: grupo[8],
					ic_nr: grupo[9],
					ic_nd: grupo[10],
					ic_fs: grupo[11],
					ic_es: grupo[12],
					ic_ai: grupo[13],
					total: movimentacoes.sum(&:valor)
				}
			end

			puts "ENCERRANDO PAR DE CONTAS PCASP #{conta1.codigo} - #{conta2.codigo}"
			bar = RakeProgressbar.new(grupos.size)

			array_grupos.group_by{ |i| [
				i[:unidade_orcamentaria], 
				i[:sub_conta_pcasp],
				i[:ic_po],
				i[:ic_fp],
				i[:ic_dc],
				i[:ic_fr],
				i[:ic_co],
				i[:ic_cf],
				i[:ic_nr],
				i[:ic_nd],
				i[:ic_fs],
				i[:ic_es],
				i[:ic_ai]
				] }.each do |grupo, a2|
					grupo = grupo.unshift(nil) # preencher tipo com vazio para passar a array grupo com a quantidade correta de elementos

					total_debitos = a2.filter{ |i| i[:tipo_de_lancamento] == 'debito' }.inject(0) {|t, a| t + a[:total].to_d }.to_d
					total_creditos = a2.filter{ |i| i[:tipo_de_lancamento] == 'credito' }.inject(0) {|t, a| t + a[:total].to_d }.to_d

				if lancar_se_invertido == true
					if tipo_de_saldo_conta == 'D'
						saldo_final = total_debitos - total_creditos
						if saldo_final >= 0
							movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, nil, :encerramento)
							self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao, :encerramento) if movimentacao.present?
						else
							movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :credito, grupo, nil, :encerramento)
							self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao, :encerramento) if movimentacao.present?
						end
					elsif tipo_de_saldo_conta == 'C'
						saldo_final = total_creditos - total_debitos
						if saldo_final >= 0
							movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, nil, :encerramento)
							self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao, :encerramento) if movimentacao.present?
						else
							movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :debito, grupo, nil, :encerramento)
							self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao, :encerramento) if movimentacao.present?
						end
					end
				else
					if conta_a_verificar == 1
						saldo_final = total_creditos - total_debitos

						movimentacao = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, nil, :encerramento)
						movimentacao2 = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, movimentacao, :encerramento) if movimentacao.present?

						# temporario - ver abaixo
						if saldo_final < 0
							movimentacao.update_column(:tipo_de_lancamento, :credito)
							movimentacao2.update_column(:tipo_de_lancamento, :debito)
						end
					else
						saldo_final = total_debitos - total_creditos
						
						movimentacao = self.gerar_movimentacao(evento, conta2, saldo_final.abs, data_de_lancamento, :credito, grupo, nil, :encerramento)
						movimentacao2 = self.gerar_movimentacao(evento, conta1, saldo_final.abs, data_de_lancamento, :debito, grupo, movimentacao, :encerramento) if movimentacao.present?

						if saldo_final < 0
							movimentacao.update_column(:tipo_de_lancamento, :debito)
							movimentacao2.update_column(:tipo_de_lancamento, :credito)
						end
					end
				end

				bar.inc
			end

			bar.finished

		end

		conta1.update_column(:saldo, conta1.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
		conta2.update_column(:saldo, conta2.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	end

	def encerrar_conta_pcasp_por_gerador(evento, codigo_da_conta_debito, codigo_da_conta_credito, classe_do_movimento, conta_a_verificar = 1, condicao_orcamento = nil, filtrar_data = true, restos_a_pagar = nil)
		conta1 = self.orcamento.contas.where(codigo: codigo_da_conta_debito).first
		conta2 = self.orcamento.contas.where(codigo: codigo_da_conta_credito).first

		if conta_a_verificar == 1
			saldo_conta = conta1.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
			tipo_de_saldo_conta = conta1.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
			movimentacoes = conta1.movimentacoes_do_plano_de_contas
			codigo_da_conta_filtro = codigo_da_conta_debito
		else
			saldo_conta = conta2.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
			tipo_de_saldo_conta = conta2.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
			movimentacoes = conta2.movimentacoes_do_plano_de_contas
			codigo_da_conta_filtro = codigo_da_conta_credito
		end

		if saldo_conta != 0
			csv_string = CSV.generate(col_sep: ";", quote_char: '"', force_quotes: true) do |csv|

				if classe_do_movimento == 'Contabilidade::Empenho'
					csv << ["ID", "CLASSE", "VALOR", "VALOR EM EVENTOS", "DIFERENCA 1", "ANULADO", "ANUL EM EVENTOS", "DIFERENCA 2", "LIQUIDADO", "LIQ EM EVENTOS", "DIFERENCA 3", "LIQ ANULADO", "LIQ ANUL EM EVENTOS", "DIFERENCA 4", "SALDO DO EMP", "VALOR EVENTO GERADO", "DIFERENCA 5"]
				end

				if classe_do_movimento == 'Contabilidade::Liquidacao'
					csv << ["ID", "CLASSE", "VALOR", "VALOR EM EVENTOS", "DIFERENCA 1", "ANULADO", "ANUL EM EVENTOS", "DIFERENCA 2", "PAGAMENTO", "PAG EM EVENTOS", "DIFERENCA 3", "EST PAGAMENTO", "EST PAG EM EVENTOS", "DIFERENCA 4", "SALDO DA LIQ", "VALOR EVENTO GERADO", "DIFERENCA 5"]
				end

				if classe_do_movimento == 'Contabilidade::Pagamento'
					csv << ["ID", "CLASSE", "VALOR", "VALOR EM EVENTOS", "DIFERENCA 1", "ANULADO", "ANUL EM EVENTOS", "DIFERENCA 2", "SALDO DO PAG", "VALOR EVENTO GERADO", "DIFERENCA 3"]
				end

				if classe_do_movimento == 'Contabilidade::Pagamento' && condicao_orcamento != nil
					movimentacoes = movimentacoes.joins("left join contabilidade_pagamentos on gerador_id = contabilidade_pagamentos.id")
						.joins("left join contabilidade_liquidacoes on contabilidade_liquidacoes.id = contabilidade_pagamentos.liquidacao_id")
						.joins("left join contabilidade_empenhos on contabilidade_empenhos.id = contabilidade_liquidacoes.empenho_id")
						.joins("left join orcamentos on contabilidade_empenhos.orcamento_id = orcamentos.id")
						.where(gerador_type: classe_do_movimento).where(condicao_orcamento).all
				elsif classe_do_movimento == 'Contabilidade::CancelamentoDeRestoAPagar' && condicao_orcamento != nil
					contabilidade_restos_a_pagar_cancelados_ids = Contabilidade::RestoAPagarCancelado.joins(empenho: :orcamento).where(condicao_orcamento).pluck(:cancelamento_de_resto_a_pagar_id)
					movimentacoes = movimentacoes.where(gerador_type: classe_do_movimento, gerador_id: [contabilidade_restos_a_pagar_cancelados_ids]).all
				else
					if filtrar_data == true
						movimentacoes = movimentacoes.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).where(gerador_type: classe_do_movimento).where("coalesce(lancamento_manual, 0) != 1000").all
					else
						movimentacoes = movimentacoes.where(gerador_type: classe_do_movimento).where("coalesce(lancamento_manual, 0) != 1000").all
					end
				end

				data_de_lancamento = Date.new(self.orcamento.exercicio.to_i, 12, 31)

				grupos = movimentacoes.group_by{ |i| [
					i.tipo_de_lancamento,
					i.unidade_orcamentaria, 
					i.sub_conta_pcasp,
					i.ic_po,
					i.ic_fp,
					i.ic_dc,
					i.ic_fr,
					i.ic_co,
					i.ic_cf,
					i.ic_nr,
					i.ic_nd,
					i.ic_fs,
					i.ic_es,
					i.ic_ai,
					i.gerador_id,
					i.gerador_type
					] }

				puts "ENCERRANDO PAR DE CONTAS PCASP #{conta1.codigo} - #{conta2.codigo}"
				bar = RakeProgressbar.new(grupos.size)

				grupos.each do |grupo, movimentacoes|
					verificacao = []

					tipo_de_lancamento_1 = grupo[0] == 0 ? :credito : :debito
					tipo_de_lancamento_2 = tipo_de_lancamento_1 == :credito ? :debito : :credito

					if grupo[15] == 'Contabilidade::Empenho'
						empenho = Contabilidade::Empenho.find(grupo[14])

						Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Empenho', gerador_id: empenho.id, codigo_da_conta: codigo_da_conta_filtro).update_all(validado: true)

						total_do_empenho = empenho.definir_valor_do_empenho
						total_anulado = empenho.anulacoes_do_empenho.confirmados.sum(:valor)

						# nao lembro o motivo, influencia negativamente no fechamento da conta 622130100
						total_do_empenho_tipo_invertido = 0 #Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Empenho', gerador_id: empenho.id, codigo_da_conta: codigo_da_conta_filtro, tipo_de_lancamento: tipo_de_lancamento_2).sum(:valor).to_d

						total_anulado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::AnulacaoDoEmpenho', gerador_id: [empenho.anulacoes_do_empenho.pluck(:id)])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::AnulacaoDoEmpenho', gerador_id: [empenho.anulacoes_do_empenho.pluck(:id)])
							.update_all(validado: true)

						total_liquidado = empenho.liquidacoes.confirmadas_ate_autorizadas.do_orcamento.sum(:valor)

						total_liquidado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Liquidacao', gerador_id: [empenho.liquidacoes.pluck(:id)])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Liquidacao', gerador_id: [empenho.liquidacoes.pluck(:id)])
							.update_all(validado: true)

						total_liquidado_estornado = empenho.liquidacoes.map { |liquidacao| liquidacao.valor if liquidacao.estorno_de_liquidacao.present? }.compact.sum.to_d

						total_liquidado_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [empenho.liquidacoes.map { |liquidacao| liquidacao.estorno_de_liquidacao&.id }.compact])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [empenho.liquidacoes.map { |liquidacao| liquidacao.estorno_de_liquidacao&.id }.compact])
							.update_all(validado: true)

						ids_de_cancelamento = Contabilidade::RestoAPagarCancelado.where(empenho_id: empenho.id).map { |i| i.cancelamento_de_resto_a_pagar_id }
						total_de_restos_cancelados_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::CancelamentoDeRestoAPagar', gerador_id: [ids_de_cancelamento])
							.sum(:valor).to_d

						saldo = total_do_empenho - total_do_empenho_tipo_invertido - total_anulado - total_liquidado + total_liquidado_estornado - total_de_restos_cancelados_em_movimentos

						verificacao = verificacao + [grupo[14], grupo[15], total_do_empenho.try(:contabil).to_s.gsub(".", ""), movimentacoes.sum(&:valor).try(:contabil).to_s.gsub(".", ""), (total_do_empenho - movimentacoes.sum(&:valor)).try(:contabil).to_s.gsub(".", ""), total_anulado.try(:contabil).to_s.gsub(".", ""), total_anulado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_anulado - total_anulado_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_liquidado.try(:contabil).to_s.gsub(".", ""), total_liquidado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_liquidado - total_liquidado_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_liquidado_estornado.try(:contabil).to_s.gsub(".", ""), total_liquidado_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_liquidado_estornado - total_liquidado_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), saldo.try(:contabil).to_s.gsub(".", "")]

					elsif grupo[15] == 'Contabilidade::Liquidacao'
						liquidacao = Contabilidade::Liquidacao.find(grupo[14])

						Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Liquidacao', gerador_id: liquidacao.id, codigo_da_conta: codigo_da_conta_filtro).update_all(validado: true)

						total_da_liquidacao = liquidacao.valor
						total_estornado = liquidacao.estorno_de_liquidacao.present? ? liquidacao.valor : 0

						total_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [liquidacao.estorno_de_liquidacao&.id])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [liquidacao.estorno_de_liquidacao&.id])
							.update_all(validado: true)

						total_pago = liquidacao.pagamentos.confirmados_ou_superior_com_estornados.do_orcamento.sum(:valor)

						total_pago_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Pagamento', gerador_id: [liquidacao.pagamentos.pluck(:id)])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Pagamento', gerador_id: [liquidacao.pagamentos.pluck(:id)])
							.update_all(validado: true)

						total_pago_estornado = liquidacao.pagamentos.map { |pagamento| pagamento.valor if pagamento.estorno_de_pagamento.present? }.compact.sum.to_d

						total_pago_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [liquidacao.pagamentos.map { |pagamento| pagamento.estorno_de_pagamento&.id }.compact])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [liquidacao.pagamentos.map { |pagamento| pagamento.estorno_de_pagamento&.id }.compact])
							.update_all(validado: true)

						saldo = total_da_liquidacao - total_estornado - total_pago + total_pago_estornado

						verificacao = verificacao + [grupo[14], grupo[15], total_da_liquidacao.try(:contabil).to_s.gsub(".", ""), movimentacoes.sum(&:valor).try(:contabil).to_s.gsub(".", ""), (total_da_liquidacao - movimentacoes.sum(&:valor)).try(:contabil).to_s.gsub(".", ""), total_estornado.try(:contabil).to_s.gsub(".", ""), total_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_estornado - total_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_pago.try(:contabil).to_s.gsub(".", ""), total_pago_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_pago - total_pago_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_pago_estornado.try(:contabil).to_s.gsub(".", ""), total_pago_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_pago_estornado - total_pago_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), saldo.try(:contabil).to_s.gsub(".", "")]
					elsif grupo[15] == 'Contabilidade::Pagamento'
						pagamento = Contabilidade::Pagamento.find(grupo[14])

						Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Pagamento', gerador_id: pagamento.id, codigo_da_conta: codigo_da_conta_filtro).update_all(validado: true)

						total_do_pagamento = pagamento.valor
						total_estornado = pagamento.estorno_de_pagamento.present? ? pagamento.valor : 0

						total_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [pagamento.estorno_de_pagamento&.id])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [pagamento.estorno_de_pagamento&.id])
							.update_all(validado: true)

						saldo = total_do_pagamento - total_estornado

						verificacao = verificacao + [grupo[14], grupo[15], total_do_pagamento.try(:contabil).to_s.gsub(".", ""), movimentacoes.sum(&:valor).try(:contabil).to_s.gsub(".", ""), (total_do_pagamento - movimentacoes.sum(&:valor)).try(:contabil).to_s.gsub(".", ""), total_estornado.try(:contabil).to_s.gsub(".", ""), total_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_estornado - total_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), saldo.try(:contabil).to_s.gsub(".", "")]
					
					elsif grupo[15] == 'Contabilidade::CancelamentoDeRestoAPagar'
						saldo = 0.0
						movimentacoes.each do |movimentacao|
							if (restos_a_pagar == 'processado' && movimentacao.gerador.processado?) || (restos_a_pagar == 'nao_processado' && movimentacao.gerador.nao_processado?)
								saldo += movimentacao.valor.to_d
							end
						end
					end

					if saldo > 0
						movimentacao = self.gerar_movimentacao(evento, conta1, saldo, data_de_lancamento, tipo_de_lancamento_1, grupo, nil, :encerramento)
						movimentacao2 = self.gerar_movimentacao(evento, conta2, saldo, data_de_lancamento, tipo_de_lancamento_2, grupo, movimentacao, :encerramento) if movimentacao.present?
						verificacao = verificacao + [movimentacao.try(:valor).try(:contabil).to_s.gsub(".", ""), (saldo - movimentacao.try(:valor).to_d).try(:contabil).to_s.gsub(".", "")]
					else
						verificacao = verificacao + ['N', 'N']
					end

					csv << verificacao

					bar.inc
				end

				bar.finished

			end

			gerar_arquivo(codigo_da_conta_debito, codigo_da_conta_credito, csv_string)
		end

		conta1.update_column(:saldo, conta1.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
		conta2.update_column(:saldo, conta2.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	end

	def encerrar_conta_pcasp_por_empenho(evento, codigo_da_conta_debito, codigo_da_conta_credito, tipo_de_orcamento, classe_do_movimento)
		conta1 = self.orcamento.contas.where(codigo: codigo_da_conta_debito).first
		conta2 = self.orcamento.contas.where(codigo: codigo_da_conta_credito).first

		saldo_conta = conta1.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
		tipo_de_saldo_conta = conta1.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
		movimentacoes = conta1.movimentacoes_do_plano_de_contas

		
		if saldo_conta != 0
			movimentacoes = movimentacoes.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).where(gerador_type: classe_do_movimento).where("coalesce(lancamento_manual, 0) != 1000").all

			data_de_lancamento = Date.new(self.orcamento.exercicio.to_i, 12, 31)

			grupos = movimentacoes.group_by{ |i| [
				i.tipo_de_lancamento,
				i.unidade_orcamentaria, 
				i.sub_conta_pcasp,
				i.ic_po,
				i.ic_fp,
				i.ic_dc,
				i.ic_fr,
				i.ic_co,
				i.ic_cf,
				i.ic_nr,
				i.ic_nd,
				i.ic_fs,
				i.ic_es,
				i.ic_ai,
				i.gerador_id,
				i.gerador_type
			] }

			puts "ENCERRANDO PAR DE CONTAS PCASP #{conta1.codigo} - #{conta2.codigo}"
			bar = RakeProgressbar.new(grupos.size)

			grupos.each do |grupo, movimentacoes|
				if grupo[15] == 'Contabilidade::Empenho'
					empenhos_para_fechamento_pcasp = EmpenhoParaFechamentoPcasp.where(tipo: tipo_de_orcamento).where("empenho_id = #{grupo[14]} and liquidacao_id is null")
					#Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Empenho', gerador_id: grupo[14], codigo_da_conta: codigo_da_conta_debito).update_all(validado: true)
				elsif grupo[15] == 'Contabilidade::Liquidacao'
					empenhos_para_fechamento_pcasp = EmpenhoParaFechamentoPcasp.where(tipo: tipo_de_orcamento).where("liquidacao_id = #{grupo[14]} and pagamento_id is null")
					#Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Liquidacao', gerador_id: grupo[14], codigo_da_conta: codigo_da_conta_debito).update_all(validado: true)

					# liquidacao = Contabilidade::Liquidacao.find(grupo[14])
					# grupo[14] = liquidacao.empenho_id
					# grupo[15] = 'Contabilidade::Empenho'
				elsif grupo[15] == 'Contabilidade::Pagamento'
					empenhos_para_fechamento_pcasp = EmpenhoParaFechamentoPcasp.where(tipo: tipo_de_orcamento).where("pagamento_id = #{grupo[14]}")
					#Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Pagamento', gerador_id: grupo[14], codigo_da_conta: codigo_da_conta_debito).update_all(validado: true)

					# pagamento = Contabilidade::Pagamento.find(grupo[14])
					# grupo[14] = pagamento.liquidacao.empenho_id
					# grupo[15] = 'Contabilidade::Empenho'
				end



				if tipo_de_orcamento.present?
					
					empenhos_para_fechamento_pcasp.where(tipo: tipo_de_orcamento).each do |empenho_para_fechamento_pcasp|
						saldo = empenho_para_fechamento_pcasp.saldo.to_d
						if saldo > 0
							tipo_de_lancamento_1 = grupo[0] == 0 ? :credito : :debito
							tipo_de_lancamento_2 = tipo_de_lancamento_1 == :credito ? :debito : :credito
							movimentacao = self.gerar_movimentacao(evento, conta1, saldo, data_de_lancamento, tipo_de_lancamento_1, grupo, nil, :encerramento)
							movimentacao2 = self.gerar_movimentacao(evento, conta2, saldo, data_de_lancamento, tipo_de_lancamento_2, grupo, movimentacao, :encerramento) if movimentacao.present?
						end
					end
				end

				bar.inc
			end

			bar.finished

		end

		conta1.update_column(:saldo, conta1.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
		conta2.update_column(:saldo, conta2.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	end

	def encerrar_conta_pcasp_de_restos_a_pagar(evento, codigo_da_conta_debito, codigo_da_conta_credito, classe_do_movimento, conta_a_verificar = 1, condicao_orcamento = nil, filtrar_data = true, restos_a_pagar = nil)
		conta1 = self.orcamento.contas.where(codigo: codigo_da_conta_debito).first
		conta2 = self.orcamento.contas.where(codigo: codigo_da_conta_credito).first

		if conta_a_verificar == 1
			saldo_conta = conta1.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
			tipo_de_saldo_conta = conta1.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
			movimentacoes = conta1.movimentacoes_do_plano_de_contas
			codigo_da_conta_filtro = codigo_da_conta_debito
		else
			saldo_conta = conta2.saldo_da_conta(Date.new(self.orcamento.exercicio, 12, 31)).to_d
			tipo_de_saldo_conta = conta2.tipo_de_saldo(Date.new(self.orcamento.exercicio, 12, 31))
			movimentacoes = conta2.movimentacoes_do_plano_de_contas
			codigo_da_conta_filtro = codigo_da_conta_credito
		end

		if saldo_conta != 0
			csv_string = CSV.generate(col_sep: ";", quote_char: '"', force_quotes: true) do |csv|

				if classe_do_movimento == 'Contabilidade::Empenho'
					csv << ["ID", "CLASSE", "VALOR", "VALOR EM EVENTOS", "DIFERENCA 1", "ANULADO", "ANUL EM EVENTOS", "DIFERENCA 2", "LIQUIDADO", "LIQ EM EVENTOS", "DIFERENCA 3", "LIQ ANULADO", "LIQ ANUL EM EVENTOS", "DIFERENCA 4", "SALDO DO EMP", "VALOR EVENTO GERADO", "DIFERENCA 5"]
				end

				if classe_do_movimento == 'Contabilidade::Liquidacao'
					csv << ["ID", "CLASSE", "VALOR", "VALOR EM EVENTOS", "DIFERENCA 1", "ANULADO", "ANUL EM EVENTOS", "DIFERENCA 2", "PAGAMENTO", "PAG EM EVENTOS", "DIFERENCA 3", "EST PAGAMENTO", "EST PAG EM EVENTOS", "DIFERENCA 4", "SALDO DA LIQ", "VALOR EVENTO GERADO", "DIFERENCA 5"]
				end

				if classe_do_movimento == 'Contabilidade::Pagamento'
					csv << ["ID", "CLASSE", "VALOR", "VALOR EM EVENTOS", "DIFERENCA 1", "ANULADO", "ANUL EM EVENTOS", "DIFERENCA 2", "SALDO DO PAG", "VALOR EVENTO GERADO", "DIFERENCA 3"]
				end

				if classe_do_movimento == 'Contabilidade::Empenho' && condicao_orcamento != nil
					movimentacoes = movimentacoes.joins("left join contabilidade_empenhos on gerador_id = contabilidade_empenhos.id")
						.joins("left join orcamentos on contabilidade_empenhos.orcamento_id = orcamentos.id")
						.where(condicao_orcamento)
						.where(gerador_type: classe_do_movimento)
						.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).all
				else
					if filtrar_data == true
						movimentacoes = movimentacoes
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(gerador_type: classe_do_movimento).all
					else
						movimentacoes = movimentacoes.where(gerador_type: classe_do_movimento).where("coalesce(lancamento_manual, 0) != 1000")
					end
				end

				data_de_lancamento = Date.new(self.orcamento.exercicio.to_i, 12, 31)

				grupos = movimentacoes.group_by{ |i| [
					i.tipo_de_lancamento,
					i.unidade_orcamentaria, 
					i.sub_conta_pcasp,
					i.ic_po,
					i.ic_fp,
					i.ic_dc,
					i.ic_fr,
					i.ic_co,
					i.ic_cf,
					i.ic_nr,
					i.ic_nd,
					i.ic_fs,
					i.ic_es,
					i.ic_ai,
					i.gerador_id,
					i.gerador_type
					] }

				puts "ENCERRANDO PAR DE CONTAS PCASP #{conta1.codigo} - #{conta2.codigo}"
				bar = RakeProgressbar.new(grupos.size)

				grupos.each do |grupo, movimentacoes|
					verificacao = []

					tipo_de_lancamento_1 = grupo[0] == 0 ? :credito : :debito
					tipo_de_lancamento_2 = tipo_de_lancamento_1 == :credito ? :debito : :credito

					if grupo[15] == 'Contabilidade::Empenho' && restos_a_pagar == 'liquidado e nao pago'
						empenho = Contabilidade::Empenho.find(grupo[14])

						liquidacoes = empenho.liquidacoes.where("data_da_liquidacao between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).confirmadas_ate_autorizadas.nao_estornada
						
						total_liquidado = liquidacoes.sum(:valor)

						total_pago = liquidacoes.inject(0) { |sum, liquidacao| sum + liquidacao.pagamentos.confirmados_ou_superior.sum(:valor) }

						saldo = total_liquidado - total_pago

					elsif grupo[15] == 'Contabilidade::Empenho' && restos_a_pagar == 'nao liquidado nao processado'
						empenho = Contabilidade::Empenho.find(grupo[14])

						liquidacoes = empenho.liquidacoes.where("data_da_liquidacao between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).confirmadas_ate_autorizadas.nao_estornada

						total_liquidado = liquidacoes.sum(:valor).to_d

						valor_cancelado = Contabilidade::RestoAPagarCancelado.joins(:cancelamento_de_resto_a_pagar).where(empenho_id: empenho.id).where("contabilidade_cancelamentos_de_restos_a_pagar.tipo = 0").sum(:valor_cancelado).to_d

						saldo = empenho.valor_nao_processado(self.orcamento).to_d - total_liquidado - valor_cancelado

					elsif grupo[15] == 'Contabilidade::Empenho' && restos_a_pagar == 'nao liquidado processado'
						empenho = Contabilidade::Empenho.find(grupo[14])

						liquidacoes = empenho.liquidacoes.where("data_da_liquidacao < ?", Date.new(self.orcamento.exercicio.to_i, 1, 1)).confirmadas_ate_autorizadas.nao_estornada

						valor_cancelado = Contabilidade::RestoAPagarCancelado.joins(:cancelamento_de_resto_a_pagar).where(empenho_id: empenho.id).where("contabilidade_cancelamentos_de_restos_a_pagar.tipo = 1").sum(:valor_cancelado).to_d

						total_pago = liquidacoes.inject(0) { |sum, liquidacao| sum + liquidacao.pagamentos.where("data between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31)).confirmados_ou_superior.sum(:valor) }

						saldo = empenho.valor_processado(self.orcamento).to_d - total_pago - valor_cancelado

					elsif grupo[15] == 'Contabilidade::Empenho'
						empenho = Contabilidade::Empenho.find(grupo[14])

						Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Empenho', gerador_id: empenho.id, codigo_da_conta: codigo_da_conta_filtro).update_all(validado: true)

						total_do_empenho = empenho.definir_valor_do_empenho
						total_anulado = empenho.anulacoes_do_empenho.confirmados.sum(:valor)

						# nao lembro o motivo, influencia negativamente no fechamento da conta 622130100
						total_do_empenho_tipo_invertido = 0 #Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Empenho', gerador_id: empenho.id, codigo_da_conta: codigo_da_conta_filtro, tipo_de_lancamento: tipo_de_lancamento_2).sum(:valor).to_d

						total_anulado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::AnulacaoDoEmpenho', gerador_id: [empenho.anulacoes_do_empenho.pluck(:id)])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::AnulacaoDoEmpenho', gerador_id: [empenho.anulacoes_do_empenho.pluck(:id)])
							.update_all(validado: true)

						total_liquidado = empenho.liquidacoes.confirmadas_ate_autorizadas.sum(:valor)

						total_liquidado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Liquidacao', gerador_id: [empenho.liquidacoes.pluck(:id)])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Liquidacao', gerador_id: [empenho.liquidacoes.pluck(:id)])
							.update_all(validado: true)

						total_liquidado_estornado = empenho.liquidacoes.map { |liquidacao| liquidacao.valor if liquidacao.estorno_de_liquidacao.present? }.compact.sum.to_d

						total_liquidado_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [empenho.liquidacoes.map { |liquidacao| liquidacao.estorno_de_liquidacao&.id }.compact])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [empenho.liquidacoes.map { |liquidacao| liquidacao.estorno_de_liquidacao&.id }.compact])
							.update_all(validado: true)

						ids_de_cancelamento = Contabilidade::RestoAPagarCancelado.where(empenho_id: empenho.id).map { |i| i.cancelamento_de_resto_a_pagar_id }
						total_de_restos_cancelados_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::CancelamentoDeRestoAPagar', gerador_id: [ids_de_cancelamento])
							.sum(:valor).to_d

						saldo = total_do_empenho - total_do_empenho_tipo_invertido - total_anulado - total_liquidado + total_liquidado_estornado - total_de_restos_cancelados_em_movimentos

						if restos_a_pagar == 'nao processado'
							total_pago = empenho.liquidacoes.confirmadas_ate_autorizadas.inject(0) { |sum, liquidacao| sum + liquidacao.pagamentos.confirmados_ou_superior.sum(:valor) }

							saldo = saldo - total_pago
						end

						verificacao = verificacao + [grupo[14], grupo[15], total_do_empenho.try(:contabil).to_s.gsub(".", ""), movimentacoes.sum(&:valor).try(:contabil).to_s.gsub(".", ""), (total_do_empenho - movimentacoes.sum(&:valor)).try(:contabil).to_s.gsub(".", ""), total_anulado.try(:contabil).to_s.gsub(".", ""), total_anulado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_anulado - total_anulado_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_liquidado.try(:contabil).to_s.gsub(".", ""), total_liquidado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_liquidado - total_liquidado_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_liquidado_estornado.try(:contabil).to_s.gsub(".", ""), total_liquidado_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_liquidado_estornado - total_liquidado_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), saldo.try(:contabil).to_s.gsub(".", "")]

					elsif grupo[15] == 'Contabilidade::Liquidacao'
						liquidacao = Contabilidade::Liquidacao.find(grupo[14])

						Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Liquidacao', gerador_id: liquidacao.id, codigo_da_conta: codigo_da_conta_filtro).update_all(validado: true)

						total_da_liquidacao = liquidacao.valor
						total_estornado = liquidacao.estorno_de_liquidacao.present? ? liquidacao.valor : 0

						total_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [liquidacao.estorno_de_liquidacao&.id])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDeLiquidacao', gerador_id: [liquidacao.estorno_de_liquidacao&.id])
							.update_all(validado: true)

						total_pago = liquidacao.pagamentos.confirmados_ou_superior_com_estornados.sum(:valor)

						total_pago_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Pagamento', gerador_id: [liquidacao.pagamentos.pluck(:id)])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::Pagamento', gerador_id: [liquidacao.pagamentos.pluck(:id)])
							.update_all(validado: true)

						total_pago_estornado = liquidacao.pagamentos.map { |pagamento| pagamento.valor if pagamento.estorno_de_pagamento.present? }.compact.sum.to_d

						total_pago_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [liquidacao.pagamentos.map { |pagamento| pagamento.estorno_de_pagamento&.id }.compact])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [liquidacao.pagamentos.map { |pagamento| pagamento.estorno_de_pagamento&.id }.compact])
							.update_all(validado: true)

						saldo = total_da_liquidacao - total_estornado - total_pago + total_pago_estornado

						verificacao = verificacao + [grupo[14], grupo[15], total_da_liquidacao.try(:contabil).to_s.gsub(".", ""), movimentacoes.sum(&:valor).try(:contabil).to_s.gsub(".", ""), (total_da_liquidacao - movimentacoes.sum(&:valor)).try(:contabil).to_s.gsub(".", ""), total_estornado.try(:contabil).to_s.gsub(".", ""), total_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_estornado - total_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_pago.try(:contabil).to_s.gsub(".", ""), total_pago_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_pago - total_pago_em_movimentos).try(:contabil).to_s.gsub(".", ""), total_pago_estornado.try(:contabil).to_s.gsub(".", ""), total_pago_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_pago_estornado - total_pago_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), saldo.try(:contabil).to_s.gsub(".", "")]
					elsif grupo[15] == 'Contabilidade::Pagamento'
						pagamento = Contabilidade::Pagamento.find(grupo[14])

						Contabilidade::MovimentacaoDoPlanoDeContas.where(gerador_type: 'Contabilidade::Pagamento', gerador_id: pagamento.id, codigo_da_conta: codigo_da_conta_filtro).update_all(validado: true)

						total_do_pagamento = pagamento.valor
						total_estornado = pagamento.estorno_de_pagamento.present? ? pagamento.valor : 0

						total_estornado_em_movimentos = Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [pagamento.estorno_de_pagamento&.id])
							.sum(:valor).to_d

						Contabilidade::MovimentacaoDoPlanoDeContas
							.where("data_de_lancamento between ? and ?", Date.new(self.orcamento.exercicio.to_i, 1, 1), Date.new(self.orcamento.exercicio.to_i, 12, 31))
							.where(codigo_da_conta: codigo_da_conta_filtro, gerador_type: 'Contabilidade::EstornoDePagamento', gerador_id: [pagamento.estorno_de_pagamento&.id])
							.update_all(validado: true)

						saldo = total_do_pagamento - total_estornado

						verificacao = verificacao + [grupo[14], grupo[15], total_do_pagamento.try(:contabil).to_s.gsub(".", ""), movimentacoes.sum(&:valor).try(:contabil).to_s.gsub(".", ""), (total_do_pagamento - movimentacoes.sum(&:valor)).try(:contabil).to_s.gsub(".", ""), total_estornado.try(:contabil).to_s.gsub(".", ""), total_estornado_em_movimentos.try(:contabil).to_s.gsub(".", ""), (total_estornado - total_estornado_em_movimentos).try(:contabil).to_s.gsub(".", ""), saldo.try(:contabil).to_s.gsub(".", "")]
					
					elsif grupo[15] == 'Contabilidade::CancelamentoDeRestoAPagar'
						saldo = movimentacoes.sum(&:valor).to_d
					end

					if saldo > 0
						movimentacao = self.gerar_movimentacao(evento, conta1, saldo, data_de_lancamento, tipo_de_lancamento_1, grupo, nil, :encerramento)
						movimentacao2 = self.gerar_movimentacao(evento, conta2, saldo, data_de_lancamento, tipo_de_lancamento_2, grupo, movimentacao, :encerramento) if movimentacao.present?

						verificacao = verificacao + [movimentacao.try(:valor).try(:contabil).to_s.gsub(".", ""), (saldo - movimentacao.try(:valor).to_d).try(:contabil).to_s.gsub(".", "")]
					else
						verificacao = verificacao + ['N', 'N']
					end

					csv << verificacao

					bar.inc
				end

				bar.finished

			end

			gerar_arquivo(codigo_da_conta_debito, codigo_da_conta_credito, csv_string)
		end

		conta1.update_column(:saldo, conta1.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
		conta2.update_column(:saldo, conta2.saldo_da_conta("#{orcamento.exercicio.to_i}-12-31"))
	end

	def gerar_movimentacao(evento, conta, valor, data_de_lancamento, tipo_de_lancamento, grupo, movimentacao_par = nil, tipo_de_lancamento_manual)
		conta_por_evento_contabil = evento.contas_por_eventos_contabeis.where(conta_id: conta.id, tipo_de_lancamento: tipo_de_lancamento).first

		if conta_por_evento_contabil.present?
			movimentacao = Contabilidade::MovimentacaoDoPlanoDeContas.new(
				conta_por_evento_contabil_id: conta_por_evento_contabil.id,
				valor: valor.abs,
				data_de_lancamento: data_de_lancamento,
				tipo_de_lancamento: tipo_de_lancamento,
				unidade_orcamentaria_id: grupo[1]&.id,
				sub_conta_pcasp_id: grupo[2]&.id,
				categoria_de_lancamento: :regular,
				lancamento_manual: tipo_de_lancamento_manual,
				ic_po: grupo[3],
				ic_fp: grupo[4],
				ic_dc: grupo[5],
				ic_fr: grupo[6],
				ic_co: grupo[7],
				ic_cf: grupo[8],
				ic_nr: grupo[9],
				ic_nd: grupo[10],
				ic_fs: grupo[11],
				ic_es: grupo[12],
				ic_ai: grupo[13],
				gerador_id: grupo[14],
				gerador_type: grupo[15],
				movimentacao_par_id: movimentacao_par&.id,
				codigo_da_conta: conta.codigo,
				skip_geracao_credito: true,
				historico: "#{evento.nome}"
			)
			if movimentacao.save(validate: false)
				if movimentacao_par.present?
					movimentacao_par.movimentacao_par_id = movimentacao.id
					movimentacao_par.save(validate: false)
				end


				return movimentacao
			end
		end
	end

	def criar_evento(orcamento, nome, conta_debito, conta_credito)

		evento = orcamento.eventos_contabeis.where(nome: nome).first

		unless evento.present?
			evento = orcamento.eventos_contabeis.create(
				nome: nome,
				padrao: false,
				tipo: 1,
				classe: 50,
				fixo: false,
				modelo: 9
			)
		end

		criar_par_de_contas(orcamento, evento, conta_debito, conta_credito)

		return evento
	end

	def criar_par_de_contas(orcamento, evento, conta_debito, conta_credito)
		conta_debito = orcamento.contas.where(codigo: conta_debito).first
		conta_credito = orcamento.contas.where(codigo: conta_credito).first

		contador = evento.contas_por_eventos_contabeis.order(:ordem_de_lancamento).last&.ordem_de_lancamento.to_i
		contador = 1 if contador == 0

		if conta_debito.present? && conta_credito.present?
			conta_por_evento_debito = evento.contas_por_eventos_contabeis.where(conta_id: conta_debito.id, tipo_de_lancamento: :debito, conta_par_id: conta_credito.id).first

			unless conta_por_evento_debito.present?
				evento.contas_por_eventos_contabeis.create(
					conta_id: conta_debito.id,
					tipo_de_lancamento: :debito,
					conta_par_id: conta_credito.id,
					ordem_de_lancamento: contador,
					conta_principal: true,
					gerar_conta_par: false
				)
			end

			conta_por_evento_credito = evento.contas_por_eventos_contabeis.where(conta_id: conta_credito.id, tipo_de_lancamento: :credito, conta_par_id: conta_debito.id).first

			unless conta_por_evento_credito.present?
				evento.contas_por_eventos_contabeis.create(
					conta_id: conta_credito.id,
					tipo_de_lancamento: :credito,
					conta_par_id: conta_debito.id,
					ordem_de_lancamento: contador + 1,
					conta_principal: true,
					gerar_conta_par: false
				)
			end
		end
	end

	def gerar_arquivo(conta1, conta2, texto)
		nome_arquivo = "encerramento_#{conta1}_#{conta2}.csv"
		pasta_temporaria = Rails.root.join('tmp') # Caminho para a pasta temporAria do Rails
		caminho_arquivo = pasta_temporaria.join(nome_arquivo)
		File.delete(caminho_arquivo) if File.exist?(caminho_arquivo)
		File.write(caminho_arquivo, texto, mode: 'a:UTF-8')
	end

end
