#!/usr/bin/env python # -*- coding: utf-8 -*- from models import * from django.db import IntegrityError from django.core.exceptions import ObjectDoesNotExist from datetime import datetime, timedelta, tzinfo, date import time from calendar import monthrange from string import Formatter ###################################### # FUNÇÕES GERAIS ###################################### def puxar_informacoes_henry(lista_funcionarios): # Arquivo com as saídas do Henry; arquivo = open("/mnt/henry/MeusArquivosSaida/Registros.txt.txt", 'r') # Ler todas as linhas do arquivo e fecha-o em seguida; conteudo_arquivo = arquivo.readlines() arquivo.close() formato = "%d/%m/%Y %H:%M:%S" for linha in conteudo_arquivo: # Matrícula com oito dígitos. matricula = linha.split(" ")[-1].rstrip()[12:20] # Compara matrícula do funcionário com a do arquivo. for funcionario in lista_funcionarios: if funcionario.matricula in matricula: # Data no formato 'DD/MM/AAAA'. data = linha.split(" ")[-3] # Hora no formato '00:00:00'. hora = linha.split(" ")[-2] data_hora = datetime.strptime("%s %s" %(data, hora), formato) batida_ponto = BatidaPonto() batida_ponto.funcionario = funcionario batida_ponto.momento_batidaponto = data_hora try: batida_ponto.save() except IntegrityError: pass # Sincroniza informações do Henry com o banco de dados def sincronizar(): lista_funcionarios = Funcionario.objects.all() if lista_funcionarios: puxar_informacoes_henry(lista_funcionarios) nova_sincronizacao = Sincronizacao() agora = datetime.now() nova_sincronizacao.data_hora = agora nova_sincronizacao.save() return True else: return False ###################################### # OUTRAS FUNÇÕES ÚTEIS ###################################### def strfdelta(tdelta, fmt): f = Formatter() d = {} l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1} k = map( lambda x: x[1], list(f.parse(fmt))) rem = int(tdelta.total_seconds()) for i in ('D', 'H', 'M', 'S'): if i in k and i in l.keys(): d[i], rem = divmod(rem, l[i]) return f.format(fmt, **d) ###################################### # FUNÇÕES QUE GERAM RELATÓRIOS ###################################### class ResumoDiario(): def __init__(self, data, horas): self.data = data self.horas = horas def horas_formatadas(self): return strfdelta(self.horas, "{H:02}:{M:02}:{S:02}") def data_formatada(self): return self.data.strftime("%d/%m/%Y") def organizar_batidasponto(batidas_do_dia, data): intervalo_almoco = datetime(data.year, data.month, data.day, 12, 30) quantidade_batidas_do_dia = len(batidas_do_dia) batida_entrada_manha = None batida_saida_manha = None batida_entrada_tarde = None batida_saida_tarde = None if quantidade_batidas_do_dia > 0: if quantidade_batidas_do_dia == 1: pass elif quantidade_batidas_do_dia == 2: if batidas_do_dia[0].momento_batidaponto < intervalo_almoco and batidas_do_dia[-1].momento_batidaponto < intervalo_almoco: batida_entrada_manha = batidas_do_dia[0] batida_saida_manha = batidas_do_dia[-1] elif batidas_do_dia[0].momento_batidaponto > intervalo_almoco and batidas_do_dia[-1].momento_batidaponto > intervalo_almoco: batida_entrada_tarde = batidas_do_dia[0] batida_saida_tarde = batidas_do_dia[-1] else: pass elif quantidade_batidas_do_dia == 3: if batidas_do_dia[0].momento_batidaponto < intervalo_almoco and batidas_do_dia[1].momento_batidaponto < intervalo_almoco: batida_entrada_manha = batidas_do_dia[0] batida_saida_manha = batidas_do_dia[1] elif batidas_do_dia[0].momento_batidaponto > intervalo_almoco and batidas_do_dia[1].momento_batidaponto > intervalo_almoco: batida_entrada_tarde = batidas_do_dia[0] batida_saida_tarde = batidas_do_dia[1] elif batidas_do_dia[1].momento_batidaponto < intervalo_almoco and batidas_do_dia[2].momento_batidaponto < intervalo_almoco: batida_entrada_manha = batidas_do_dia[1] batida_saida_manha = batidas_do_dia[2] elif batidas_do_dia[1].momento_batidaponto > intervalo_almoco and batidas_do_dia[2].momento_batidaponto > intervalo_almoco: batida_entrada_tarde = batidas_do_dia[1] batida_saida_tarde = batidas_do_dia[2] else: pass else: batida_entrada_manha = batidas_do_dia[0] batida_saida_tarde = batidas_do_dia[-1] for i in range(quantidade_batidas_do_dia): if batidas_do_dia[i].momento_batidaponto >= intervalo_almoco: batida_saida_manha = batidas_do_dia[i-1] batida_entrada_tarde = batidas_do_dia[i] break return batida_entrada_manha, batida_saida_manha, batida_entrada_tarde, batida_saida_tarde def calcular_horas_trabalhadas_dia(funcionario, data): batidas_do_dia = list(BatidaPonto.objects.filter(funcionario=funcionario, momento_batidaponto__day=data.day, momento_batidaponto__month=data.month, momento_batidaponto__year=data.year).order_by('momento_batidaponto')) tempo_total_dia = timedelta(0,0) batida_entrada_manha, batida_saida_manha, batida_entrada_tarde, batida_saida_tarde = organizar_batidasponto(batidas_do_dia, data) # Para limitar o horário de entrada e saídas if batida_entrada_manha: print batida_entrada_manha.momento_batidaponto.time() print funcionario.horario_inicial_entrada if batida_entrada_manha and batida_saida_manha: horas_trabalhadas_manha = batida_saida_manha.momento_batidaponto - batida_entrada_manha.momento_batidaponto tempo_total_dia += horas_trabalhadas_manha if batida_entrada_tarde and batida_saida_tarde: horas_trabalhadas_tarde = batida_saida_tarde.momento_batidaponto - batida_entrada_tarde.momento_batidaponto tempo_total_dia += horas_trabalhadas_tarde """ if(quantidade_batidas_do_dia%2==0): for i in range(0, quantidade_batidas_do_dia, 2): hora_menor = batidas_do_dia[i].momento_batidaponto hora_maior = batidas_do_dia[i+1].momento_batidaponto tempo_parcial = hora_maior - hora_menor tempo_total_dia += tempo_parcial else: for i in range(0, quantidade_batidas_do_dia-1, 2): hora_menor = batidas_do_dia[i].momento_batidaponto hora_maior = batidas_do_dia[i+1].momento_batidaponto tempo_parcial = hora_maior - hora_menor tempo_total_dia += tempo_parcial """ return tempo_total_dia def horas_trabalhadas_dia(funcionario): resumos = [] primeira_batidaponto = None try: primeira_batidaponto = BatidaPonto.objects.filter(funcionario=funcionario).earliest('momento_batidaponto') except ObjectDoesNotExist: pass if primeira_batidaponto: primeira_data = primeira_batidaponto.momento_batidaponto data_atual = datetime.now() diferenca_datas = data_atual - primeira_data quantidade_dias = diferenca_datas.days data_temp = primeira_data while data_temp <= data_atual: horas_dia = calcular_horas_trabalhadas_dia(funcionario, data_temp) resumo = ResumoDiario(data_temp.date(), horas_dia) resumos.append(resumo) data_temp += timedelta(days=1) return resumos class ResumoSemanal(): def __init__(self, domingo, horas): self.domingo = domingo self.horas = horas def horas_formatadas(self): return strfdelta(self.horas, "{H:02}:{M:02}:{S:02}") def semana_formatada(self): meses = ("Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro") domingo = self.domingo sexta_feira = self.domingo + timedelta(days=6) dia_domingo = "%d" %(domingo.day) dia_sexta = "%d" %(sexta_feira.day) if domingo.day < 10: dia_domingo = "0%d" %(domingo.day) if sexta_feira.day < 10: dia_sexta = "0%d" %(sexta_feira.day) semana = "De %s de %s de %d a %s de %s de %d" %(dia_domingo, meses[domingo.month -1], domingo.year, dia_sexta, meses[sexta_feira.month -1], sexta_feira.year) return semana def calcular_horas_trabalhadas_semana(funcionario, domingo): tempo_total_semana = timedelta(0,0) data_temp = domingo for i in range(7): tempo_total_semana += calcular_horas_trabalhadas_dia(funcionario, data_temp) data_temp += timedelta(days=1) # Retorna o tempo total da semana. return tempo_total_semana def horas_trabalhadas_semana(funcionario): resumos = [] primeira_batidaponto = None try: primeira_batidaponto = BatidaPonto.objects.filter(funcionario=funcionario).earliest('momento_batidaponto') except ObjectDoesNotExist: pass if primeira_batidaponto: primeira_data = primeira_batidaponto.momento_batidaponto data_atual = datetime.now() dia_semana = primeira_data.weekday() # Caso não seja uma domingo, ele voltará alguns dias até encontrá-la. while dia_semana != 6: primeira_data -= timedelta(days=1) dia_semana = primeira_data.weekday() data_atual = datetime.now() data_temp = primeira_data while data_temp < data_atual: horas_trabalhadas = calcular_horas_trabalhadas_semana(funcionario, data_temp) resumo_semanal = ResumoSemanal(data_temp.date(), horas_trabalhadas) resumos.append(resumo_semanal) data_temp += timedelta(days=7) return resumos def horas_trabalhadas_datas(funcionario, datas): resumos = [] tempo_total = timedelta(0,0) for data in datas: tempo_total += calcular_horas_trabalhadas_dia(funcionario,data) return strfdelta(tempo_total, "{H:02}:{M:02}:{S:02}") class RelatorioDiario(): def __init__(self, data, tempo_total_dia, batida_entrada_manha, batida_saida_manha, batida_entrada_tarde, batida_saida_tarde): self.data = data self.tempo_total_dia = tempo_total_dia if batida_entrada_manha: self.batida_entrada_manha = batida_entrada_manha.momento_batidaponto.strftime("%H:%M:%S") if batida_saida_manha: self.batida_saida_manha = batida_saida_manha.momento_batidaponto.strftime("%H:%M:%S") if batida_entrada_tarde: self.batida_entrada_tarde = batida_entrada_tarde.momento_batidaponto.strftime("%H:%M:%S") if batida_saida_tarde: self.batida_saida_tarde = batida_saida_tarde.momento_batidaponto.strftime("%H:%M:%S") def gerar_relatorio_mensal(funcionario, mes, ano): fim_do_mes = monthrange(ano, mes)[1] relatorios_diarios = [] # Percorre todos os dias do mês. for dia in range(1,fim_do_mes+1,1): batidas_formatadas = [] data = date(ano, mes, dia) data_formatada = data.strftime("%d/%m/%Y") tempo_total_dia = calcular_horas_trabalhadas_dia(funcionario, data) tempo_total_dia_formatado = strfdelta(tempo_total_dia, "{H:02}:{M:02}:{S:02}") batidas_ponto_dia = list(BatidaPonto.objects.filter(funcionario=funcionario, momento_batidaponto__month=mes, momento_batidaponto__day=dia, momento_batidaponto__year=ano)) batida_entrada_manha, batida_saida_manha, batida_entrada_tarde, batida_saida_tarde = organizar_batidasponto(batidas_ponto_dia , data) #for bp in batidas_ponto_dia: # batidas_formatadas.append(bp.momento_batidaponto.strftime("%H:%M:%S")) relatorio_diario = RelatorioDiario(data_formatada, tempo_total_dia_formatado, batida_entrada_manha, batida_saida_manha, batida_entrada_tarde, batida_saida_tarde) relatorios_diarios.append(relatorio_diario) return relatorios_diarios