Skip to content

Instantly share code, notes, and snippets.

@ricardosiri68
Last active April 15, 2016 01:39
Show Gist options
  • Save ricardosiri68/a4261900fa011904f15b to your computer and use it in GitHub Desktop.
Save ricardosiri68/a4261900fa011904f15b to your computer and use it in GitHub Desktop.

Como se usa

En linux

./main.py <yyyy-mm>

ej (recuperando los registro de marzo del 2016):

./main.py 2016-03

En windows (tambien en linux)

python main.py <yyyy-mm>

ej (recuperando los registro de marzo del 2016):

python main.py 2016-03

salida o resultado

  ID |                          NOMBRE COMPLETO |  C. HORAS | MONTO/UNIDAD | SUELDO A COBRAR
--------------------------------------------------------------------------------------------
0001 |                           Carlyn Yeldell |         1 | $  10.000,00 | $  10.000,00
0002 |                            Darci Simkins |         1 | $  10.000,00 | $  10.000,00
0003 |                             Alison Penna |         1 | $  10.000,00 | $  10.000,00
0004 |                          Tammi Mcfarland |       102 | $      50,00 | $   5.100,00
0005 |                           Johnna Arehart |       122 | $      86,00 | $  10.492,00
0006 |                             Anitra Saleh |       116 | $      50,00 | $   5.800,00
0007 |                             Daine Boutte |       121 | $      70,00 | $   8.470,00
0008 |                            Judie Dejonge |       106 | $      75,00 | $   7.950,00
0009 |                               Pierre Apo |         0 | $       0,00 | $       0,00
0010 |                              Beau Nunley |         0 | $       0,00 | $       0,00
id first_name last_name age salary_type amount
1 Carlyn Yeldell 22 m 10000
2 Darci Simkins 21 m 10000
3 Alison Penna 20 m 10000
4 Tammi Mcfarland 23 h 50
5 Johnna Arehart 40 h 86
6 Anitra Saleh 50 h 50
7 Daine Boutte 19 h 70
8 Judie Dejonge 50 h 75
9 Pierre Apo 22 v
10 Beau Nunley 30 v
year_month week_num employee_id cant_hours
2016-03 1 4 21
2016-03 2 4 36
2016-03 3 4 20
2016-03 4 4 25
2016-03 1 5 30
2016-03 2 5 36
2016-03 3 5 17
2016-03 4 5 39
2016-03 1 6 19
2016-03 2 6 20
2016-03 3 6 40
2016-03 4 6 37
2016-03 1 7 40
2016-03 2 7 23
2016-03 3 7 36
2016-03 4 7 22
2016-03 1 8 37
2016-03 2 8 23
2016-03 3 8 33
2016-03 4 8 13
2016-02 1 4 21
2016-02 2 4 36
2016-02 3 4 20
2016-02 4 4 25
2016-02 1 5 30
2016-02 2 5 36
2016-02 3 5 17
#!/usr/bin/env python
import sys
import locale
from object_collections import Employees
locale.setlocale(locale.LC_ALL, 'es_AR')
def main(year_month):
header = "%04s | %40s | %9s | %12s | %s" % ('ID', 'NOMBRE COMPLETO',
'C. HORAS', 'MONTO/UNIDAD',
'SUELDO A COBRAR')
print(header)
print("-" * len(header))
for e in Employees.liquidate_salaries(year_month):
row = "%(id)04d | %(fullname)40s | %(cant_hours)9d | $ "
row += "%(amount)s | $ %(salary_collect)s"
print(row % {
'id': e.id,
'fullname': e.fullname,
'cant_hours': e.cant_hours,
'amount': locale.format('%10.2f', e.amount, grouping=True),
'salary_collect': locale.format('%10.2f', e.salary_collect,
grouping=True)
})
if __name__ == '__main__': # espero que no cuenten esto como un if :$
main(sys.argv[1])
class Model(object):
'''modelo de datos base'''
def __init__(self, item, collection):
self.__collection = collection
@property
def collection(self):
'''instancia de colleccion padre a la que se encuentra vinculado el
modelo'''
return self.__collection
class Employee(Model):
'''modelo de datos del empleado'''
def __init__(self, item, collection):
super().__init__(item, collection)
self.__id = int(item['id'])
self.__first_name = item['first_name']
self.__last_name = item['last_name']
self.__age = item['age']
self.__salary_type = item['salary_type']
self.__amount = float(item.get('amount') or 0)
def week_hours(self):
'''recupera/genera las hs trabajadas cada semana del mes y luego las
suma'''
return sum(record.hours for record in
self.collection.week_hours.get_by_employee(self.id))
# este diccionario mapea los metodos que recuperarn el modo de operar el
# monto que se le asigna a un empleado
SALARY_OPTION = {
'm': lambda x: 1, # multiplo de hs de un empleado con sueldo fijo
'v': lambda x: 0, # multiplo de hs de un voluntario (sin sueldo)
'h': week_hours
}
@property
def cant_hours(self):
'''recupera la contidad de hs trabajadas por un empleado, si es
<<voluntario>> son 0 hs, si cobra <<sueldo fijo>> es 1 y en ultimo caso
devuelve la <<suma semanal>> de su jornadas'''
return self.SALARY_OPTION[self.salary_type](self)
@property
def salary_collect(self):
'''importe del sueldo a cobrar del empleado'''
return self.cant_hours * self.amount
@property
def id(self):
'''numero identificador del empleado o legajo'''
return self.__id
@property
def fist_name(self):
'''nombre'''
return self.__first_name
@property
def last_name(self):
'''apellido'''
return self.__last_name
@property
def fullname(self):
'''nombre compledo'''
return "%s %s" % (self.fist_name, self.last_name)
@property
def age(self):
'''edad'''
return self.__age
@property
def salary_type(self):
'''tipo del suelo: m (fijo mensual), h (suma de horas semanales),
v (voluntario)'''
return self.__salary_type
@property
def amount(self):
'''monto unitario del sueldo ya sea por hora o mensual'''
return self.__amount
class WeekHour(Model):
'''modelo de datos de un registro de las horas hechas en una semana'''
def __init__(self, item, collection):
super().__init__(item, collection)
self.__year_month = item['year_month']
self.__week_num = int(item['week_num'])
self.__employee_id = int(item['employee_id'])
self.__cant_hours = int(item['cant_hours'])
@property
def year_month(self):
'''formato yyyy-mm del anio al que pertenece esta suma semanal de
horas'''
return self.__year_month
@property
def week_num(self):
'''numero de la semana a la que pertenece'''
return self.__week_num
@property
def employee(self):
'''numero id del empleado al que pertenece el registro horario
semanal'''
return self.__employee_id
@property
def hours(self):
'''cantidad de horas detalladas'''
return self.__cant_hours
import re
import csv
from models import Employee, WeekHour
class CSVCollection(object):
'''colleccion que recupera los datos y genera los modelos desde una entrada
CSV'''
csv_name = None
model_class = None
def __init__(self):
assert self.model_class is not None,\
Exception('No se le asigno un tipo de modelo')
assert self.csv_name is not None,\
Exception('No se le asigno la ruta de un *.CSV')
with open(self.csv_name, 'r') as csv_file:
self.items = [self.model_class(item, self) for item in
csv.DictReader(csv_file)]
def __len__(self):
return len(self.items)
def __iter__(self):
for item in self.items:
yield item
def __getitem__(self, key):
return self.items[key]
class Employees(CSVCollection):
'''colleccion de instancias de models.Employee'''
week_hours = None
csv_name = 'empleados.csv'
model_class = Employee
def __init__(self):
assert self.week_hours is not None,\
Exception('Necesita instancia de la collecion WeekHours')
super().__init__()
def get_by_pk(self, pk):
'''recupera el empleado segun su clave id (pk)'''
return list(filter(lambda x: x.id == pk, self))[0]
@classmethod
def liquidate_salaries(cls, year_month):
'''asigna a la clase una instancia de liquidacion de horas semanales de
un mes determinado en year_month (yyyy-mm)'''
cls.week_hours = WeekHours(year_month)
return cls()
class WeekHours(CSVCollection):
'''coleccion de instancias de models.WeekHour'''
csv_name = 'horas_semanales.csv'
model_class = WeekHour
def __init__(self, year_month):
'''luego de recuperar TODOS los registros filtra aquellos que pertenecen
al mes y anio (year_month - yyyy-mm)'''
super().__init__()
assert re.match('\d{4}-\d{2}', year_month),\
Exception('El formato de entrada es yyyy-mm')
self.items = list(filter(lambda x: x.year_month == year_month,
self.items))
def get_by_employee(self, pk):
'''filtra todos los registros de liquidacion semanal de segun la id de
un empleado (pk)'''
return list(filter(lambda x: x.employee == pk, self))
#!/usr/bin/env python
import unittest
from object_collections import Employees, WeekHours
from models import Employee
class TestEmployees(unittest.TestCase):
employees = Employees.liquidate_salaries("2016-03")
def test_index(self):
'''obtener todos los empleados sin liquidar su sueldo'''
self.assertEqual(len(self.employees), 10)
def test_by_id(self):
'''obtener un empleado segun su id'''
employee = self.employees.get_by_pk(4)
self.assertIsInstance(employee, Employee)
self.assertEqual(employee.fist_name, "Tammi")
def test_liquidate_employee_hour(self):
'''empleado por suma semanal de horas'''
employee = self.employees.get_by_pk(4)
self.assertEqual(employee.salary_collect, 5100)
def test_liquidate_employee_month(self):
'''empleado con sueldo fijo por mes'''
employee = self.employees.get_by_pk(1)
self.assertEqual(employee.salary_collect, 10000)
def test_liquidate_employee_voluntary(self):
'''empleado voluntario (sin sueldo)'''
employees = self.employees.liquidate_salaries("2016-03")
employee = employees.get_by_pk(9)
self.assertEqual(employee.salary_collect, 0)
class TestWeekHours(unittest.TestCase):
week_hours = WeekHours("2016-03")
def test_index(self):
'''obtener los registros de horas trabajadas del mes de marzo del
2016'''
self.assertEqual(len(self.week_hours), 20)
def test_by_employee(self):
'''obtener todas los registros de un empleado segun su id'''
hours = self.week_hours.get_by_employee(4)
self.assertEqual(len(hours), 4)
if __name__ == '__main__': # espero que no cuenten esto como un if :$
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment