#!/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
from ponto.models import Comentario
######################################
# 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 >= 1:
batida_entrada_manha = batidas_do_dia[0].momento_batidaponto
if quantidade_batidas_do_dia >= 2:
batida_saida_manha = batidas_do_dia[1].momento_batidaponto
if quantidade_batidas_do_dia >= 3:
batida_entrada_tarde = batidas_do_dia[2].momento_batidaponto
if quantidade_batidas_do_dia >= 4:
batida_saida_tarde = batidas_do_dia[3].momento_batidaponto
"""
if quantidade_batidas_do_dia > 1:
batidas_antes_intervalo_almoco = []
batidas_depois_intervalo_almoco = []
for bd in batidas_do_dia:
if bd.momento_batidaponto < intervalo_almoco:
batidas_antes_intervalo_almoco.append(bd.momento_batidaponto)
else:
batidas_depois_intervalo_almoco.append(bd.momento_batidaponto)
batidas_antes_intervalo_almoco.sort()
batidas_depois_intervalo_almoco.sort()
if len(batidas_antes_intervalo_almoco) == 1:
batida_entrada_manha = batidas_antes_intervalo_almoco[0]
elif len(batidas_antes_intervalo_almoco) > 1:
batida_entrada_manha = batidas_antes_intervalo_almoco[0]
batida_saida_manha = batidas_antes_intervalo_almoco[-1]
if len(batidas_depois_intervalo_almoco) == 1:
batida_entrada_tarde = batidas_depois_intervalo_almoco[0]
elif len(batidas_depois_intervalo_almoco) > 1:
batida_entrada_tarde = batidas_depois_intervalo_almoco[0]
batida_saida_tarde = batidas_depois_intervalo_almoco[-1]
"""
"""
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:
batidas_antes_intervalo_almoco = []
batidas_depois_intervalo_almoco = []
for bd in batidas_do_dias:
if bd.momento_batidaponto < intervalo_almoco:
batidas_antes_intervalo_almoco.append(bd)
else:
batidas_depois_intervalo_almoco.append(bd)
if batidas_do_dia[0].momento_batidaponto < intervalo_almoco
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)
if batida_entrada_manha and batida_saida_manha:
# Para limitar o horário de entrada
horario_entrada = batida_entrada_manha.time()
if horario_entrada < funcionario.horario_inicial_entrada:
batida_entrada_manha = datetime.combine(data, funcionario.horario_inicial_entrada)
horas_trabalhadas_manha = batida_saida_manha - batida_entrada_manha
tempo_total_dia += horas_trabalhadas_manha
if batida_entrada_tarde and batida_saida_tarde:
# Para limitar o horário de saída
horario_saida = batida_saida_tarde.time()
if horario_saida > funcionario.horario_final_saida:
batida_saida_tarde = datetime.combine(data, funcionario.horario_final_saida)
horas_trabalhadas_tarde = batida_saida_tarde - batida_entrada_tarde
tempo_total_dia += horas_trabalhadas_tarde
try:
comentario = Comentario.objects.get(funcionario=funcionario, data=data)
if comentario.aprovado:
tempo_gasto = comentario.tempo_gasto
horas = tempo_gasto.hour
minutos = tempo_gasto.minute
segundos = tempo_gasto.second
tempo_gasto_timedelta = timedelta(0,segundos,0,0,minutos,horas,0)
tempo_total_dia += tempo_gasto_timedelta
except ObjectDoesNotExist:
pass
"""
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.date() <= data_atual.date():
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.date() < data_atual.date():
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_semana_durante_mes(funcionario, mes, ano):
limites_mes = monthrange(ano, mes)
primeiro_dia_mes = date(ano, mes, limites_mes[0])
ultimo_dia_mes = date(ano, mes, limites_mes[1])
primeira_data = primeiro_dia_mes
resumos = []
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_temp = primeira_data
while data_temp < ultimo_dia_mes:
horas_trabalhadas = calcular_horas_trabalhadas_semana(funcionario, data_temp)
resumo_semanal = ResumoSemanal(data_temp, 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.strftime("%H:%M:%S")
if batida_saida_manha:
self.batida_saida_manha = batida_saida_manha.strftime("%H:%M:%S")
if batida_entrada_tarde:
self.batida_entrada_tarde = batida_entrada_tarde.strftime("%H:%M:%S")
if batida_saida_tarde:
self.batida_saida_tarde = batida_saida_tarde.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