Skip to content

Instantly share code, notes, and snippets.

@vsanjuan
Last active August 29, 2015 14:06
Show Gist options
  • Save vsanjuan/f668a3fbac4858f2f5d3 to your computer and use it in GitHub Desktop.
Save vsanjuan/f668a3fbac4858f2f5d3 to your computer and use it in GitHub Desktop.
Cost calculation tool
# Persistent class is imported so the Class can
# be saved later in ZODB
from persistent import Persistent
from ZODB import FileStorage, DB
import transaction
from copy import deepcopy
storage = FileStorage.FileStorage('activity_costing.fs')
db = DB(storage)
class Resource(Persistent):
"""Represents the resources used by the different activities.
Attributes:
name: Resource name.
resource_code: A unique alphanumeric that identifies the resource.
measure_unit : Unity of measure in which the resource usage and cost
is measured.
cost: Cost in Euros of the resource per measure_unit. This value is
calculated for its child from its properties.
"""
def __init__(self, name, resource_code, measure_unit, cost):
self.name = name
self.resource_code = resource_code
self.measure_unit = measure_unit
self.cost = cost
def calculate_cost():
"""Calculates the cost per unit of measure for each resource depending
of the properties of each child resource.
Args:
Defined in the child class
Returns:
A cost in Euros per measure_unit
"""
pass
class ResourceCatalogue(Persistent):
""" Represents a catalogue of the resources available and the
methods used to manage the catalogue. This class has no attributes """
def __init__(self):
connection, root = self.connect_ZODB()
try:
self.resource_catalogue = deepcopy(root.resource_catalogue)
except:
self.resource_catalogue = {}
connection.close()
def connect_ZODB(self):
"""Opens a connection to the ZODB"""
connection = db.open()
root = connection.root()
return connection, root
def save_ZODB(self, resource):
"""Saves de catalogue to the ZODB"""
connection, root = self.connect_ZODB()
self.resource_catalogue[resource.resource_code] = resource
root.resource_catalogue = self.resource_catalogue
transaction.commit()
connection.close()
def add_resource(self) :
""" Method to be implemented by the child class to add a new
resource"""
pass
def search_resource(self, resource_code = "", resource_name = ""):
"""Method to search and retrieve a resource by code or name.
If the resource is found returns a ResourceCategory object. If
not returns None."""
if resource_code in self.resource_catalogue:
return self.resource_catalogue[resource_code]
else:
return None
for resource in self.resource_catalogue.values():
if ( resource.name == resource_name) :
return resource
return None
def list_resources(self, typeofresource = None):
"""List all items included in the catalogue.
Each child from this class has its own __str__ method"""
catalogue = self.resource_catalogue.values()
print "*" * 80
print "*" * 30 + "Lista de recursos" + "*" * 33
print "*" * 80
for resource in catalogue:
if typeofresource == None:
print resource
print "*" * 80
else:
if typeofresource == type(resource):
print resource
print "*" * 80
def delete_resource(self, resource_code):
pass
class JobCatalogue(ResourceCatalogue):
"""Represent a catalogue of the different job categories from where
they can be managed and puts it in persistent ZODB storage
"""
def __init__(self):
"""Adds a new Job Category list to the root ZODB if it hasn't
been created yet. Otherwise it loads the information from the database.
"""
ResourceCatalogue.__init__(self)
def add_resource(self, job_category, resource_code, gross_salary, benefits, annual_hours, effective_working_rate):
"""Adds a new job category to the job catalogue and returns the JobCategory object
"""
new_category = JobCategory(job_category, resource_code, gross_salary, benefits, annual_hours, effective_working_rate)
# checks if the resource code is in the database. If so warns the user before committing the changes
if resource_code not in self.resource_catalogue:
#Save the new_category object
self.save_ZODB(new_category)
return new_category
else:
print "Resource {} code already exists. ".format(resource_code)
resource = self.search_resource(resource_code)
print resource
print "Please check and try again"
return new_category # The object is returned to the user to modify it.
class JobCategory(Resource):
"""Represents the different job categories employed in each activity
according to its qualifications
Attributes:
job_category: job performed.
gross_salary: annual income before taxes
benefits: annual monetary cost of extra costs as social security, health
insurance, etc..
annual_hours: yearly hours worked according to law and labour agreements.
effective_working_rate: estimated percentage of effective working hours.
Default value is 80%. The value is stored as a percentage.
"""
def __init__(self, job_category, resource_code, gross_salary, benefits, annual_hours, effective_working_rate):
"""Inits JobCategory."""
Resource.__init__(self, job_category, resource_code, "hours", 0)
self.gross_salary = gross_salary
self.benefits = benefits
self.annual_hours = annual_hours
self.effective_working_rate = effective_working_rate / 100.0
self.cost = self.calculate_cost()
def __str__(self):
return ("Resource Code: " + str(self.resource_code) +
" \nJob category: " + str(self.name) +
" \nGross salary: {:,}".format(self.gross_salary) +
" \nBenefits {:,} ".format(self.benefits) +
" \nAnnual working hours: {:,}".format(self.annual_hours) +
" \nEffective working rate {:.2%} ".format(self.effective_working_rate) +
" \nHourly cost: {:.2f} ".format(self.cost))
def calculate_cost(self):
"""Calculates the cost per effective working hour based on the object
properties"""
hourly_cost = ( self.gross_salary + self.benefits) / (self.annual_hours * self.effective_working_rate)
return hourly_cost
class EquipmentCatalogue(ResourceCatalogue):
"""Represents a catalogue of the company equipment information
from where it be managed and stored in a persistent ZODB storage
"""
def __init__(self):
"""Loads to memory the Resource Catalogue"""
ResourceCatalogue.__init__(self)
def add_resource(self, resource_code, equipment_name, measure_unit, acquisition_cost, useful_life, useful_life_time_unit="hours"):
"""Adds a new equipment to the company catalogue"""
new_resource = Equipment(resource_code, equipment_name, measure_unit, acquisition_cost, useful_life, useful_life_time_unit="hours")
# checks if the resource code is in the database. If so warns the user before committing the changes
if resource_code not in self.resource_catalogue:
#Save the new_category object
self.save_ZODB(new_resource)
return new_resource
else:
print "Resource {} code already exists. ".format(resource_code)
resource = self.search_resource(resource_code)
print resource
print "Please check and try again"
return new_resource # The object is returned to the user to modify it.
def list_resources(self, typeofobject = Equipment):
CatalogueResource.list_resources(typeofobject)
class Equipment(Resource):
"""Represents the equipment used in the company to peform different activities.
Attributes:
Resouce_code : A unique code that identifies the equipment
Equipment_name: Name of the equipment
Measure_unit: Unit of measure in which the equipment is kept in inventory.
Acquisition_cost : Cost of the equipment installed and working in the company including transport
and installation expenses.
Useful_life : Time in which the equipment will be productive.
Useful_life_time_unit = It can be hours or years depending on the type of equipment.
"""
def __init__(self, resource_code, equipment_name, measure_unit, acquisition_cost, useful_life, useful_life_time_unit="hours"):
Resource.__init__(self, equipment_name, resource_code, measure_unit, 0)
self.acquisition_cost = acquisition_cost # acquisition in Euros.
self.useful_life = useful_life # useful life in hours
self.useful_life_time_unit = useful_life_time_unit # it has to be a time object that allows conversions
self.cost = self.calculate_cost()
def calculate_cost(self):
""" Calculates the cost of the equipment per unit of time"""
return self.acquisition_cost / self.useful_life
def __str__(self):
return ("Equipment code: {} ".format(self.resource_code) +
"\nEquipment name: {} ".format(self.name) +
"\nMeasure unit: {} ".format(self.measure_unit) +
"\nAcquisition cost: {:,} ".format(self.acquisition_cost) +
"\nUseful life: {:,}".format(self.useful_life) +
"\nUseful life time unit: {}".format(self.useful_life_time_unit) +
"\nCost per time unit: {:.2f}".format(self.cost))
class Space(Resource):
"""Represents the space available for the activities performed in the company.
Attributes:
Monthly_rental: Rent paid each month by the company without V.A.T.
Rental_space: Space rented in square meters.
% UsefulSpace: % of the total space that can be employed in company
activities.
"""
def __init__(self, space_code, space_name, monthly_rental, rental_space, useful_space):
Resource.__init__(self, space_name, space_code, "square meters", 0)
self.monthly_rental = monthly_rental
self.rental_space = rental_space
self.useful_sapce = useful_space / 100.0
def CalculateCost(self):
"""Calculates the rental monthly cost per sqm."""
return self.monthly_rental / self.rental_space
def __str__(self):
return ("Space code: {} ".format(self.resource_code) +
"\nSpace name: {}".format(self.name) +
"\nMonthly rental: {:,}".format(self.monthly_rental) +
"\nRental space: {:,}".format(self.rental_space) +
"\nUseful space: {:.2%}".format(self.useful_space) +
"\nRenta cost per sqm: {:,.2f}".format(self.cost))
if __name__ == "__main__":
equipos = EquipmentCatalogue()
equipos.add_resource(22, "Cortadora", "Maquina", 30000, 5000)
equipos.add_resource(21, "Prensa", "Maquina", 20000, 10000)
alquiler_oficina = Space(24, "Oficina centro", 3000, 200, 80)
equipos.list_resources()
# resource = ResourceCatalogue()
# resource.list_resources()
catalogue = ResourceCatalogue()
catalogue.list_resources(JobCategory)
catalogue.list_resources(Equipment)
job_catalogue = JobCatalogue()
# paleta = job_catalogue.add_resource("Paleta", 16, 15000, 5000, 1800, 50 )
# print "*" * 80
# designer = job_catalogue.add_resource("Designer", 15, 30000, 10000, 1800, 80 )
# print "*" * 80
# resource = job_catalogue.search_resource(15)
# print "El recurso quince es: ", resource
# resource = job_catalogue.search_resource(22)
# print "El recurso 22 es: ", resource
# job_catalogue.list_resources(JobCategory)
# print "*" * 80
# print "Lista todos los recursos"
job_catalogue.list_resources()
# print job
# print paleta
# print job.gross_salary
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment