diff --git a/students/template_student/lesson00/oo_class.py b/students/Justin_Jameson/lesson00/oo_class.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson00/oo_class.py rename to students/Justin_Jameson/lesson00/oo_class.py diff --git a/students/template_student/lesson00/oo_inherit.py b/students/Justin_Jameson/lesson00/oo_inherit.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson00/oo_inherit.py rename to students/Justin_Jameson/lesson00/oo_inherit.py diff --git a/students/Justin_Jameson/lesson01/activity/.idea/activity.iml b/students/Justin_Jameson/lesson01/activity/.idea/activity.iml new file mode 100644 index 0000000..f3d7bc9 --- /dev/null +++ b/students/Justin_Jameson/lesson01/activity/.idea/activity.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson01/activity/.idea/encodings.xml b/students/Justin_Jameson/lesson01/activity/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/students/Justin_Jameson/lesson01/activity/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson01/activity/.idea/misc.xml b/students/Justin_Jameson/lesson01/activity/.idea/misc.xml new file mode 100644 index 0000000..a2e120d --- /dev/null +++ b/students/Justin_Jameson/lesson01/activity/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson01/activity/.idea/modules.xml b/students/Justin_Jameson/lesson01/activity/.idea/modules.xml new file mode 100644 index 0000000..2b39da0 --- /dev/null +++ b/students/Justin_Jameson/lesson01/activity/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson01/activity/.idea/vcs.xml b/students/Justin_Jameson/lesson01/activity/.idea/vcs.xml new file mode 100644 index 0000000..4fce1d8 --- /dev/null +++ b/students/Justin_Jameson/lesson01/activity/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson01/activity/.idea/workspace.xml b/students/Justin_Jameson/lesson01/activity/.idea/workspace.xml new file mode 100644 index 0000000..2fed593 --- /dev/null +++ b/students/Justin_Jameson/lesson01/activity/.idea/workspace.xml @@ -0,0 +1,568 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + divider + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1554956370486 + + + 1554962824626 + + + 1555028299073 + + + 1555033481936 + + + 1555037422763 + + + 1555044378345 + + + 1555433176564 + + + 1555437331844 + + + 1555437485614 + + + 1555460569576 + + + 1555525315497 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson01/assignment/inventory_management/electric_appliances_class.py b/students/Justin_Jameson/lesson01/assignment/inventory_management/electric_appliances_class.py new file mode 100644 index 0000000..e3b35cd --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/inventory_management/electric_appliances_class.py @@ -0,0 +1,47 @@ +# -------------------------------------------------# +# # Title: electric appliances class module for Inventory Management +# # Dev: unknown +# # Date: 4/16/2019 +# # ChangeLog: (Who, , What) +# Justin Jameson +# added content to doc strings +# -------------------------------------------------# +""" +This files is a class for Electric appliances +""" +from inventory_class import Inventory + + +class ElectricAppliances(Inventory): + """ + This class is for appliances. + """ + def __init__(self, + product_code, + description, + market_price, + rental_price, + brand, + voltage): + + """Creates common instance variables from the parent class""" + super().__init__(product_code, + description, + market_price, + rental_price) + + self.brand = brand + self.voltage = voltage + self.output_dict = {} + + def returnasdictionary(self): + """"fixing docstring""" + # output_dict = {} + self.output_dict['product_code'] = self.product_code + self.output_dict['description'] = self.description + self.output_dict['market_price'] = self.market_price + self.output_dict['rental_price'] = self.rental_price + self.output_dict['brand'] = self.brand + self.output_dict['voltage'] = self.voltage + + return self.output_dict diff --git a/students/Justin_Jameson/lesson01/assignment/inventory_management/furniture_class.py b/students/Justin_Jameson/lesson01/assignment/inventory_management/furniture_class.py new file mode 100644 index 0000000..e3224c8 --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/inventory_management/furniture_class.py @@ -0,0 +1,43 @@ +# -------------------------------------------------# +# # Title:inventory class module for Inventory Management +# # Dev: unknown +# # Date: 4/16/2019 +# # ChangeLog: (Who, What) +# Justin Jameson +# added content to doc strings +# added super(). to get rid of duplicate code. +# -------------------------------------------------# +""" Fixing docstring """ +from inventory_class import Inventory + + +class Furniture(Inventory): + """ creating a child class of Inventory""" + def __init__(self, + product_code, + description, + market_price, + rental_price, + material, + size): + """Creates common instance variables from the parent class""" + super().__init__(product_code, + description, + market_price, + rental_price) + + self.material = material + self.size = size + self.output_dict = {} + + def return_as_dictionary(self): + """"can I get rid of the replicated ones from the original class?""" + # output_dict = {} + self.output_dict['product_code'] = self.product_code + self.output_dict['description'] = self.description + self.output_dict['market_price'] = self.market_price + self.output_dict['rental_price'] = self.rental_price + self.output_dict['material'] = self.material + self.output_dict['size'] = self.size + + return self.output_dict diff --git a/students/Justin_Jameson/lesson01/assignment/inventory_management/inventory_class.py b/students/Justin_Jameson/lesson01/assignment/inventory_management/inventory_class.py new file mode 100644 index 0000000..e9f6b65 --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/inventory_management/inventory_class.py @@ -0,0 +1,36 @@ +# -------------------------------------------------# +# # Title:inventory class module for Inventory Management +# # Dev: unknown +# # Date: 4/16/2019 +# # ChangeLog: (Who, What) +# Justin Jameson +# added content to doc strings +# -------------------------------------------------# + +""" Super class for Inventory Management program """ + + +class Inventory: + """ Inventory class defining attributes, content + is fed to this class from main.py and converted + to a dictionary. """ + def __init__(self, + product_code, + description, + market_price, + rental_price): + """ prepping input from main to place in dictionary""" + self.product_code = product_code + self.description = description + self.market_price = market_price + self.rental_price = rental_price + + def return_as_dictionary(self): + """ Fixing doc string """ + output_dict = {} + output_dict['product_code'] = self.product_code + output_dict['description'] = self.description + output_dict['market_price'] = self.market_price + output_dict['rental_price'] = self.rental_price + + return output_dict diff --git a/students/Justin_Jameson/lesson01/assignment/inventory_management/main.py b/students/Justin_Jameson/lesson01/assignment/inventory_management/main.py new file mode 100644 index 0000000..fd41ea8 --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/inventory_management/main.py @@ -0,0 +1,112 @@ +# -------------------------------------------------# +# # Title: Main module for inventory Management +# # Dev: unknown +# # Date: 4/16/2019 +# # ChangeLog: (Who, What) +# Justin Jameson +# Added doc strings +# shortened lines to conform to PEP 8 +# method 'add_new_item' removed global FULL_INVENTORY; +# added doc strings. +# #-------------------------------------------------# +""" Launches the user interface for the Inventory management system""" + +import sys +import market_prices +import inventory_class +import furniture_class +import electric_appliances_class + + +def main_menu(user_prompt=None): + """"This method is the menu for the program. The intent is to + offer (3) choices, add an item, retrieve information from an existing + item, and exit the program.""" + valid_prompts = {"1": add_new_item, + "2": item_info, + "q": exit_program} + options = list(valid_prompts.keys()) + + while user_prompt not in valid_prompts: + options_str = ("{}" + ", {}" * (len(options)-1)).format(*options) + # look at the format string with the use of f and options at the end. + print(f"Please choose from the following options ({options_str}):") + print("1. Add a new item to the Inventory") + print("2. Get item information") + print("q. Quit") + user_prompt = input(">") + return valid_prompts.get(user_prompt) + + +def get_price(item_code): + """This method is incomplete, I suspect it will + be incorporated in the future with code from below + item_price = market_prices.get_latest_price(item_code)""" + # print("Get price") + item_price = market_prices.get_latest_price(item_code) + + +def add_new_item(): + """Adding items to inventory. This method will add user + input into a dictionary""" + item_code = input("Enter item code: ") + item_description = input("Enter item description: ") + item_rental_price = input("Enter item rental price: ") + + # Get price from the market prices module + item_price = market_prices.get_latest_price(item_code) + + is_furniture = input("Is this item a piece of Furniture? (Y/N): ") + if is_furniture.lower() == "y": + item_material = input("Enter item material: ") + item_size = input("Enter item size (S,M,L,XL): ") + new_item = furniture_class.Furniture(item_code, + item_description, + item_price, + item_rental_price, + item_material, + item_size) + else: + is_electric_appliance = input("Is this item an electric appliance?" + " (Y/N): ") + if is_electric_appliance.lower() == "y": + item_brand = input("Enter item brand: ") + item_voltage = input("Enter item voltage: ") + new_item = \ + electric_appliances_class.ElectricAppliances(item_code, + item_description, + item_price, + item_rental_price, + item_brand, + item_voltage) + else: + new_item = inventory_class.Inventory(item_code, + item_description, + item_price, + item_rental_price) + FULL_INVENTORY[item_code] = new_item.return_as_dictionary() + print("New Inventory item added") + + +def item_info(): + """ This method prints the dictionary""" + item_code = input("Enter item code: ") + if item_code in FULL_INVENTORY: + print_dict = FULL_INVENTORY[item_code] + for k, value in print_dict.items(): + print("{}:{}".format(k, value)) + else: + print("Item not found in Inventory") + + +def exit_program(): + """This method exits the program""" + sys.exit() + + +if __name__ == '__main__': + FULL_INVENTORY = {} + while True: + print(FULL_INVENTORY) + main_menu()() + input("Press Enter to continue...........") diff --git a/students/Justin_Jameson/lesson01/assignment/inventory_management/market_prices.py b/students/Justin_Jameson/lesson01/assignment/inventory_management/market_prices.py new file mode 100644 index 0000000..8021a99 --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/inventory_management/market_prices.py @@ -0,0 +1,8 @@ +""" Market Prices """ + + +def get_latest_price(item_code): + """ I think this should be the magic mock? + Not sure exactly what is happening here""" + return 24 + # Raise an exception to force the user to Mock its output diff --git a/students/template_student/lesson01/assignment/pylintrc b/students/Justin_Jameson/lesson01/assignment/pylintrc similarity index 100% rename from students/template_student/lesson01/assignment/pylintrc rename to students/Justin_Jameson/lesson01/assignment/pylintrc diff --git a/students/Justin_Jameson/lesson01/assignment/test_unit.py b/students/Justin_Jameson/lesson01/assignment/test_unit.py new file mode 100644 index 0000000..a084b5b --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/test_unit.py @@ -0,0 +1,49 @@ +from unittest import TestCase +from unittest.mock import MagicMock +from unittest.mock import patch +from inventory_management import main +from inventory_class import Inventory +from furniture_class import Furniture +from electric_appliances_class import ElectricAppliances + + +class MainTest(unittest.TestCase): + """Tests for main.py: + 1. does each prompt work in 'main_menu'. + 2. when adding content to 'add_new_item', item is added to the dictionary. + 3. 'item_info' either prints the dictionary or 'Item not found in Inventory' """ + + def test_main(self): + + +class InventoryTest(unittest.TestCase): + """Tests for inventory_class + Not a test, but would like to think about, if any of the codes have a specific + format, such as numbers only. + 1. can take 4 input items and create a dictionary""" + + def test_dic_values(self): + test_dic = {'0u812': {'product_code': '0u812', 'description': 'new', 'market_price': 24, 'rental_price': '70'}} + product_code = '0u812' + description = 'new' + market_price = 24 + rental_price = 70 + self.assertEqual(test_dic, output_dict) + + +class FurnitureTest(unittest.TestCase): + """Tests for furniture_class + 1. can take 6 input items and create a dictionary""" + pass + + +class ElectricAppliancesTest(unittest.TestCase): + """Tests for electric_appliances_class + 1. can take 6 input items and create a dictionary""" + pass + + +class MarketPriceTest(unittest.TestCase): + """Test for market_prices + 1. can return a value for latest price """ + pass diff --git a/students/template_student/lesson01/assignment/tests/README.md b/students/Justin_Jameson/lesson01/assignment/tests/README.md similarity index 100% rename from students/template_student/lesson01/assignment/tests/README.md rename to students/Justin_Jameson/lesson01/assignment/tests/README.md diff --git a/students/Justin_Jameson/lesson01/assignment/tests/test_unit.py b/students/Justin_Jameson/lesson01/assignment/tests/test_unit.py new file mode 100644 index 0000000..6a8a286 --- /dev/null +++ b/students/Justin_Jameson/lesson01/assignment/tests/test_unit.py @@ -0,0 +1,23 @@ +from unittest import TestCase +from unittest.mock import MagicMock +import main.py + +"""Tests for Main.py: +1. does each prompt work in 'main_menu'. +2. when adding content to 'add_new_item', item is added to the dictionary. +3. 'item_info' either prints the dictionary or 'Item not found in Inventory' + +Tests for inventory_class +Not a test, but would like to think about, if any of the codes have a specific +format, such as numbers only. +1. can take 4 input items and create a dictionary + +Tests for furniture_class +1. can take 6 input items and create a dictionary + +Tests for electric_appliances_class +1. can take 6 input items and create a dictionary + +Test for market_prices +1. can return a value for latest price? +""" \ No newline at end of file diff --git a/students/template_student/lesson02/activity/recursive.py b/students/Justin_Jameson/lesson02/activity/recursive.py similarity index 100% rename from students/template_student/lesson02/activity/recursive.py rename to students/Justin_Jameson/lesson02/activity/recursive.py diff --git a/students/Justin_Jameson/lesson02/assignment/Justin Jameson src.zip b/students/Justin_Jameson/lesson02/assignment/Justin Jameson src.zip new file mode 100644 index 0000000..4de3e77 Binary files /dev/null and b/students/Justin_Jameson/lesson02/assignment/Justin Jameson src.zip differ diff --git a/students/template_student/lesson02/assignment/README.md b/students/Justin_Jameson/lesson02/assignment/README.md old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson02/assignment/README.md rename to students/Justin_Jameson/lesson02/assignment/README.md diff --git a/students/template_student/lesson02/assignment/extras-optional/PhyRe.py b/students/Justin_Jameson/lesson02/assignment/extras-optional/PhyRe.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson02/assignment/extras-optional/PhyRe.py rename to students/Justin_Jameson/lesson02/assignment/extras-optional/PhyRe.py diff --git a/students/template_student/lesson02/assignment/extras-optional/README.md b/students/Justin_Jameson/lesson02/assignment/extras-optional/README.md old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson02/assignment/extras-optional/README.md rename to students/Justin_Jameson/lesson02/assignment/extras-optional/README.md diff --git a/students/template_student/lesson02/assignment/pylintrc b/students/Justin_Jameson/lesson02/assignment/pylintrc similarity index 100% rename from students/template_student/lesson02/assignment/pylintrc rename to students/Justin_Jameson/lesson02/assignment/pylintrc diff --git a/students/Justin_Jameson/lesson02/assignment/src/charges_calc.py b/students/Justin_Jameson/lesson02/assignment/src/charges_calc.py new file mode 100644 index 0000000..fb98e23 --- /dev/null +++ b/students/Justin_Jameson/lesson02/assignment/src/charges_calc.py @@ -0,0 +1,88 @@ +# -------------------------------------------------# +# # Title: charges calculator for Inventory management. +# # Dev: unknown +# # Date: 4/17/2019 +# # ChangeLog: (Who, What) +# Justin Jameson +# correct ouput to output line 20 'ouptu JSON file' +# in source.json removed extra comma on line 5884 from +# 'units_rented': 7,, +# imported logger +# #-------------------------------------------------# + +""" Returns total price paid for individual rentals """ + +import argparse +import json +import datetime +import math +import logging +logging.basicConfig(filename='charges_calc.log', level=logging.DEBUG) +log_format = "%(asctime)s %(filename)s:%(lineno)-3d %(levelname)s %(message)s" +formatter = logging.Formatter(log_format) +file_handler = logging.FileHandler('charges_calc.log') +file_handler.setFormatter(formatter) +logger = logging.getLogger() +logger.addHandler(file_handler) + + + +def parse_cmd_arguments(): + logging.debug('called parse_cmd') + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument('-i', '--input', help='input JSON file', required=True) + parser.add_argument('-o', '--output', help='output JSON file', required=True) + logging.debug('about to return parser.parse_arg') + return parser.parse_args() + + +def load_rentals_file(filename): + with open(filename) as file: + try: + logging.debug('you made it to the try except block') + data = json.load(file) + except: + logging.warning('load_rentals_files threw an exception') + exit(0) + logging.debug('made it through try except about to "return data"') + return data + + +def calculate_additional_fields(data): + for value in data.values(): + logging.debug('trying to print values in data', value) + try: + logging.debug('cycling through calculate_add.. try block') + rental_start = datetime.datetime.strptime(value['rental_start'], '%m/%d/%y') + logging.debug('made it through rental_start') + rental_end = datetime.datetime.strptime(value['rental_end'], '%m/%d/%y') + logging.debug('made it through rental_end') + value['total_days'] = (rental_end - rental_start).days + logging.debug('made it through value total_days') + value['total_price'] = value['total_days'] * value['price_per_day'] + logging.debug('made it through total_price') + # value['sqrt_total_price'] = math.sqrt(value['total_price']) + # logging.debug('made it through sqrt_total_price') + value['unit_cost'] = value['total_price'] / value['units_rented'] + logging.debug('made it through calculate_add... try block', value) + except: + logging.warning('except block of calculate_add... this will exit the program without') + exit(0) + logging.debug('about to return data from calculate_add...') + return data + + +def save_to_json(filename, data): + logging.debug('made it to "save_to_json') + with open(filename, 'w') as file: + json.dump(data, file) + + +if __name__ == "__main__": + args = parse_cmd_arguments() + logging.debug('stepping into data') + data = load_rentals_file(args.input) + logging.debug('returning data, now redefining data to calculate_add...') + data = calculate_additional_fields(data) + logging.debug('returned data from calculate_add..., now stepping into save_to_json') + save_to_json(args.output, data) diff --git a/students/template_student/lesson02/assignment/src/source.json b/students/Justin_Jameson/lesson02/assignment/src/source.json old mode 100755 new mode 100644 similarity index 99% rename from students/template_student/lesson02/assignment/src/source.json rename to students/Justin_Jameson/lesson02/assignment/src/source.json index e33b77c..a092f9b --- a/students/template_student/lesson02/assignment/src/source.json +++ b/students/Justin_Jameson/lesson02/assignment/src/source.json @@ -5881,7 +5881,7 @@ }, "RNT841": { "product_code": "PRD33", - "units_rented": 7,, + "units_rented": 7, "price_per_day": 19, "rental_start": "5/11/16", "rental_end": "7/27/17" diff --git a/students/Justin_Jameson/lesson02/assignment/src/testing logger.py b/students/Justin_Jameson/lesson02/assignment/src/testing logger.py new file mode 100644 index 0000000..4179a2c --- /dev/null +++ b/students/Justin_Jameson/lesson02/assignment/src/testing logger.py @@ -0,0 +1,5 @@ +import logging +logging.basicConfig(filename='example.log',level=logging.DEBUG) +logging.debug('This message should go to the log file') +logging.info('So should this') +logging.warning('And this, too') \ No newline at end of file diff --git a/students/template_student/lesson03/activity/DatabaseDiagram.jpeg b/students/Justin_Jameson/lesson03/activity/DatabaseDiagram.jpeg old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson03/activity/DatabaseDiagram.jpeg rename to students/Justin_Jameson/lesson03/activity/DatabaseDiagram.jpeg diff --git a/students/template_student/lesson03/activity/create_personjob.py b/students/Justin_Jameson/lesson03/activity/create_personjob.py similarity index 100% rename from students/template_student/lesson03/activity/create_personjob.py rename to students/Justin_Jameson/lesson03/activity/create_personjob.py diff --git a/students/template_student/lesson03/activity/personjob.db b/students/Justin_Jameson/lesson03/activity/personjob.db similarity index 100% rename from students/template_student/lesson03/activity/personjob.db rename to students/Justin_Jameson/lesson03/activity/personjob.db diff --git a/students/template_student/lesson03/activity/personjob_learning_v1_p1.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v1_p1.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v1_p1.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v1_p1.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v1_p2.csv b/students/Justin_Jameson/lesson03/activity/personjob_learning_v1_p2.csv similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v1_p2.csv rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v1_p2.csv diff --git a/students/template_student/lesson03/activity/personjob_learning_v1_p3.txt b/students/Justin_Jameson/lesson03/activity/personjob_learning_v1_p3.txt similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v1_p3.txt rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v1_p3.txt diff --git a/students/template_student/lesson03/activity/personjob_learning_v3_p1.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v3_p1.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v3_p1.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v3_p1.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v3_p2.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v3_p2.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v3_p2.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v3_p2.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v3_p3.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v3_p3.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v3_p3.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v3_p3.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p1.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p1.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p1.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p1.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p2.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p2.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p2.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p2.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p3.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p3.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p3.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p3.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p4.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p4.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p4.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p4.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p5.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p5.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p5.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p5.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p6.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p6.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p6.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p6.py diff --git a/students/template_student/lesson03/activity/personjob_learning_v5_p7.py b/students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p7.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_learning_v5_p7.py rename to students/Justin_Jameson/lesson03/activity/personjob_learning_v5_p7.py diff --git a/students/template_student/lesson03/activity/personjob_model.py b/students/Justin_Jameson/lesson03/activity/personjob_model.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_model.py rename to students/Justin_Jameson/lesson03/activity/personjob_model.py diff --git a/students/template_student/lesson03/activity/personjob_modeli.py b/students/Justin_Jameson/lesson03/activity/personjob_modeli.py similarity index 100% rename from students/template_student/lesson03/activity/personjob_modeli.py rename to students/Justin_Jameson/lesson03/activity/personjob_modeli.py diff --git a/students/template_student/lesson03/activity/utilities.py b/students/Justin_Jameson/lesson03/activity/utilities.py similarity index 100% rename from students/template_student/lesson03/activity/utilities.py rename to students/Justin_Jameson/lesson03/activity/utilities.py diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/assignment.iml b/students/Justin_Jameson/lesson03/assignment/.idea/assignment.iml new file mode 100644 index 0000000..738176b --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/assignment.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/dictionaries/jjame.xml b/students/Justin_Jameson/lesson03/assignment/.idea/dictionaries/jjame.xml new file mode 100644 index 0000000..6b3b38d --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/dictionaries/jjame.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/encodings.xml b/students/Justin_Jameson/lesson03/assignment/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/misc.xml b/students/Justin_Jameson/lesson03/assignment/.idea/misc.xml new file mode 100644 index 0000000..a2e120d --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/modules.xml b/students/Justin_Jameson/lesson03/assignment/.idea/modules.xml new file mode 100644 index 0000000..25466ae --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/terminal.xml b/students/Justin_Jameson/lesson03/assignment/.idea/terminal.xml new file mode 100644 index 0000000..63657c7 --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/terminal.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/vcs.xml b/students/Justin_Jameson/lesson03/assignment/.idea/vcs.xml new file mode 100644 index 0000000..4fce1d8 --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson03/assignment/.idea/workspace.xml b/students/Justin_Jameson/lesson03/assignment/.idea/workspace.xml new file mode 100644 index 0000000..34460b3 --- /dev/null +++ b/students/Justin_Jameson/lesson03/assignment/.idea/workspace.xml @@ -0,0 +1,599 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Meta + \\ + primary_key = True, + m + output_dict + customer_class + customer_info_model + model_to_dict + query_dict + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1557689396152 + + + 1557689465299 + + + 1557899214975 + + + 1557921286895 + + + 1558212503659 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/students/Justin_Jameson/lesson05/MongoWorkModified.py b/students/Justin_Jameson/lesson05/MongoWorkModified.py new file mode 100644 index 0000000..1ae5f30 --- /dev/null +++ b/students/Justin_Jameson/lesson05/MongoWorkModified.py @@ -0,0 +1,103 @@ +from pymongo import MongoClient + + +class MongoDBConnection(): + """MongoDB Connection""" + + def __init__(self, host='127.0.0.1', port=27017): + """ be sure to use the ip address not name for local windows""" + self.host = host + self.port = port + self.connection = None + + def __enter__(self): + self.connection = MongoClient(self.host, self.port) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.connection.close() + + +def print_mdb_collection(collection_name): + for doc in collection_name.find(): + print(doc) + + +def main(): + mongo = MongoDBConnection() + + with mongo: # Context manager. + # mongodb database; it all starts here + db = mongo.connection.media #We are connecting to a database named "media". + + # collection in database + cd = db["cd"] #Please do not confuse "cd" (corresponding to CompactDisk) with similarly named OS command (change directory) + + # notice how easy these are to create and that they are "schemaless" + # that is, the Python module defines the data structure in a dict, + # rather than the database which just stores what it is told + + cd_ip = {"artist": "The Who", "Title": "By Numbers"} + result = cd.insert_one(cd_ip) #Inserting precisely one record + + cd_ip = [{ + "artist": "Deep Purple", + "Title": "Made In Japan", + "name": "Andy" + }, + { + "artist": "Led Zeppelin", + "Title": "House of the Holy", + "name": "Andy" + }, { + "artist": "Pink Floyd", + "Title": "DSOM", + "name": "Andy" + }, + { + "artist": "Albert Hammond", + "Title": "Free Electric Band", + "name": "Sam" + }, { + "artist": "Nilsson", + "Title": "Without You", + "name": "Sam" + }] #List of dictionaries corresponding to records to be inserted + + result = cd.insert_many(cd_ip) #Inserts records specified in the list above + + print_mdb_collection(cd) #Prints all records from a specified table + + # another collection, i.e., table + ThePersonWhoCollects = db["ThePersonWhoCollects"] #Should table names be the same or different? + #I changed name from collector to ThePersonWhoCollects so that it would not be confused with "collection". + ThePersonWhoCollects_ip = [{ + "name": "Andy", + "preference": "Rock" + }, { + "name": "Sam", + "preference": "Pop" + }] + result = ThePersonWhoCollects.insert_many(ThePersonWhoCollects_ip) #The database appears after we insert many + + print_mdb_collection(ThePersonWhoCollects) + + # related data + for CurrentRecord in ThePersonWhoCollects.find(): #Here CurrentRecord is a variable pointing to each found record in a table + #CurrentRecord is a dictionary (EACH record is a dictionary). We can refer an element of the dictionary + #by its key; one of the keys is called "name" + print(f'List for {CurrentRecord["name"]}') + query = {"name": CurrentRecord["name"]} + for a_cd in cd.find(query): #Find all the records from table "cd" where attribute name is equal to a specified value (which happens to be a + #a name of a current record). In general, keys from records need satisfy properties specified in query + print(f'{CurrentRecord["name"]} has collected {a_cd}') + + # start afresh next time? + yorn = input("Drop data?") + if yorn.upper() == 'Y': + cd.drop() + ThePersonWhoCollects.drop() #Deletes the table and the data + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/students/template_student/lesson05/activity/mongdb_ex.py b/students/Justin_Jameson/lesson05/activity/mongdb_ex.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/mongdb_ex.py rename to students/Justin_Jameson/lesson05/activity/mongdb_ex.py diff --git a/students/template_student/lesson05/activity/mongodb.py b/students/Justin_Jameson/lesson05/activity/mongodb.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/mongodb.py rename to students/Justin_Jameson/lesson05/activity/mongodb.py diff --git a/students/template_student/lesson05/activity/mongodb_script.py.amend b/students/Justin_Jameson/lesson05/activity/mongodb_script.py.amend old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/mongodb_script.py.amend rename to students/Justin_Jameson/lesson05/activity/mongodb_script.py.amend diff --git a/students/template_student/lesson05/activity/neo4j.py b/students/Justin_Jameson/lesson05/activity/neo4j.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/neo4j.py rename to students/Justin_Jameson/lesson05/activity/neo4j.py diff --git a/students/template_student/lesson05/activity/nosql-other/.config/config.ini.sample b/students/Justin_Jameson/lesson05/activity/nosql-other/.config/config.ini.sample old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/.config/config.ini.sample rename to students/Justin_Jameson/lesson05/activity/nosql-other/.config/config.ini.sample diff --git a/students/template_student/lesson05/activity/nosql-other/data/data.pkl b/students/Justin_Jameson/lesson05/activity/nosql-other/data/data.pkl old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/data/data.pkl rename to students/Justin_Jameson/lesson05/activity/nosql-other/data/data.pkl diff --git a/students/template_student/lesson05/activity/nosql-other/data/rockstars.csv b/students/Justin_Jameson/lesson05/activity/nosql-other/data/rockstars.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/data/rockstars.csv rename to students/Justin_Jameson/lesson05/activity/nosql-other/data/rockstars.csv diff --git a/students/template_student/lesson05/activity/nosql-other/data/shelve.dat.db b/students/Justin_Jameson/lesson05/activity/nosql-other/data/shelve.dat.db old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/data/shelve.dat.db rename to students/Justin_Jameson/lesson05/activity/nosql-other/data/shelve.dat.db diff --git a/students/template_student/lesson05/activity/nosql-other/data/shelve.db b/students/Justin_Jameson/lesson05/activity/nosql-other/data/shelve.db old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/data/shelve.db rename to students/Justin_Jameson/lesson05/activity/nosql-other/data/shelve.db diff --git a/students/template_student/lesson05/activity/nosql-other/src/__init__.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/__init__.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/__init__.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/learn_data.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/learn_data.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/learn_data.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/learn_data.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/learnnosql.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/learnnosql.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/learnnosql.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/learnnosql.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/login_database.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/login_database.py old mode 100755 new mode 100644 similarity index 88% rename from students/template_student/lesson05/activity/nosql-other/src/login_database.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/login_database.py index 4a9e6fd..aa7d8cd --- a/students/template_student/lesson05/activity/nosql-other/src/login_database.py +++ b/students/Justin_Jameson/lesson05/activity/nosql-other/src/login_database.py @@ -21,16 +21,16 @@ def login_mongodb_cloud(): """ log.info('Here is where we use the connect to mongodb.') - log.info('Note use of f string to embed the user & password (from the tuple).') + log.info('Note use of customer string to embed the user & password (from the tuple).') try: config.read(config_file) user = config["mongodb_cloud"]["user"] pw = config["mongodb_cloud"]["pw"] except Exception as e: - print(f'error: {e}') + print(customer'error: {e}') - client = pymongo.MongoClient(f'mongodb://{user}:{pw}' + client = pymongo.MongoClient(customer'mongodb://{user}:{pw}' '@cluster0-shard-00-00-wphqo.mongodb.net:27017,' 'cluster0-shard-00-01-wphqo.mongodb.net:27017,' 'cluster0-shard-00-02-wphqo.mongodb.net:27017/test' @@ -51,7 +51,7 @@ def login_redis_cloud(): except Exception as e: - print(f'error: {e}') + print(customer'error: {e}') log.info('Here is where we use the connect to redis.') @@ -59,7 +59,7 @@ def login_redis_cloud(): r = redis.StrictRedis(host=host, port=port, password=pw, decode_responses=True) except Exception as e: - print(f'error: {e}') + print(customer'error: {e}') return r diff --git a/students/template_student/lesson05/activity/nosql-other/src/mongodb_script.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/mongodb_script.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/mongodb_script.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/mongodb_script.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/neo4j_script.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/neo4j_script.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/neo4j_script.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/neo4j_script.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/redis_script.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/redis_script.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/redis_script.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/redis_script.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/simple_script.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/simple_script.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/simple_script.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/simple_script.py diff --git a/students/template_student/lesson05/activity/nosql-other/src/utilities.py b/students/Justin_Jameson/lesson05/activity/nosql-other/src/utilities.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/nosql-other/src/utilities.py rename to students/Justin_Jameson/lesson05/activity/nosql-other/src/utilities.py diff --git a/students/template_student/lesson05/activity/peeweeapi.py b/students/Justin_Jameson/lesson05/activity/peeweeapi.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/peeweeapi.py rename to students/Justin_Jameson/lesson05/activity/peeweeapi.py diff --git a/students/template_student/lesson05/activity/rdbms_api.py b/students/Justin_Jameson/lesson05/activity/rdbms_api.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/rdbms_api.py rename to students/Justin_Jameson/lesson05/activity/rdbms_api.py diff --git a/students/template_student/lesson05/activity/redis.py b/students/Justin_Jameson/lesson05/activity/redis.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/activity/redis.py rename to students/Justin_Jameson/lesson05/activity/redis.py diff --git a/students/Justin_Jameson/lesson05/assignment/data/csv testing.py b/students/Justin_Jameson/lesson05/assignment/data/csv testing.py new file mode 100644 index 0000000..bf58fcb --- /dev/null +++ b/students/Justin_Jameson/lesson05/assignment/data/csv testing.py @@ -0,0 +1,26 @@ +import csv +list_of_customers = [] +list_of_products = [] +list_of_rentals = [] +with open('customers.csv', 'r') as customer: + reader = csv.reader(customer) + for row in reader: + c_dict = {'User ID': row[0], 'Name': row[1], 'Address': row[2], + 'zip code': row[3], 'phone number': row[4], 'email': row[5]} + list_of_customers.append(c_dict) + list_of_customers.pop(0) +with open('product.csv', 'r') as product: + reader = csv.reader(product) + for row in reader: + p_dict = {'Product ID': row[0], 'Description': row[1], 'Product Type': row[2], 'Quantity available': row[3]} + list_of_products.append(p_dict) + list_of_products.pop(0) +with open('rental.csv', 'r') as rentals: + reader = csv.reader(rentals) + for row in reader: + r_dict = {'Product ID': row[0], 'User ID': row[1]} + list_of_rentals.append(r_dict) + list_of_rentals.pop(0) +print(list_of_customers) +print(list_of_products) +print(list_of_rentals) diff --git a/students/template_student/lesson05/assignment/data/customers.csv b/students/Justin_Jameson/lesson05/assignment/data/customers.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/assignment/data/customers.csv rename to students/Justin_Jameson/lesson05/assignment/data/customers.csv diff --git a/students/template_student/lesson05/assignment/data/product.csv b/students/Justin_Jameson/lesson05/assignment/data/product.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/assignment/data/product.csv rename to students/Justin_Jameson/lesson05/assignment/data/product.csv diff --git a/students/template_student/lesson05/assignment/data/rental.csv b/students/Justin_Jameson/lesson05/assignment/data/rental.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/assignment/data/rental.csv rename to students/Justin_Jameson/lesson05/assignment/data/rental.csv diff --git a/students/template_student/lesson05/assignment/pylintrc b/students/Justin_Jameson/lesson05/assignment/pylintrc similarity index 100% rename from students/template_student/lesson05/assignment/pylintrc rename to students/Justin_Jameson/lesson05/assignment/pylintrc diff --git a/students/Justin_Jameson/lesson05/assignment/src/Test open in other dir.py b/students/Justin_Jameson/lesson05/assignment/src/Test open in other dir.py new file mode 100644 index 0000000..a377b6f --- /dev/null +++ b/students/Justin_Jameson/lesson05/assignment/src/Test open in other dir.py @@ -0,0 +1,94 @@ +from pymongo import MongoClient +import csv + + +class MongoDBConnection: + """MongoDB Connection""" + + def __init__(self, host='127.0.0.1', port=27017): + """ be sure to use the ip address not name for local windows""" + self.host = host + self.port = port + self.connection = None + + def __enter__(self): + self.connection = MongoClient(self.host, self.port) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.connection.close() + + +def print_mdb_collection(collection_name): + for doc in collection_name.find(): + print(doc) + + +def read_csv_files(): + list_of_customers = [] + list_of_products = [] + list_of_rentals = [] + with open('..\\.\\data\\customers.csv', 'r') as customer: + reader = csv.reader(customer) + for row in reader: + c_dict = {'User ID': row[0], 'Name': row[1], 'Address': row[2], + 'zip code': row[3], 'phone number': row[4], 'email': row[5]} + list_of_customers.append(c_dict) + list_of_customers.pop(0) + with open('..\\.\\data\\product.csv', 'r') as product: + reader = csv.reader(product) + for row in reader: + p_dict = {'Product ID': row[0], 'Description': row[1], 'Product Type': row[2], 'Quantity available': row[3]} + list_of_products.append(p_dict) + list_of_products.pop(0) + with open('..\\.\\data\\rental.csv', 'r') as rentals: + reader = csv.reader(rentals) + for row in reader: + r_dict = {'Product ID': row[0], 'User ID': row[1]} + list_of_rentals.append(r_dict) + list_of_rentals.pop(0) + main(list_of_customers, list_of_products, list_of_rentals) + + +def main(list_of_customers, list_of_products, list_of_rentals): + mongo = MongoDBConnection() + + with mongo: # Context manager. + # mongodb database; create rentaldatabase + db = mongo.connection.rentaldatabase + + # collection (table) in database, (3) customers, products and rental status (rental) + customers = db["customers"] # todo: if the db is failing, review original code from instructor for syntax + # todo: create method to define the list of dictionaries for customers, pass in as an argument + products = db["products"] + rental = db["rental"] + result_customer = customers.insert_many(list_of_customers) # Inserts records specified in the list above + result_products = products.insert_many(list_of_products) + result_rentals = rental.insert_many(list_of_rentals) + print_mdb_collection(customers) # Prints all records from a specified table + print_mdb_collection(products) + print_mdb_collection(rental) + + """ # related data + for CurrentRecord in ThePersonWhoCollects.find(): # Here CurrentRecord is a variable + pointing to each found record in a table + # CurrentRecord is a dictionary (EACH record is a dictionary). We can refer an element of the dictionary + # by its key; one of the keys is called "name" + print(customer'List for {CurrentRecord["name"]}') + query = {"name": CurrentRecord["name"]} + for a_cd in cd.find( + query): # Find all the records from table "cd" where attribute name + is equal to a specified value (which happens to be a + # a name of a current record). In general, keys from records need satisfy properties specified in query + print(customer'{CurrentRecord["name"]} has collected {a_cd}') + """ + # start afresh next time? + yorn = input("Drop data?") + if yorn.upper() == 'Y': + customers.drop() + products.drop() + rental.drop() # Deletes the table and the data + + +if __name__ == "__main__": + read_csv_files() diff --git a/students/Justin_Jameson/lesson05/assignment/src/database.py b/students/Justin_Jameson/lesson05/assignment/src/database.py new file mode 100644 index 0000000..f954912 --- /dev/null +++ b/students/Justin_Jameson/lesson05/assignment/src/database.py @@ -0,0 +1,233 @@ +# -------------------------------------------------# +# # Title: Lesson 05 database.py +# # Dev: Justin Jameson +# # Date: 5/18/2019 +# # ChangeLog: (Who, when, What) +# -------------------------------------------------# +from pymongo import MongoClient +import sys +import csv +import logging + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# ************************************** Defining variables ************************************* +directory_name = '..\\.\\data\\' +product_data = 'product.csv' +customer_data = 'customers.csv' +rentals_data = 'rental.csv' +logger.info('defined directory name and the following .csv files: product_data, customer_data, and rental_data') + + +# ******************************************** Defining Classes ********************************* +class MongoDBConnection: + """ + MongoDB Connection + """ + + def __init__(self, host='127.0.0.1', port=27017): + """ be sure to use the ip address not name for local windows""" + self.host = host + self.port = port + self.connection = None + logger.info('created connection to host {} and port {}'.format(self.host, self.port)) + + def __enter__(self): + self.connection = MongoClient(self.host, self.port) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.connection.close() + + +class ReadCsvFiles: + """ + This class calls 'import_data' method to access the csv files. + Then reads the csv files, and turns them into a list of dictionaries. + Then sends the list to the 'main' method for incorporation into MongoDB. + This class also uses the self items for calls in other methods. + + :return: + """ + def __init__(self, list_of_customers=[], list_of_products=[], list_of_rentals=[]): + self.list_of_customers = list_of_customers + self.list_of_products = list_of_products + self.list_of_rentals = list_of_rentals + + logger.info('created empty lists') + imported_data = import_data(directory_name, product_data, customer_data, rentals_data) + customers_file = imported_data[0] + products_file = imported_data[1] + rentals_file = imported_data[2] + + with open(customers_file, 'r') as customer: + reader = csv.reader(customer) + for row in reader: + c_dict = {'User ID': row[0], 'Name': row[1], 'Address': row[2], + 'zip code': row[3], 'phone number': row[4], 'email': row[5]} + list_of_customers.append(c_dict) + list_of_customers.pop(0) + with open(products_file, 'r') as product: + reader = csv.reader(product) + for row in reader: + p_dict = {'Product ID': row[0], 'Description': row[1], 'Product Type': row[2], 'Quantity available': row[3]} + list_of_products.append(p_dict) + list_of_products.pop(0) + with open(rentals_file, 'r') as rentals: + reader = csv.reader(rentals) + for row in reader: + r_dict = {'Product ID': row[0], 'User ID': row[1]} + list_of_rentals.append(r_dict) + list_of_rentals.pop(0) + logger.info('appended all lists with content from csv files') + return + + +# ************************************* user interface ************************************* +def main_menu(user_prompt=None): + """ + This method creates the menu for the program. + """ + valid_prompts = {"1": ReadCsvFiles, + "2": show_available_products, + "3": show_rentals, + "4": reset_db, + "q": exit_program} + options = list(valid_prompts.keys()) + + while user_prompt not in valid_prompts: + options_str = ("{}" + ", {}" * (len(options) - 1)).format(*options) + print(f"Please choose from the following options ({options_str}):") + print("1. Load csv files to database.") + print("2. Show Customer products available for rent") + print("3. Show Sales Person the list of customers") + print("4. Reset the DataBase") + print("q. Quit") + user_prompt = input(">") + return valid_prompts.get(user_prompt) + + +# ************************************* Processing ***************************************** +def db_info(): + """ + This method returns the use of the class 'ReadCsvFiles'. + :return: + """ + return ReadCsvFiles() + + +def import_data(directory_location, product_file, customer_file, rental_file): + """ + This function takes a directory name and three csv files as input, + then creates a directory and file name for use in 'ReadCsvFiles' method. + 1. product data = product.csv + 2. customer data = customers.csv + 3. rentals data = rental.csv + :param directory_location: + :param product_file: + :param customer_file: + :param rental_file: + :return:import_customer, import_product, import_rentals + """ + import_customer = directory_location + customer_file + import_product = directory_location + product_file + import_rentals = directory_location + rental_file + logger.info('returning tuple for use in method "ReadCsvFiles"') + return import_customer, import_product, import_rentals + + +def main(list_of_customers, list_of_products, list_of_rentals): + """ + Return: 2 tuples: + 1. a record count of the number of products, customers and rentals + added (in that order) + 2. a count of any errors that occurred, in the same order. + :param list_of_customers: + :param list_of_products: + :param list_of_rentals: + :return: + """ + mongo = MongoDBConnection() + + with mongo: # Context manager. + # mongodb database; create rentaldatabase + db = mongo.connection.rentaldatabase + + # collection (table) in database, (3) customers, products and rental status (rental) + customers = db["customers"] + products = db["products"] + rental = db["rental"] + result_customer = customers.insert_many(list_of_customers) # Inserts records specified in the list above + result_products = products.insert_many(list_of_products) + result_rentals = rental.insert_many(list_of_rentals) + # print_mdb_collection(customers) # Prints all records from a specified table + # print_mdb_collection(products) + # print_mdb_collection(rental) + return result_customer, result_products, result_rentals + + +def reset_db(): + """ + deletes db + :return: + """ + mongo = MongoDBConnection() + + with mongo: # Context manager. + db = mongo.connection.rentaldatabase + # start afresh next time? + drop_data = input("Drop data?") + if drop_data.upper() == 'Y': + db['customers'].drop() + db["products"].drop() + db["rental"].drop() + logger.info('dropped data from DB') + + +# ****************************************** output to the user ************************************* +def show_available_products(): + """ + As a HP Norton customer I want to see a list of all products available for rent so that I can make a rental choice. + You can have a specific field to indicate if a product is available, however, + a quantity_available of 0 is understood as “not available”. + Returns a Python dictionary of products listed as available with the following fields: + product_id. + description. + product_type. + quantity_available. + :return: + """ + + for dlop in return_db_info.list_of_products: + if dlop['Quantity available'] != '0': + print(dlop) + + +def show_rentals(): + """ + Returns a Python dictionary with the following user information from users that have rented products + matching product_id: + user_id. + name. + address. + phone_number. + email. + """ + for doc in return_db_info.list_of_customers: + logger.info('producing a list of products, customers, and rentals.') + print(doc) + + +# ***************************************** execution *********************************************** +def exit_program(): + """This method exits the program""" + logger.info('called exit_program') + sys.exit() + + +if __name__ == "__main__": + return_db_info = db_info() + while True: + main_menu()() + input("Press Enter to continue...........") diff --git a/students/template_student/lesson03/assignment/src/basic_operations.py b/students/Justin_Jameson/lesson05/assignment/src/testcode.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson03/assignment/src/basic_operations.py rename to students/Justin_Jameson/lesson05/assignment/src/testcode.py diff --git a/students/Justin_Jameson/lesson05/assignment/src/testcode2.py b/students/Justin_Jameson/lesson05/assignment/src/testcode2.py new file mode 100644 index 0000000..325864a --- /dev/null +++ b/students/Justin_Jameson/lesson05/assignment/src/testcode2.py @@ -0,0 +1,231 @@ +# -------------------------------------------------# +# # Title: Lesson 05 database.py +# # Dev: Justin Jameson +# # Date: 5/18/2019 +# # ChangeLog: (Who, when, What) +# -------------------------------------------------# +from pymongo import MongoClient +import sys +import csv +import logging + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# ************************************** Defining variables ************************************* +directory_name = '..\\.\\data\\' +product_data = 'product.csv' +customer_data = 'customers.csv' +rentals_data = 'rental.csv' +logger.info('defined directory name and the following .csv files: product_data, customer_data, and rental_data') + + +# ******************************************** Defining Classes ********************************* +class MongoDBConnection: + """ + MongoDB Connection + """ + + def __init__(self, host='127.0.0.1', port=27017): + """ be sure to use the ip address not name for local windows""" + self.host = host + self.port = port + self.connection = None + logger.info('created connection to host {} and port {}'.format(self.host, self.port)) + + def __enter__(self): + self.connection = MongoClient(self.host, self.port) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.connection.close() + + +class ReadCsvFiles: + """ + This class calls 'import_data' method to access the csv files. + Then reads the csv files, and turns them into a list of dictionaries. + Then sends the list to the 'main' method for incorporation into MongoDB. + This class also uses the self items for calls in other methods. + + :return: + """ + def __init__(self, list_of_customers=[], list_of_products=[], list_of_rentals=[]): + self.list_of_customers = list_of_customers + self.list_of_products = list_of_products + self.list_of_rentals = list_of_rentals + + logger.info('created empty lists') + imported_data = import_data(directory_name, product_data, customer_data, rentals_data) + customers_file = imported_data[0] + products_file = imported_data[1] + rentals_file = imported_data[2] + + with open(customers_file, 'r') as customer: + reader = csv.reader(customer) + for row in reader: + c_dict = {'User ID': row[0], 'Name': row[1], 'Address': row[2], + 'zip code': row[3], 'phone number': row[4], 'email': row[5]} + list_of_customers.append(c_dict) + list_of_customers.pop(0) + with open(products_file, 'r') as product: + reader = csv.reader(product) + for row in reader: + p_dict = {'Product ID': row[0], 'Description': row[1], 'Product Type': row[2], 'Quantity available': row[3]} + list_of_products.append(p_dict) + list_of_products.pop(0) + with open(rentals_file, 'r') as rentals: + reader = csv.reader(rentals) + for row in reader: + r_dict = {'Product ID': row[0], 'User ID': row[1]} + list_of_rentals.append(r_dict) + list_of_rentals.pop(0) + logger.info('appended all lists with content from csv files') + main_menu()() + + +# ************************************* user interface ************************************* +def main_menu(user_prompt=None): + """ + This method creates the menu for the program. + """ + valid_prompts = {"1": ReadCsvFiles, + "2": show_available_products, + "3": show_rentals, + "4": reset_db, + "q": exit_program} + options = list(valid_prompts.keys()) + + while user_prompt not in valid_prompts: + options_str = ("{}" + ", {}" * (len(options) - 1)).format(*options) + print(f"Please choose from the following options ({options_str}):") + print("1. Load csv files to database.") + print("2. Show Customer products available for rent") + print("3. Show Sales Person the list of customers") + print("4. Reset the DataBase") + print("q. Quit") + user_prompt = input(">") + return valid_prompts.get(user_prompt) + + +# ************************************* Processing ***************************************** +def db_info(): + """ + This method returns the use of the class 'ReadCsvFiles'. + :return: + """ + return ReadCsvFiles() + + +def import_data(directory_location, product_file, customer_file, rental_file): + """ + This function takes a directory name and three csv files as input, + then creates a directory and file name for use in 'ReadCsvFiles' method. + 1. product data = product.csv + 2. customer data = customers.csv + 3. rentals data = rental.csv + :param directory_location: + :param product_file: + :param customer_file: + :param rental_file: + :return:import_customer, import_product, import_rentals + """ + import_customer = directory_location + customer_file + import_product = directory_location + product_file + import_rentals = directory_location + rental_file + logger.info('returning tuple for use in method "ReadCsvFiles"') + return import_customer, import_product, import_rentals + + +def main(list_of_customers, list_of_products, list_of_rentals): + """ + Return: 2 tuples: + 1. a record count of the number of products, customers and rentals + added (in that order) + 2. a count of any errors that occurred, in the same order. + :param list_of_customers: + :param list_of_products: + :param list_of_rentals: + :return: + """ + mongo = MongoDBConnection() + + with mongo: # Context manager. + # mongodb database; create rentaldatabase + db = mongo.connection.rentaldatabase + + # collection (table) in database, (3) customers, products and rental status (rental) + customers = db["customers"] + products = db["products"] + rental = db["rental"] + result_customer = customers.insert_many(list_of_customers) # Inserts records specified in the list above + result_products = products.insert_many(list_of_products) + result_rentals = rental.insert_many(list_of_rentals) + # print_mdb_collection(customers) # Prints all records from a specified table + # print_mdb_collection(products) + # print_mdb_collection(rental) + return result_customer, result_products, result_rentals + + +def reset_db(): + """ + deletes db + :return: + """ + mongo = MongoDBConnection() + + with mongo: # Context manager. + db = mongo.connection.rentaldatabase + # start afresh next time? + drop_data = input("Drop data?") + if drop_data.upper() == 'Y': + db['customers'].drop() + db["products"].drop() + db["rental"].drop() + logger.info('dropped data from DB') + + +# ****************************************** output to the user ************************************* +def show_available_products(): + """ + As a HP Norton customer I want to see a list of all products available for rent so that I can make a rental choice. + You can have a specific field to indicate if a product is available, however, + a quantity_available of 0 is understood as “not available”. + Returns a Python dictionary of products listed as available with the following fields: + product_id. + description. + product_type. + quantity_available. + :return: + """ + + for dlop in return_db_info.list_of_products: + if dlop['Quantity available'] != '0': + print(dlop) + + +def show_rentals(): + """ + Returns a Python dictionary with the following user information from users that have rented products + matching product_id: + user_id. + name. + address. + phone_number. + email. + """ + return_db_info = db_info() + for doc in return_db_info.list_of_customers: + logger.info('producing a list of products, customers, and rentals.') + print(doc) + + +# ***************************************** execution *********************************************** +def exit_program(): + """This method exits the program""" + logger.info('called exit_program') + sys.exit() + + +if __name__ == "__main__": + main_menu()() diff --git a/students/template_student/lesson05/assignment/tests/test_database.py b/students/Justin_Jameson/lesson05/assignment/tests/test_database.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson05/assignment/tests/test_database.py rename to students/Justin_Jameson/lesson05/assignment/tests/test_database.py diff --git a/students/Justin_Jameson/lesson05/chat from zoom lesson 5.txt b/students/Justin_Jameson/lesson05/chat from zoom lesson 5.txt new file mode 100644 index 0000000..5247b6b --- /dev/null +++ b/students/Justin_Jameson/lesson05/chat from zoom lesson 5.txt @@ -0,0 +1,110 @@ +From Kyle Creek to Everyone: 06:02 PM +I am ready whenever +From danielcastro to Everyone: 06:02 PM +yes ready +From PYTHON Host to Everyone: 06:04 PM +Any volunteer to answer the question :) +From Sam Chang to Everyone: 06:18 PM +not yet +From Me to Everyone: 06:18 PM +yes +From Kyle Creek to Everyone: 06:18 PM +I tried to install the software. Not sure if it works +From Aaron Devey to Everyone: 06:19 PM +haven't tried yet +From Kyle Creek to Everyone: 06:20 PM +I had to go to the mongo website to install Mongo +From danielcastro to Everyone: 06:20 PM +theres a test file you can run to make sure everything was installed +From Aaron Devey to Everyone: 06:20 PM +brew is for mac +https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/ <--- windows instructions +From Kyle Creek to Everyone: 06:21 PM +I have a question about Mongo, or maybe API's in general. From what I"ve gathered Mongo is an API. I always had the understand that you query APIs for data and they return it. IN the samples provided it seems like you build the data and store it in a MongoDB? +From Me to Everyone: 06:21 PM +Thanks Aaron! +From Kyle Creek to Everyone: 06:25 PM +Yeah that makes sense +From PYTHON Host to Everyone: 06:26 PM +Does anyone have a Windows computer? +From Kyle Creek to Everyone: 06:26 PM +I have a windows computer +From PYTHON Host to Everyone: 06:27 PM +My understanding is that you were able to install Mongo, Kyle… +From Kyle Creek to Everyone: 06:27 PM +I believe so +From PYTHON Host to Everyone: 06:27 PM +:) +From Kyle Creek to Everyone: 06:27 PM +I ran the file given in the "activity" foler and it worked +From danielcastro to Everyone: 06:29 PM +You can run this script to test it +https://canvas.uw.edu/courses/1260484/files/56075781?module_item_id=9450736 +Yes we can see it +From Kyle Creek to Everyone: 06:32 PM +what is the significance of host and port? is that like an IP addres? +From Kyle Creek to Everyone: 06:42 PM +Its gets confusing +From PYTHON Host to Everyone: 06:42 PM +Yes. +And what else? +From danielcastro to Everyone: 06:42 PM +The length of all of them might not match? +From Kyle Creek to Everyone: 06:42 PM +Uses a lot of memory? +From Lola Guerrero to Everyone: 06:42 PM +it might never finish +From Aaron Devey to Everyone: 06:42 PM +big O gets really out of hand +From PYTHON Host to Everyone: 06:43 PM +Or at least not within reasonable time... +Say we need to browse through 1,000,000 records in one for loop, 1,000 in the second, 1,000 in the thitd, +From Aaron Devey to Everyone: 06:43 PM +exponential loops +From PYTHON Host to Everyone: 06:45 PM +And 1,000 in the fourth for loop. +The number of records retrieved does grow exponentially with number of fors. +Indexes +From Kyle Creek to Everyone: 06:47 PM +is there similiar documentation for mongo +like there is for the database stuff we used last week? +From Aaron Devey to Everyone: 06:50 PM +there should be some docs for pymongo +http://api.mongodb.com/python/current/tutorial.html +From Kyle Creek to Everyone: 06:51 PM +I think I might have misunderstood the structure. So if you would be so kind please correct me if I'm wrong. MongoDB is just the location that houses the data. The code that is written utilizes the Pymongo module to obtain and manipulate that housed data +From Aaron Devey to Everyone: 06:52 PM +MongoDB is actually a server or daemon +From PYTHON Host to Everyone: 06:52 PM +I think you are both right. +From Kyle Creek to Everyone: 06:53 PM +what is a daemon +I don't have much of a CS background so I'm trying to wrap my head around some of these conceptfs +From Aaron Devey to Everyone: 06:53 PM +there are other kinds of servers or daemons that you might already be familiar with, such as web servers +From PYTHON Host to Everyone: 06:53 PM +The point is: in real World, you would not connect to a local application, you would connect to a server, with a specified IP address. Through Python, you’d be able to insert and manipulate (query, delete, update) data. +From Aaron Devey to Everyone: 06:54 PM +when you go to a website for example, you're connecting to a web server +daemon is just another word for a server +From PYTHON Host to Everyone: 06:54 PM +The beauty of data base approach: while you are connecting to it, it I can also connect, and this is precisely when you are on FB. When you type a status, it goes to a FB database, when I am commenting on your status, it goes there, too, but from my client (browser). +From Kyle Creek to Everyone: 06:54 PM +got it. Thank you. +From PYTHON Host to Everyone: 06:57 PM +Deamon is an application running on a server; server is typically a machine, deamon is a software. +Do you see my screen with (pdb) prompt? +From Kyle Creek to Everyone: 07:00 PM +yes +where do you define the initial databse media +or does calling it initialize it +From Kyle Creek to Everyone: 07:22 PM +why do you have to assign the insert function to the "result" variable +From Kyle Creek to Everyone: 07:41 PM +I'm ready whenever +From rlarge to Everyone: 07:41 PM +ready +From Lola Guerrero to Everyone: 07:41 PM +mee too +From Sam Chang to Everyone: 07:41 PM +ready to go diff --git a/students/template_student/lesson06/activity/README.md b/students/Justin_Jameson/lesson06/activity/README.md similarity index 100% rename from students/template_student/lesson06/activity/README.md rename to students/Justin_Jameson/lesson06/activity/README.md diff --git a/students/template_student/lesson06/assignment/data/exercise.csv b/students/Justin_Jameson/lesson06/assignment/data/exercise.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson06/assignment/data/exercise.csv rename to students/Justin_Jameson/lesson06/assignment/data/exercise.csv diff --git a/students/template_student/lesson06/assignment/pylintrc b/students/Justin_Jameson/lesson06/assignment/pylintrc similarity index 100% rename from students/template_student/lesson06/assignment/pylintrc rename to students/Justin_Jameson/lesson06/assignment/pylintrc diff --git a/students/template_student/lesson06/assignment/src/good_perf.py b/students/Justin_Jameson/lesson06/assignment/src/good_perf.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson06/assignment/src/good_perf.py rename to students/Justin_Jameson/lesson06/assignment/src/good_perf.py diff --git a/students/template_student/lesson06/assignment/src/poor_perf.py b/students/Justin_Jameson/lesson06/assignment/src/poor_perf.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson06/assignment/src/poor_perf.py rename to students/Justin_Jameson/lesson06/assignment/src/poor_perf.py diff --git a/students/template_student/lesson06/assignment/tests/test_good_perf.py b/students/Justin_Jameson/lesson06/assignment/tests/test_good_perf.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson06/assignment/tests/test_good_perf.py rename to students/Justin_Jameson/lesson06/assignment/tests/test_good_perf.py diff --git a/students/template_student/lesson06/assignment/tests/test_perf.py b/students/Justin_Jameson/lesson06/assignment/tests/test_perf.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson06/assignment/tests/test_perf.py rename to students/Justin_Jameson/lesson06/assignment/tests/test_perf.py diff --git a/students/template_student/lesson07/activity/README.md b/students/Justin_Jameson/lesson07/activity/README.md similarity index 100% rename from students/template_student/lesson07/activity/README.md rename to students/Justin_Jameson/lesson07/activity/README.md diff --git a/students/template_student/lesson07/assignment/data/customer.csv b/students/Justin_Jameson/lesson07/assignment/data/customer.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson07/assignment/data/customer.csv rename to students/Justin_Jameson/lesson07/assignment/data/customer.csv diff --git a/students/template_student/lesson07/assignment/data/product.csv b/students/Justin_Jameson/lesson07/assignment/data/product.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson07/assignment/data/product.csv rename to students/Justin_Jameson/lesson07/assignment/data/product.csv diff --git a/students/template_student/lesson07/assignment/data/rental.csv b/students/Justin_Jameson/lesson07/assignment/data/rental.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson07/assignment/data/rental.csv rename to students/Justin_Jameson/lesson07/assignment/data/rental.csv diff --git a/students/template_student/lesson07/assignment/pylintrc b/students/Justin_Jameson/lesson07/assignment/pylintrc similarity index 100% rename from students/template_student/lesson07/assignment/pylintrc rename to students/Justin_Jameson/lesson07/assignment/pylintrc diff --git a/students/template_student/lesson07/assignment/tests/test_gradel07.py b/students/Justin_Jameson/lesson07/assignment/tests/test_gradel07.py old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson07/assignment/tests/test_gradel07.py rename to students/Justin_Jameson/lesson07/assignment/tests/test_gradel07.py diff --git a/students/Justin_Jameson/lesson08/Justin_Jameson_lesson08.zip b/students/Justin_Jameson/lesson08/Justin_Jameson_lesson08.zip new file mode 100644 index 0000000..3d46296 Binary files /dev/null and b/students/Justin_Jameson/lesson08/Justin_Jameson_lesson08.zip differ diff --git a/students/template_student/lesson10/activity/README.md b/students/Justin_Jameson/lesson08/activity/README.md similarity index 92% rename from students/template_student/lesson10/activity/README.md rename to students/Justin_Jameson/lesson08/activity/README.md index 48cdce8..5e05e74 100644 --- a/students/template_student/lesson10/activity/README.md +++ b/students/Justin_Jameson/lesson08/activity/README.md @@ -1 +1 @@ -placeholder +placeholder diff --git a/students/Justin_Jameson/lesson08/assignment/data/rented_items.csv b/students/Justin_Jameson/lesson08/assignment/data/rented_items.csv new file mode 100644 index 0000000..9f588d2 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/data/rented_items.csv @@ -0,0 +1,11 @@ + +Elisa Miles,LR04,Leather Sofa,25 +Edward Data,KT78,Kitchen Table,10 +Alex Gonzales,QM83,Queen Mattress,17 +Elisa Miles,LR04,Leather Sofa,25 +Edward Data,KT78,Kitchen Table,10 +Alex Gonzales,QM83,Queen Mattress,17 +Susan Wong,LR01,Small lamp,7.5 +Susan Wong,LR02,Television,28 +Susan Wong,BR07,LED lamp,5.5 +Susan Wong,KT08,Basic refrigerator,40 diff --git a/students/Justin_Jameson/lesson08/assignment/data/test_invoice_file - Copy.csv b/students/Justin_Jameson/lesson08/assignment/data/test_invoice_file - Copy.csv new file mode 100644 index 0000000..f2ddaa6 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/data/test_invoice_file - Copy.csv @@ -0,0 +1,6 @@ +customer_name,item_code,item_description,item_monthly_price +Elisa Miles,LR04,Leather Sofa,25 +Edward Data,KT78,Kitchen Table,10 +Gonzales,BR02,Queen Mattress,17 +Edward Data,KT78,Kitchen Table,10 +Gonzales,BR02,Queen Mattress,17 diff --git a/students/Justin_Jameson/lesson08/assignment/data/test_invoice_file.csv b/students/Justin_Jameson/lesson08/assignment/data/test_invoice_file.csv new file mode 100644 index 0000000..d45675c --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/data/test_invoice_file.csv @@ -0,0 +1,10 @@ +customer_name,item_code,item_description,item_monthly_price +Elisa Miles,LR04,Leather Sofa,25 +Edward Data,KT78,Kitchen Table,10 +Gonzales,BR02,Queen Mattress,17 +Edward Data,KT78,Kitchen Table,10 +Gonzales,BR02,Queen Mattress,17 +Susan,LR01,Small lamp,7.5 +Susan,LR02,Television,28 +Susan,BR07,LED lamp,5.5 +Susan,KT08,Basic refrigerator,40 diff --git a/students/Justin_Jameson/lesson08/assignment/data/test_items - Copy.csv b/students/Justin_Jameson/lesson08/assignment/data/test_items - Copy.csv new file mode 100644 index 0000000..f0ac872 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/data/test_items - Copy.csv @@ -0,0 +1,4 @@ +LR01,Small lamp,7.5 +LR02,Television,28 +BR07,LED lamp,5.5 +KT08,Basic refrigerator,40 diff --git a/students/Justin_Jameson/lesson08/assignment/data/test_items.csv b/students/Justin_Jameson/lesson08/assignment/data/test_items.csv new file mode 100644 index 0000000..f0ac872 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/data/test_items.csv @@ -0,0 +1,4 @@ +LR01,Small lamp,7.5 +LR02,Television,28 +BR07,LED lamp,5.5 +KT08,Basic refrigerator,40 diff --git a/students/template_student/lesson09/assignment/pylintrc b/students/Justin_Jameson/lesson08/assignment/pylintrc similarity index 96% rename from students/template_student/lesson09/assignment/pylintrc rename to students/Justin_Jameson/lesson08/assignment/pylintrc index 0d96a23..c6cccdb 100644 --- a/students/template_student/lesson09/assignment/pylintrc +++ b/students/Justin_Jameson/lesson08/assignment/pylintrc @@ -1,236 +1,236 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add to the black list. It should be a base name, not a -# path. You may set this option multiple times. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifier separated by comma (,) or put this option -# multiple time. -disable= too-few-public-methods, too-many-arguments - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html -output-format=text - -# Include message's id in output -include-ids=no - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=yes - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (R0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (R0004). -comment=no - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching names used for dummy variables (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=80 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. -generated-members=REQUEST,acl_users,aq_parent - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add to the black list. It should be a base name, not a +# path. You may set this option multiple times. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifier separated by comma (,) or put this option +# multiple time. +disable= too-few-public-methods, too-many-arguments + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html +output-format=text + +# Include message's id in output +include-ids=no + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (R0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (R0004). +comment=no + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching names used for dummy variables (i.e. not used). +dummy-variables-rgx=_|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. +generated-members=REQUEST,acl_users,aq_parent + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp diff --git a/students/Justin_Jameson/lesson08/assignment/src/Justin_Jameson_with_Partial_inventory.zip b/students/Justin_Jameson/lesson08/assignment/src/Justin_Jameson_with_Partial_inventory.zip new file mode 100644 index 0000000..d0c4cb7 Binary files /dev/null and b/students/Justin_Jameson/lesson08/assignment/src/Justin_Jameson_with_Partial_inventory.zip differ diff --git a/students/Justin_Jameson/lesson08/assignment/src/Testing.py b/students/Justin_Jameson/lesson08/assignment/src/Testing.py new file mode 100644 index 0000000..a455e99 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/src/Testing.py @@ -0,0 +1,19 @@ +import csv + + +def single_customer(customer_name, invoice_file): + # open csv file and read lines. + with open(invoice_file, 'r', newline='') as rcsvfile: + reader = csv.reader(rcsvfile, delimiter=',', quotechar='"') + for row in reader: + # write to the invoice to file. + def simple_intro(item_code, item_description, item_monthly_price): + with open('../data/test_invoice_file.csv', 'a', newline='') as wcsvfile: + writer = csv.writer(wcsvfile, delimiter=',', quotechar='"') + new_row = [customer_name, item_code, item_description, item_monthly_price] + writer.writerow(new_row) + return print(new_row) + simple_intro(row[0], row[1], row[2]) + + +single_customer('Susan', '../data/test_items.csv') diff --git a/students/Justin_Jameson/lesson08/assignment/src/inventory.py b/students/Justin_Jameson/lesson08/assignment/src/inventory.py new file mode 100644 index 0000000..47733f1 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/src/inventory.py @@ -0,0 +1,76 @@ +# ************************** +# Title: inventory.py +# Desc: +# 1. Create a python module called inventory.py, to replace the existing spreadsheet. +# 2. Create a function called add_furniture that takes the following input parameters: +# invoice_file +# customer_name +# item_code +# item_description +# item_monthly_price +# This function will create invoice_file (to replace the spreadsheet’s data) +# if it doesnt exist, or append a new line to it if it does exist. +# +# 3. Create a function called single_customer: +# Input parameters: customer_name, invoice_file. +# Output: Returns a function that takes one parameter, rental_items. +# single_customer needs to use functools.partial and closures, in order to return a function +# that will iterate through rental_items and add each item to invoice_file. +# +# should write a try catch block to identify if items are not included such as if item no has more than len(4) error. +# +# Change Log: (Who, When, What) +# Justin Jameson, 20190525, created file +# +# ************************** + +import csv +from functools import partial + + +existing_invoice_file = '../data/rented_items.csv' + + +def add_furniture(invoice_file=existing_invoice_file, customer_name='Name', + item_code='Item', item_description='Description', item_monthly_price='Price'): + """ + This function creates invoice_file if it does not exist, or appends a new line to it if it does exist. + :param invoice_file: The name of the csv file(s) that will be added to the master (single_customer) invoice. + :param customer_name: The name of the Customer who rented the furniture. + :param item_code: The coding identifier for the rented furniture. + :param item_description: A short description of the furniture. + :param item_monthly_price: The amount rental amount for the furniture. + :return: + """ + with open(invoice_file, 'a', newline='') as csvfile: + writer = csv.writer(csvfile, delimiter=',', quotechar='"') + new_row = [customer_name, item_code, item_description, item_monthly_price] + writer.writerow(new_row) + + +def single_customer(customer_name, invoice_file): + """ + This function imports a csv file, reads the rows, then writes the row to the invoice csv file. + :param customer_name: A single customer with multiple rentals. + :param invoice_file: File that the invoice will write to (database). + :return: + """ + with open(invoice_file, 'r', newline='') as rcsvfile: + reader = csv.reader(rcsvfile, delimiter=',', quotechar='"') + for row in reader: + mult_entry_single_customer = partial(add_furniture, existing_invoice_file, customer_name) + mult_entry_single_customer(row[0], row[1], row[2]) + + +if __name__ == "__main__": + add_furniture("../data/rented_items.csv", "Elisa Miles", "LR04", "Leather Sofa", 25) + add_furniture("../data/rented_items.csv", "Edward Data", "KT78", "Kitchen Table", 10) + add_furniture("../data/rented_items.csv", "Alex Gonzales", "QM83", "Queen Mattress", 17) + single_customer("Susan Wong", "../data/test_items.csv") + + + + + # my_single_customer("XYAJ", "TABLE", 22) + +# https://www.learnpython.org/en/Partial_functions diff --git a/students/Justin_Jameson/lesson08/assignment/src/moreTesting.py b/students/Justin_Jameson/lesson08/assignment/src/moreTesting.py new file mode 100644 index 0000000..62c7599 --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/src/moreTesting.py @@ -0,0 +1,46 @@ +from functools import partial +import csv + +existing_invoice_file = '../data/rented_items.csv' + +def add_furniture(invoice_file='existing_invoice_file', customer_name='Name', + item_code='Item', item_description='Description', item_monthly_price='Price'): + print(invoice_file, customer_name, item_code,item_description, item_monthly_price) + + +def single_customer(customer_name, invoice_file): + with open(invoice_file, 'r', newline='') as rcsvfile: + reader = csv.reader(rcsvfile, delimiter=',', quotechar='"') + for row in reader: + mult_entry_single_customer = partial(add_furniture, existing_invoice_file, customer_name) + # mult_entry_single_customer('lro4', 'leather sofa', 25) + mult_entry_single_customer(row[0], row[1], row[2]) + + +add_furniture("../data/rented_items.csv", "Elisa Miles", "LR04", "Leather Sofa", 25) +add_furniture("../data/rented_items.csv", "Edward Data", "KT78", "Kitchen Table", 10) +add_furniture("../data/rented_items.csv", "Alex Gonzales", "QM83", "Queen Mattress", 17) +single_customer("Susan Wong", "../data/test_items.csv") + +# mult_entry_single_customer = single_customer("Susan Wong", "../data/test_items.csv") +# mult_entry_single_customer('lro4', 'leather sofa', 25) + + +# *************************************************************** +# # mult_entry_single_customer = partial(add_furniture, customer_name, invoice_file) +# # open csv file and read lines. +# with open(invoice_file, 'r', newline='') as rcsvfile: +# reader = csv.reader(rcsvfile, delimiter=',', quotechar='"') +# for row in reader: +# mult_entry_single_customer = partial(add_furniture, customer_name, existing_invoice_file) +# mult_entry_single_customer(row[0], row[1], row[2]) +# print(row) +# print(mult_entry_single_customer(row[0], row[1], row[2])) +# # write to the invoice to file. +# # def invoice_file(item_code, item_description, item_monthly_price): +# # with open(existing_invoice_file, 'a', newline='') as wcsvfile: +# # writer = csv.writer(wcsvfile, delimiter=',', quotechar='"') +# # new_row = [customer_name, item_code, item_description, item_monthly_price] +# # writer.writerow(new_row) +# # return print(new_row) +# # invoice_file(row[0], row[1], row[2]) \ No newline at end of file diff --git a/students/Justin_Jameson/lesson08/assignment/src/tester.py b/students/Justin_Jameson/lesson08/assignment/src/tester.py new file mode 100644 index 0000000..9919e3a --- /dev/null +++ b/students/Justin_Jameson/lesson08/assignment/src/tester.py @@ -0,0 +1,6 @@ +from .inventory import add_furniture, single_customer +add_furniture("rented_items.csv", "Elisa Miles", "LR04", "Leather Sofa", 25) +add_furniture("rented_items.csv", "Edward Data", "KT78", "Kitchen Table", 10) +add_furniture("rented_items.csv", "Alex Gonzales", "Queen Mattress", 17) +# create_invoice = single_customer("Susan Wong", "rented_items.csv") +# create_invoice("test_items.csv") diff --git a/students/template_student/lesson08/assignment/tests/test_inventory.py b/students/Justin_Jameson/lesson08/assignment/tests/test_inventory.py old mode 100755 new mode 100644 similarity index 93% rename from students/template_student/lesson08/assignment/tests/test_inventory.py rename to students/Justin_Jameson/lesson08/assignment/tests/test_inventory.py index cb1d05e..2bd3a0d --- a/students/template_student/lesson08/assignment/tests/test_inventory.py +++ b/students/Justin_Jameson/lesson08/assignment/tests/test_inventory.py @@ -1,19 +1,19 @@ -""" - Autograde Lesson 8 assignment - -""" - -import pytest - -import inventory as l - - - -def test_add_furniture(invoice_file, customer_name, item_code, item_description, item_monthly_price): - - - -def single_customer(customer_name, invoice_file): - - +""" + Autograde Lesson 8 assignment + +""" + +import pytest + +import inventory as l + + + +def test_add_furniture(invoice_file, customer_name, item_code, item_description, item_monthly_price): + + + +def single_customer(customer_name, invoice_file): + + \ No newline at end of file diff --git a/students/template_student/lesson09/activity/locke_manager.py b/students/Justin_Jameson/lesson09/activity/locke_manager.py similarity index 93% rename from students/template_student/lesson09/activity/locke_manager.py rename to students/Justin_Jameson/lesson09/activity/locke_manager.py index ce8b925..7f844a0 100644 --- a/students/template_student/lesson09/activity/locke_manager.py +++ b/students/Justin_Jameson/lesson09/activity/locke_manager.py @@ -1,3 +1,3 @@ -class Locke: - -if __name__ == '__main__': +class Locke: + +if __name__ == '__main__': diff --git a/students/template_student/lesson09/assignment/data/furniture/chair/couch/sofa_400_clr_10056.png b/students/Justin_Jameson/lesson09/assignment/data/furniture/chair/couch/sofa_400_clr_10056.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/furniture/chair/couch/sofa_400_clr_10056.png rename to students/Justin_Jameson/lesson09/assignment/data/furniture/chair/couch/sofa_400_clr_10056.png diff --git a/students/template_student/lesson09/assignment/data/furniture/chair/metal_chair_back_isometric_400_clr_17527.png b/students/Justin_Jameson/lesson09/assignment/data/furniture/chair/metal_chair_back_isometric_400_clr_17527.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/furniture/chair/metal_chair_back_isometric_400_clr_17527.png rename to students/Justin_Jameson/lesson09/assignment/data/furniture/chair/metal_chair_back_isometric_400_clr_17527.png diff --git a/students/template_student/lesson09/assignment/data/furniture/table/basic_desk_main_400_clr_17523.png b/students/Justin_Jameson/lesson09/assignment/data/furniture/table/basic_desk_main_400_clr_17523.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/furniture/table/basic_desk_main_400_clr_17523.png rename to students/Justin_Jameson/lesson09/assignment/data/furniture/table/basic_desk_main_400_clr_17523.png diff --git a/students/template_student/lesson09/assignment/data/furniture/table/desk_isometric_back_400_clr_17524.png b/students/Justin_Jameson/lesson09/assignment/data/furniture/table/desk_isometric_back_400_clr_17524.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/furniture/table/desk_isometric_back_400_clr_17524.png rename to students/Justin_Jameson/lesson09/assignment/data/furniture/table/desk_isometric_back_400_clr_17524.png diff --git a/students/template_student/lesson09/assignment/data/furniture/table/table_with_cloth_400_clr_10664.png b/students/Justin_Jameson/lesson09/assignment/data/furniture/table/table_with_cloth_400_clr_10664.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/furniture/table/table_with_cloth_400_clr_10664.png rename to students/Justin_Jameson/lesson09/assignment/data/furniture/table/table_with_cloth_400_clr_10664.png diff --git a/students/Justin_Jameson/lesson09/assignment/data/list_of_files.bat b/students/Justin_Jameson/lesson09/assignment/data/list_of_files.bat new file mode 100644 index 0000000..068a3f4 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/data/list_of_files.bat @@ -0,0 +1 @@ +dir /b /s > List_of_jpg.txt diff --git a/students/template_student/lesson09/assignment/data/new/chairs_balancing_stacked_400_clr_11525.png b/students/Justin_Jameson/lesson09/assignment/data/new/chairs_balancing_stacked_400_clr_11525.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/new/chairs_balancing_stacked_400_clr_11525.png rename to students/Justin_Jameson/lesson09/assignment/data/new/chairs_balancing_stacked_400_clr_11525.png diff --git a/students/template_student/lesson09/assignment/data/new/hotel_room_400_clr_12721.png b/students/Justin_Jameson/lesson09/assignment/data/new/hotel_room_400_clr_12721.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/new/hotel_room_400_clr_12721.png rename to students/Justin_Jameson/lesson09/assignment/data/new/hotel_room_400_clr_12721.png diff --git a/students/template_student/lesson09/assignment/data/old/couple_on_swing_bench_400_clr_12844.png b/students/Justin_Jameson/lesson09/assignment/data/old/couple_on_swing_bench_400_clr_12844.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/old/couple_on_swing_bench_400_clr_12844.png rename to students/Justin_Jameson/lesson09/assignment/data/old/couple_on_swing_bench_400_clr_12844.png diff --git a/students/template_student/lesson09/assignment/data/old/sitting_in_chair_relaxing_400_clr_6028.png b/students/Justin_Jameson/lesson09/assignment/data/old/sitting_in_chair_relaxing_400_clr_6028.png old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson09/assignment/data/old/sitting_in_chair_relaxing_400_clr_6028.png rename to students/Justin_Jameson/lesson09/assignment/data/old/sitting_in_chair_relaxing_400_clr_6028.png diff --git a/students/template_student/lesson10/assignment/pylintrc b/students/Justin_Jameson/lesson09/assignment/pylintrc similarity index 96% rename from students/template_student/lesson10/assignment/pylintrc rename to students/Justin_Jameson/lesson09/assignment/pylintrc index 0d96a23..c6cccdb 100644 --- a/students/template_student/lesson10/assignment/pylintrc +++ b/students/Justin_Jameson/lesson09/assignment/pylintrc @@ -1,236 +1,236 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add to the black list. It should be a base name, not a -# path. You may set this option multiple times. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=yes - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifier separated by comma (,) or put this option -# multiple time. -disable= too-few-public-methods, too-many-arguments - - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html -output-format=text - -# Include message's id in output -include-ids=no - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=yes - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (R0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (R0004). -comment=no - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching names used for dummy variables (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=80 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. -generated-members=REQUEST,acl_users,aq_parent - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add to the black list. It should be a base name, not a +# path. You may set this option multiple times. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifier separated by comma (,) or put this option +# multiple time. +disable= too-few-public-methods, too-many-arguments + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html +output-format=text + +# Include message's id in output +include-ids=no + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (R0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (R0004). +comment=no + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching names used for dummy variables (i.e. not used). +dummy-variables-rgx=_|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. +generated-members=REQUEST,acl_users,aq_parent + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp diff --git a/students/Justin_Jameson/lesson09/assignment/src/charges_calc.log b/students/Justin_Jameson/lesson09/assignment/src/charges_calc.log new file mode 100644 index 0000000..dc69b21 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/charges_calc.log @@ -0,0 +1,13 @@ +DEBUG:root:called parse_cmd +2019-06-02 22:26:57,016 charges_calc.py:32 DEBUG called parse_cmd +DEBUG:root:about to return parser.parse_arg +2019-06-02 22:26:57,017 charges_calc.py:36 DEBUG about to return parser.parse_arg +2019-06-02 23:44:54,409 charges_calc.py:41 DEBUG Calling parse_cmd_arguments() +2019-06-02 23:47:18,404 charges_calc.py:41 DEBUG Calling parse_cmd_arguments() +2019-06-02 23:47:18,406 charges_calc.py:43 INFO 'parse_cmd_arguments' returned Namespace(input=None, output=None) +2019-06-02 23:47:18,406 charges_calc.py:41 DEBUG Calling load_rentals_file(None) +2019-06-03 12:53:00,170 charges_calc.py:41 DEBUG Calling parse_cmd_arguments() +2019-06-03 12:53:00,173 charges_calc.py:43 INFO 'parse_cmd_arguments' returned Namespace(input=None, output=None) +2019-06-03 12:53:00,174 charges_calc.py:41 DEBUG Calling load_rentals_file(None) +2019-06-03 12:53:25,520 charges_calc.py:41 DEBUG Calling parse_cmd_arguments() +2019-06-05 19:50:00,530 charges_calc.py:41 DEBUG Calling parse_cmd_arguments() diff --git a/students/Justin_Jameson/lesson09/assignment/src/charges_calc.py b/students/Justin_Jameson/lesson09/assignment/src/charges_calc.py new file mode 100644 index 0000000..fcd95e7 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/charges_calc.py @@ -0,0 +1,100 @@ +# -------------------------------------------------# +# # Title: charges calculator for Inventory management. +# # Dev: unknown +# # Date: 4/17/2019 +# # ChangeLog: (Who, What) +# Justin Jameson +# correct ouput to output line 20 'ouptu JSON file' +# in source.json removed extra comma on line 5884 from +# 'units_rented': 7,, +# imported logger +# 20190602 updating file to use decorators to induce logging. +# #-------------------------------------------------# + +""" Returns total price paid for individual rentals """ + +import argparse +import json +import datetime +import math +import logging +import functools + +logging.basicConfig(filename='charges_calc_updated.log', level=logging.DEBUG) +log_format = "%(asctime)s %(filename)s:%(lineno)-3d %(levelname)s %(message)s" +formatter = logging.Formatter(log_format) +file_handler = logging.FileHandler('charges_calc.log') +file_handler.setFormatter(formatter) +logger = logging.getLogger() +logger.addHandler(file_handler) +do_debug = input('Debug? Y/N: ') + + +def debug(func): + """Print the function signature and return value""" + if do_debug.lower() == 'y': + @functools.wraps(func) + def wrapper_debug(*args, **kwargs): + args_repr = [repr(a) for a in args] + kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()] + signature = ", ".join(args_repr + kwargs_repr) + logging.debug(f"Calling {func.__name__}({signature})") + value = func(*args, **kwargs) + logging.info(f"{func.__name__!r} returned {value!r}") + return value + return wrapper_debug + else: + @functools.wraps(func) + def debug_disabled(*args, **kwargs): + # print("Debug has been disabled") + returned_value = func(*args, **kwargs) + return returned_value + return debug_disabled + + +@debug +def parse_cmd_arguments(): + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument('-i', '--input', help='input JSON file', required=True) + parser.add_argument('-o', '--output', help='output JSON file', required=True) + return parser.parse_args() + + +@debug +def load_rentals_file(filename): + with open(filename) as file: + try: + data = json.load(file) + except: + logging.warning('load_rentals_files threw an exception') + exit(0) + return data + + +@debug +def calculate_additional_fields(data): + for value in data.values(): + try: + rental_start = datetime.datetime.strptime(value['rental_start'], '%m/%d/%y') + rental_end = datetime.datetime.strptime(value['rental_end'], '%m/%d/%y') + value['total_days'] = (rental_end - rental_start).days + value['total_price'] = value['total_days'] * value['price_per_day'] + value['sqrt_total_price'] = math.sqrt(value['total_price']) + value['unit_cost'] = value['total_price'] / value['units_rented'] + except: + logging.warning('except block of calculate_add... this will exit the program without') + exit(0) + return data + + +@debug +def save_to_json(filename, data): + with open(filename, 'w') as file: + json.dump(data, file) + + +if __name__ == "__main__": + args = parse_cmd_arguments() + data = load_rentals_file(args.input) + data = calculate_additional_fields(data) + save_to_json(args.output, data) diff --git a/students/Justin_Jameson/lesson09/assignment/src/charges_calc_updated.log b/students/Justin_Jameson/lesson09/assignment/src/charges_calc_updated.log new file mode 100644 index 0000000..231c4c6 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/charges_calc_updated.log @@ -0,0 +1,9 @@ +DEBUG:root:Calling parse_cmd_arguments() +DEBUG:root:Calling parse_cmd_arguments() +INFO:root:'parse_cmd_arguments' returned Namespace(input=None, output=None) +DEBUG:root:Calling load_rentals_file(None) +DEBUG:root:Calling parse_cmd_arguments() +INFO:root:'parse_cmd_arguments' returned Namespace(input=None, output=None) +DEBUG:root:Calling load_rentals_file(None) +DEBUG:root:Calling parse_cmd_arguments() +DEBUG:root:Calling parse_cmd_arguments() diff --git a/students/Justin_Jameson/lesson09/assignment/src/database.py b/students/Justin_Jameson/lesson09/assignment/src/database.py new file mode 100644 index 0000000..61a80bb --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/database.py @@ -0,0 +1,235 @@ +# -------------------------------------------------# +# # Title: Lesson 09 database.py +# # Dev: Justin Jameson +# # Date: 5/18/2019 +# # ChangeLog: (Who, when, What) +# # adding ideas for mongo context manager. +# -------------------------------------------------# +from pymongo import MongoClient +import sys +import csv +import logging + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# ************************************** Defining variables ************************************* +directory_name = '..\\.\\data\\' +product_data = 'product.csv' +customer_data = 'customers.csv' +rentals_data = 'rental.csv' +logger.info('defined directory name and the following .csv files: product_data, customer_data, and rental_data') + + +# ******************************************** Defining Classes ********************************* +class MongoDBConnection: + """ + MongoDB Connection + """ + + def __init__(self, host='127.0.0.1', port=27017): + """ be sure to use the ip address not name for local windows""" + self.host = host + self.port = port + self.connection = None + logger.info('created connection to host {} and port {}'.format(self.host, self.port)) + # maybe add an option to offer client log in? + + def __enter__(self): + self.connection = MongoClient(self.host, self.port) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.connection.close() + + +class ReadCsvFiles: + """ + This class calls 'import_data' method to access the csv files. + Then reads the csv files, and turns them into a list of dictionaries. + Then sends the list to the 'main' method for incorporation into MongoDB. + This class also uses the self items for calls in other methods. + + :return: + """ + def __init__(self, list_of_customers=[], list_of_products=[], list_of_rentals=[]): + self.list_of_customers = list_of_customers + self.list_of_products = list_of_products + self.list_of_rentals = list_of_rentals + + logger.info('created empty lists') + imported_data = import_data(directory_name, product_data, customer_data, rentals_data) + customers_file = imported_data[0] + products_file = imported_data[1] + rentals_file = imported_data[2] + + with open(customers_file, 'r') as customer: + reader = csv.reader(customer) + for row in reader: + c_dict = {'User ID': row[0], 'Name': row[1], 'Address': row[2], + 'zip code': row[3], 'phone number': row[4], 'email': row[5]} + list_of_customers.append(c_dict) + list_of_customers.pop(0) + with open(products_file, 'r') as product: + reader = csv.reader(product) + for row in reader: + p_dict = {'Product ID': row[0], 'Description': row[1], 'Product Type': row[2], 'Quantity available': row[3]} + list_of_products.append(p_dict) + list_of_products.pop(0) + with open(rentals_file, 'r') as rentals: + reader = csv.reader(rentals) + for row in reader: + r_dict = {'Product ID': row[0], 'User ID': row[1]} + list_of_rentals.append(r_dict) + list_of_rentals.pop(0) + logger.info('appended all lists with content from csv files') + return + + +# ************************************* user interface ************************************* +def main_menu(user_prompt=None): + """ + This method creates the menu for the program. + """ + valid_prompts = {"1": ReadCsvFiles, + "2": show_available_products, + "3": show_rentals, + "4": reset_db, + "q": exit_program} + options = list(valid_prompts.keys()) + + while user_prompt not in valid_prompts: + options_str = ("{}" + ", {}" * (len(options) - 1)).format(*options) + print(f"Please choose from the following options ({options_str}):") + print("1. Load csv files to database.") + print("2. Show Customer products available for rent") + print("3. Show Sales Person the list of customers") + print("4. Reset the DataBase") + print("q. Quit") + user_prompt = input(">") + return valid_prompts.get(user_prompt) + + +# ************************************* Processing ***************************************** +def db_info(): + """ + This method returns the use of the class 'ReadCsvFiles'. + :return: + """ + return ReadCsvFiles() + + +def import_data(directory_location, product_file, customer_file, rental_file): + """ + This function takes a directory name and three csv files as input, + then creates a directory and file name for use in 'ReadCsvFiles' method. + 1. product data = product.csv + 2. customer data = customers.csv + 3. rentals data = rental.csv + :param directory_location: + :param product_file: + :param customer_file: + :param rental_file: + :return:import_customer, import_product, import_rentals + """ + import_customer = directory_location + customer_file + import_product = directory_location + product_file + import_rentals = directory_location + rental_file + logger.info('returning tuple for use in method "ReadCsvFiles"') + return import_customer, import_product, import_rentals + + +def main(list_of_customers, list_of_products, list_of_rentals): + """ + Return: 2 tuples: + 1. a record count of the number of products, customers and rentals + added (in that order) + 2. a count of any errors that occurred, in the same order. + :param list_of_customers: + :param list_of_products: + :param list_of_rentals: + :return: + """ + mongo = MongoDBConnection() + + with mongo: # Context manager. + # mongodb database; create rentaldatabase + db = mongo.connection.rentaldatabase + + # collection (table) in database, (3) customers, products and rental status (rental) + customers = db["customers"] + products = db["products"] + rental = db["rental"] + result_customer = customers.insert_many(list_of_customers) # Inserts records specified in the list above + result_products = products.insert_many(list_of_products) + result_rentals = rental.insert_many(list_of_rentals) + # print_mdb_collection(customers) # Prints all records from a specified table + # print_mdb_collection(products) + # print_mdb_collection(rental) + return result_customer, result_products, result_rentals + + +def reset_db(): + """ + deletes db + :return: + """ + mongo = MongoDBConnection() + + with mongo: # Context manager. + db = mongo.connection.rentaldatabase + # start afresh next time? + drop_data = input("Drop data?") + if drop_data.upper() == 'Y': + db['customers'].drop() + db["products"].drop() + db["rental"].drop() + logger.info('dropped data from DB') + + +# ****************************************** output to the user ************************************* +def show_available_products(): + """ + As a HP Norton customer I want to see a list of all products available for rent so that I can make a rental choice. + You can have a specific field to indicate if a product is available, however, + a quantity_available of 0 is understood as “not available”. + Returns a Python dictionary of products listed as available with the following fields: + product_id. + description. + product_type. + quantity_available. + :return: + """ + + for dlop in return_db_info.list_of_products: + if dlop['Quantity available'] != '0': + print(dlop) + + +def show_rentals(): + """ + Returns a Python dictionary with the following user information from users that have rented products + matching product_id: + user_id. + name. + address. + phone_number. + email. + """ + for doc in return_db_info.list_of_customers: + logger.info('producing a list of products, customers, and rentals.') + print(doc) + + +# ***************************************** execution *********************************************** +def exit_program(): + """This method exits the program""" + logger.info('called exit_program') + sys.exit() + + +if __name__ == "__main__": + return_db_info = db_info() + while True: + main_menu()() + input("Press Enter to continue...........") diff --git a/students/Justin_Jameson/lesson09/assignment/src/example.log b/students/Justin_Jameson/lesson09/assignment/src/example.log new file mode 100644 index 0000000..3a92009 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/example.log @@ -0,0 +1,8 @@ +DEBUG:root:This message should go to the log file +INFO:root:So should this +WARNING:root:And this, too +DEBUG:root:This message should go to the log file +INFO:root:So should this +WARNING:root:And this, too +DEBUG:root:Calling some_function() +INFO:root:'some_function' returned 'Just a funciton' diff --git a/students/Justin_Jameson/lesson09/assignment/src/jpgdiscover.py b/students/Justin_Jameson/lesson09/assignment/src/jpgdiscover.py new file mode 100644 index 0000000..f96ef55 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/jpgdiscover.py @@ -0,0 +1,42 @@ +# ************************** +# Title: jpgdiscover.py +# Desc: +# 1. Discovers all directories on the server? +# 2. Searches the Parent directory and all subdirectories for jpg files. +# 3. Works from a parent directory called images provided on the command line. +# a. The program will take the parent directory as input. +# b. As output, it will return a list of lists structured like this: +# [“full/working_directory/to/files”, [“file1.jpg”, “file2.jpg”,…], “another/working_directory”,[], etc] +# +# Change Log: (Who, When, What) +# Justin Jameson, 20190602, created file +# Justin Jameson, +# **************************# + + +import os + +# collect current directory and move back one folder. +working_directory = os.path.dirname('../') + + +def list_jpg_files(path): + """ + utilizing os.walk to recurse through the directory and find jpg files. However, only png files have been provided. + :param path: defines directory to start the search. + :return: a list of directories and file names. + """ + files = [] + # r=root, d=directories, f = files + for r, d, f in os.walk(path): + for file in f: + # direction sate find jpg files. However, no jpg files exist so I found png files instead. + if '.png' in file: + entry = [] + entry.append(os.path.join(r, file)) + files.append(entry) + return files + + +print(list_jpg_files(working_directory)) + diff --git a/students/Justin_Jameson/lesson09/assignment/src/source.json b/students/Justin_Jameson/lesson09/assignment/src/source.json new file mode 100644 index 0000000..c4e90b1 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/source.json @@ -0,0 +1,6995 @@ +{ + "RNT001": { + "product_code": "PRD80", + "units_rented": 8, + "price_per_day": 31, + "rental_start": "6/12/17", + "rental_end": "3/22/17" + }, + "RNT002": { + "product_code": "PRD11", + "units_rented": 1, + "price_per_day": 16, + "rental_start": "7/20/16", + "rental_end": "9/30/18" + }, + "RNT003": { + "product_code": "PRD22", + "units_rented": 4, + "price_per_day": 40, + "rental_start": "2/1/16", + "rental_end": "6/4/17" + }, + "RNT004": { + "product_code": "PRD86", + "units_rented": 6, + "price_per_day": 40, + "rental_start": "8/14/16", + "rental_end": "12/7/17" + }, + "RNT005": { + "product_code": "PRD70", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "7/12/17", + "rental_end": "11/23/18" + }, + "RNT006": { + "product_code": "PRD51", + "units_rented": 8, + "price_per_day": 20, + "rental_start": "8/26/18", + "rental_end": "7/29/18" + }, + "RNT007": { + "product_code": "PRD42", + "units_rented": 1, + "price_per_day": 16, + "rental_start": "7/10/17", + "rental_end": "5/31/17" + }, + "RNT008": { + "product_code": "PRD32", + "units_rented": 3, + "price_per_day": 12, + "rental_start": "10/25/18", + "rental_end": "7/4/18" + }, + "RNT009": { + "product_code": "PRD13", + "units_rented": 9, + "price_per_day": 6, + "rental_start": "11/3/18", + "rental_end": "7/28/16" + }, + "RNT010": { + "product_code": "PRD22", + "units_rented": 6, + "price_per_day": 27, + "rental_start": "3/15/18", + "rental_end": "8/27/17" + }, + "RNT011": { + "product_code": "PRD17", + "units_rented": 7, + "price_per_day": 26, + "rental_start": "9/29/17", + "rental_end": "4/29/16" + }, + "RNT012": { + "product_code": "PRD55", + "units_rented": 4, + "price_per_day": 18, + "rental_start": "10/24/17", + "rental_end": "1/15/16" + }, + "RNT013": { + "product_code": "PRD81", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "2/3/17", + "rental_end": "8/31/17" + }, + "RNT014": { + "product_code": "PRD0", + "units_rented": 7, + "price_per_day": 37, + "rental_start": "1/30/17", + "rental_end": "7/30/16" + }, + "RNT015": { + "product_code": "PRD82", + "units_rented": 10, + "price_per_day": 29, + "rental_start": "5/2/17", + "rental_end": "6/22/18" + }, + "RNT016": { + "product_code": "PRD52", + "units_rented": 10, + "price_per_day": 11, + "rental_start": "6/18/18", + "rental_end": "2/5/16" + }, + "RNT017": { + "product_code": "PRD5", + "units_rented": 10, + "price_per_day": 36, + "rental_start": "4/28/18", + "rental_end": "4/11/18" + }, + "RNT018": { + "product_code": "PRD59", + "units_rented": 9, + "price_per_day": 40, + "rental_start": "8/16/16", + "rental_end": "1/13/16" + }, + "RNT019": { + "product_code": "PRD6", + "units_rented": 8, + "price_per_day": 39, + "rental_start": "12/16/17", + "rental_end": "5/10/16" + }, + "RNT020": { + "product_code": "PRD2", + "units_rented": 9, + "price_per_day": 33, + "rental_start": "6/20/18", + "rental_end": "1/12/16" + }, + "RNT021": { + "product_code": "PRD97", + "units_rented": 3, + "price_per_day": 33, + "rental_start": "8/31/17", + "rental_end": "2/9/16" + }, + "RNT022": { + "product_code": "PRD66", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "10/3/16", + "rental_end": "11/1/17" + }, + "RNT023": { + "product_code": "PRD14", + "units_rented": 9, + "price_per_day": 20, + "rental_start": "9/13/16", + "rental_end": "11/16/18" + }, + "RNT024": { + "product_code": "PRD78", + "units_rented": 3, + "price_per_day": 20, + "rental_start": "7/14/17", + "rental_end": "11/25/18" + }, + "RNT025": { + "product_code": "PRD28", + "units_rented": 5, + "price_per_day": 26, + "rental_start": "3/2/18", + "rental_end": "5/28/16" + }, + "RNT026": { + "product_code": "PRD40", + "units_rented": 6, + "price_per_day": 24, + "rental_start": "3/27/18", + "rental_end": "4/21/16" + }, + "RNT027": { + "product_code": "PRD11", + "units_rented": 2, + "price_per_day": 27, + "rental_start": "3/28/16", + "rental_end": "8/3/16" + }, + "RNT028": { + "product_code": "PRD63", + "units_rented": 10, + "price_per_day": 17, + "rental_start": "7/6/18", + "rental_end": "5/6/17" + }, + "RNT029": { + "product_code": "PRD77", + "units_rented": 5, + "price_per_day": 10, + "rental_start": "9/5/16", + "rental_end": "5/3/18" + }, + "RNT030": { + "product_code": "PRD43", + "units_rented": 4, + "price_per_day": 31, + "rental_start": "7/1/17", + "rental_end": "4/18/17" + }, + "RNT031": { + "product_code": "PRD51", + "units_rented": 10, + "price_per_day": 27, + "rental_start": "4/18/18", + "rental_end": "4/13/17" + }, + "RNT032": { + "product_code": "PRD97", + "units_rented": 9, + "price_per_day": 34, + "rental_start": "7/2/16", + "rental_end": "7/18/16" + }, + "RNT033": { + "product_code": "PRD0", + "units_rented": 6, + "price_per_day": 8, + "rental_start": "2/5/17", + "rental_end": "3/28/17" + }, + "RNT034": { + "product_code": "PRD72", + "units_rented": 9, + "price_per_day": 36, + "rental_start": "10/11/17", + "rental_end": "4/3/16" + }, + "RNT035": { + "product_code": "PRD19", + "units_rented": 7, + "price_per_day": 20, + "rental_start": "9/15/16", + "rental_end": "11/4/17" + }, + "RNT036": { + "product_code": "PRD94", + "units_rented": 2, + "price_per_day": 14, + "rental_start": "10/16/17", + "rental_end": "1/9/18" + }, + "RNT037": { + "product_code": "PRD6", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "3/20/18", + "rental_end": "9/13/18" + }, + "RNT038": { + "product_code": "PRD5", + "units_rented": 4, + "price_per_day": 18, + "rental_start": "2/16/17", + "rental_end": "6/24/17" + }, + "RNT039": { + "product_code": "PRD61", + "units_rented": 1, + "price_per_day": 17, + "rental_start": "7/24/16", + "rental_end": "7/24/16" + }, + "RNT040": { + "product_code": "PRD51", + "units_rented": 1, + "price_per_day": 23, + "rental_start": "12/1/17", + "rental_end": "12/30/16" + }, + "RNT041": { + "product_code": "PRD59", + "units_rented": 4, + "price_per_day": 14, + "rental_start": "2/19/18", + "rental_end": "3/30/17" + }, + "RNT042": { + "product_code": "PRD18", + "units_rented": 10, + "price_per_day": 11, + "rental_start": "7/27/17", + "rental_end": "10/19/17" + }, + "RNT043": { + "product_code": "PRD68", + "units_rented": 2, + "price_per_day": 27, + "rental_start": "4/9/17", + "rental_end": "7/5/18" + }, + "RNT044": { + "product_code": "PRD43", + "units_rented": 1, + "price_per_day": 15, + "rental_start": "9/4/18", + "rental_end": "12/19/16" + }, + "RNT045": { + "product_code": "PRD62", + "units_rented": 3, + "price_per_day": 33, + "rental_start": "12/19/18", + "rental_end": "11/12/18" + }, + "RNT046": { + "product_code": "PRD46", + "units_rented": 5, + "price_per_day": 34, + "rental_start": "10/15/18", + "rental_end": "1/8/18" + }, + "RNT047": { + "product_code": "PRD52", + "units_rented": 2, + "price_per_day": 12, + "rental_start": "8/3/18", + "rental_end": "6/24/16" + }, + "RNT048": { + "product_code": "PRD32", + "units_rented": 5, + "price_per_day": 36, + "rental_start": "9/5/17", + "rental_end": "10/28/16" + }, + "RNT049": { + "product_code": "PRD77", + "units_rented": 4, + "price_per_day": 14, + "rental_start": "1/9/18", + "rental_end": "3/14/18" + }, + "RNT050": { + "product_code": "PRD6", + "units_rented": 8, + "price_per_day": 34, + "rental_start": "12/6/18", + "rental_end": "6/30/17" + }, + "RNT051": { + "product_code": "PRD45", + "units_rented": 6, + "price_per_day": 33, + "rental_start": "2/18/16", + "rental_end": "7/19/17" + }, + "RNT052": { + "product_code": "PRD53", + "units_rented": 7, + "price_per_day": 9, + "rental_start": "10/30/16", + "rental_end": "3/13/17" + }, + "RNT053": { + "product_code": "PRD17", + "units_rented": 7, + "price_per_day": 10, + "rental_start": "12/12/16", + "rental_end": "9/20/17" + }, + "RNT054": { + "product_code": "PRD62", + "units_rented": 1, + "price_per_day": 6, + "rental_start": "12/31/16", + "rental_end": "12/21/17" + }, + "RNT055": { + "product_code": "PRD16", + "units_rented": 6, + "price_per_day": 33, + "rental_start": "2/4/18", + "rental_end": "9/14/18" + }, + "RNT056": { + "product_code": "PRD43", + "units_rented": 9, + "price_per_day": 40, + "rental_start": "4/12/18", + "rental_end": "2/27/16" + }, + "RNT057": { + "product_code": "PRD58", + "units_rented": 4, + "price_per_day": 23, + "rental_start": "9/23/17", + "rental_end": "9/17/18" + }, + "RNT058": { + "product_code": "PRD35", + "units_rented": 8, + "price_per_day": 28, + "rental_start": "7/14/17", + "rental_end": "1/25/17" + }, + "RNT059": { + "product_code": "PRD9", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "3/26/16", + "rental_end": "10/11/16" + }, + "RNT060": { + "product_code": "PRD84", + "units_rented": 8, + "price_per_day": 29, + "rental_start": "2/15/16", + "rental_end": "1/18/16" + }, + "RNT061": { + "product_code": "PRD35", + "units_rented": 8, + "price_per_day": 24, + "rental_start": "2/12/18", + "rental_end": "2/28/17" + }, + "RNT062": { + "product_code": "PRD29", + "units_rented": 3, + "price_per_day": 12, + "rental_start": "8/25/18", + "rental_end": "6/3/18" + }, + "RNT063": { + "product_code": "PRD47", + "units_rented": 4, + "price_per_day": 35, + "rental_start": "1/11/17", + "rental_end": "5/18/18" + }, + "RNT064": { + "product_code": "PRD83", + "units_rented": 3, + "price_per_day": 23, + "rental_start": "2/24/17", + "rental_end": "6/28/17" + }, + "RNT065": { + "product_code": "PRD61", + "units_rented": 1, + "price_per_day": 11, + "rental_start": "10/11/18", + "rental_end": "12/12/16" + }, + "RNT066": { + "product_code": "PRD74", + "units_rented": 10, + "price_per_day": 39, + "rental_start": "2/28/16", + "rental_end": "11/12/17" + }, + "RNT067": { + "product_code": "PRD29", + "units_rented": 5, + "price_per_day": 31, + "rental_start": "1/18/18", + "rental_end": "10/18/17" + }, + "RNT068": { + "product_code": "PRD71", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "3/28/16", + "rental_end": "5/20/16" + }, + "RNT069": { + "product_code": "PRD38", + "units_rented": 9, + "price_per_day": 27, + "rental_start": "10/21/16", + "rental_end": "2/17/17" + }, + "RNT070": { + "product_code": "PRD82", + "units_rented": 3, + "price_per_day": 13, + "rental_start": "10/24/17", + "rental_end": "10/21/18" + }, + "RNT071": { + "product_code": "PRD38", + "units_rented": 9, + "price_per_day": 6, + "rental_start": "10/5/16", + "rental_end": "5/25/16" + }, + "RNT072": { + "product_code": "PRD53", + "units_rented": 8, + "price_per_day": 32, + "rental_start": "10/6/16", + "rental_end": "6/19/18" + }, + "RNT073": { + "product_code": "PRD37", + "units_rented": 3, + "price_per_day": 23, + "rental_start": "4/3/18", + "rental_end": "9/8/18" + }, + "RNT074": { + "product_code": "PRD33", + "units_rented": 9, + "price_per_day": 22, + "rental_start": "9/9/17", + "rental_end": "7/14/17" + }, + "RNT075": { + "product_code": "PRD2", + "units_rented": 8, + "price_per_day": 25, + "rental_start": "4/25/16", + "rental_end": "11/13/18" + }, + "RNT076": { + "product_code": "PRD64", + "units_rented": 4, + "price_per_day": 20, + "rental_start": "6/6/18", + "rental_end": "5/12/16" + }, + "RNT077": { + "product_code": "PRD6", + "units_rented": 8, + "price_per_day": 14, + "rental_start": "8/15/18", + "rental_end": "11/19/16" + }, + "RNT078": { + "product_code": "PRD72", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "1/6/17", + "rental_end": "11/1/17" + }, + "RNT079": { + "product_code": "PRD85", + "units_rented": 1, + "price_per_day": 21, + "rental_start": "11/27/18", + "rental_end": "1/27/18" + }, + "RNT080": { + "product_code": "PRD8", + "units_rented": 10, + "price_per_day": 21, + "rental_start": "6/27/17", + "rental_end": "4/18/18" + }, + "RNT081": { + "product_code": "PRD52", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "2/8/18", + "rental_end": "12/9/18" + }, + "RNT082": { + "product_code": "PRD2", + "units_rented": 2, + "price_per_day": 24, + "rental_start": "10/3/16", + "rental_end": "11/16/17" + }, + "RNT083": { + "product_code": "PRD70", + "units_rented": 1, + "price_per_day": 17, + "rental_start": "9/9/17", + "rental_end": "2/6/18" + }, + "RNT084": { + "product_code": "PRD75", + "units_rented": 6, + "price_per_day": 16, + "rental_start": "5/13/17", + "rental_end": "4/29/16" + }, + "RNT085": { + "product_code": "PRD16", + "units_rented": 6, + "price_per_day": 21, + "rental_start": "2/21/18", + "rental_end": "3/20/18" + }, + "RNT086": { + "product_code": "PRD87", + "units_rented": 6, + "price_per_day": 40, + "rental_start": "12/3/18", + "rental_end": "3/20/18" + }, + "RNT087": { + "product_code": "PRD0", + "units_rented": 2, + "price_per_day": 37, + "rental_start": "8/10/16", + "rental_end": "6/18/16" + }, + "RNT088": { + "product_code": "PRD84", + "units_rented": 9, + "price_per_day": 20, + "rental_start": "6/9/16", + "rental_end": "2/25/17" + }, + "RNT089": { + "product_code": "PRD58", + "units_rented": 5, + "price_per_day": 20, + "rental_start": "11/5/18", + "rental_end": "8/15/18" + }, + "RNT090": { + "product_code": "PRD18", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "1/14/17", + "rental_end": "8/19/18" + }, + "RNT091": { + "product_code": "PRD46", + "units_rented": 7, + "price_per_day": 5, + "rental_start": "6/27/17", + "rental_end": "10/25/17" + }, + "RNT092": { + "product_code": "PRD6", + "units_rented": 10, + "price_per_day": 18, + "rental_start": "3/10/17", + "rental_end": "5/23/16" + }, + "RNT093": { + "product_code": "PRD64", + "units_rented": 2, + "price_per_day": 33, + "rental_start": "4/2/16", + "rental_end": "11/19/18" + }, + "RNT094": { + "product_code": "PRD28", + "units_rented": 3, + "price_per_day": 19, + "rental_start": "8/22/16", + "rental_end": "8/24/16" + }, + "RNT095": { + "product_code": "PRD83", + "units_rented": 6, + "price_per_day": 6, + "rental_start": "8/5/18", + "rental_end": "7/23/17" + }, + "RNT096": { + "product_code": "PRD97", + "units_rented": 1, + "price_per_day": 12, + "rental_start": "2/6/16", + "rental_end": "7/9/16" + }, + "RNT097": { + "product_code": "PRD36", + "units_rented": 7, + "price_per_day": 29, + "rental_start": "1/11/17", + "rental_end": "8/29/16" + }, + "RNT098": { + "product_code": "PRD5", + "units_rented": 7, + "price_per_day": 19, + "rental_start": "1/28/17", + "rental_end": "2/11/18" + }, + "RNT099": { + "product_code": "PRD42", + "units_rented": 1, + "price_per_day": 18, + "rental_start": "11/23/18", + "rental_end": "10/21/16" + }, + "RNT100": { + "product_code": "PRD66", + "units_rented": 6, + "price_per_day": 10, + "rental_start": "6/16/18", + "rental_end": "5/21/16" + }, + "RNT101": { + "product_code": "PRD42", + "units_rented": 9, + "price_per_day": 9, + "rental_start": "12/3/18", + "rental_end": "9/20/17" + }, + "RNT102": { + "product_code": "PRD68", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "7/17/17", + "rental_end": "12/8/16" + }, + "RNT103": { + "product_code": "PRD76", + "units_rented": 6, + "price_per_day": 20, + "rental_start": "1/24/17", + "rental_end": "2/18/16" + }, + "RNT104": { + "product_code": "PRD98", + "units_rented": 1, + "price_per_day": 31, + "rental_start": "12/20/17", + "rental_end": "8/30/16" + }, + "RNT105": { + "product_code": "PRD3", + "units_rented": 4, + "price_per_day": 32, + "rental_start": "12/29/17", + "rental_end": "2/20/16" + }, + "RNT106": { + "product_code": "PRD80", + "units_rented": 7, + "price_per_day": 35, + "rental_start": "3/14/18", + "rental_end": "1/1/18" + }, + "RNT107": { + "product_code": "PRD84", + "units_rented": 3, + "price_per_day": 11, + "rental_start": "5/30/17", + "rental_end": "6/4/16" + }, + "RNT108": { + "product_code": "PRD44", + "units_rented": 1, + "price_per_day": 26, + "rental_start": "6/5/16", + "rental_end": "3/15/17" + }, + "RNT109": { + "product_code": "PRD88", + "units_rented": 2, + "price_per_day": 30, + "rental_start": "6/26/18", + "rental_end": "1/9/17" + }, + "RNT110": { + "product_code": "PRD42", + "units_rented": 2, + "price_per_day": 33, + "rental_start": "10/25/16", + "rental_end": "7/14/18" + }, + "RNT111": { + "product_code": "PRD10", + "units_rented": 7, + "price_per_day": 5, + "rental_start": "9/4/16", + "rental_end": "11/10/17" + }, + "RNT112": { + "product_code": "PRD99", + "units_rented": 10, + "price_per_day": 20, + "rental_start": "7/11/16", + "rental_end": "9/1/16" + }, + "RNT113": { + "product_code": "PRD65", + "units_rented": 2, + "price_per_day": 6, + "rental_start": "10/19/18", + "rental_end": "11/6/18" + }, + "RNT114": { + "product_code": "PRD89", + "units_rented": 10, + "price_per_day": 14, + "rental_start": "6/6/17", + "rental_end": "1/9/16" + }, + "RNT115": { + "product_code": "PRD22", + "units_rented": 2, + "price_per_day": 8, + "rental_start": "5/11/18", + "rental_end": "2/3/16" + }, + "RNT116": { + "product_code": "PRD74", + "units_rented": 1, + "price_per_day": 8, + "rental_start": "4/14/17", + "rental_end": "8/4/16" + }, + "RNT117": { + "product_code": "PRD11", + "units_rented": 9, + "price_per_day": 29, + "rental_start": "6/12/18", + "rental_end": "12/23/18" + }, + "RNT118": { + "product_code": "PRD11", + "units_rented": 10, + "price_per_day": 23, + "rental_start": "7/23/18", + "rental_end": "6/4/17" + }, + "RNT119": { + "product_code": "PRD58", + "units_rented": 10, + "price_per_day": 28, + "rental_start": "7/19/18", + "rental_end": "12/18/17" + }, + "RNT120": { + "product_code": "PRD83", + "units_rented": 8, + "price_per_day": 6, + "rental_start": "1/3/17", + "rental_end": "8/1/16" + }, + "RNT121": { + "product_code": "PRD39", + "units_rented": 2, + "price_per_day": 11, + "rental_start": "11/30/18", + "rental_end": "2/25/17" + }, + "RNT122": { + "product_code": "PRD9", + "units_rented": 5, + "price_per_day": 16, + "rental_start": "12/4/18", + "rental_end": "4/5/17" + }, + "RNT123": { + "product_code": "PRD83", + "units_rented": 7, + "price_per_day": 13, + "rental_start": "3/2/18", + "rental_end": "7/25/17" + }, + "RNT124": { + "product_code": "PRD42", + "units_rented": 2, + "price_per_day": 11, + "rental_start": "11/3/16", + "rental_end": "3/10/17" + }, + "RNT125": { + "product_code": "PRD76", + "units_rented": 10, + "price_per_day": 27, + "rental_start": "12/15/18", + "rental_end": "7/30/18" + }, + "RNT126": { + "product_code": "PRD8", + "units_rented": 7, + "price_per_day": 10, + "rental_start": "1/10/16", + "rental_end": "7/7/17" + }, + "RNT127": { + "product_code": "PRD95", + "units_rented": 10, + "price_per_day": 39, + "rental_start": "4/8/16", + "rental_end": "8/25/18" + }, + "RNT128": { + "product_code": "PRD59", + "units_rented": 10, + "price_per_day": 29, + "rental_start": "4/8/17", + "rental_end": "12/7/17" + }, + "RNT129": { + "product_code": "PRD75", + "units_rented": 10, + "price_per_day": 6, + "rental_start": "3/23/18", + "rental_end": "5/23/17" + }, + "RNT130": { + "product_code": "PRD23", + "units_rented": 8, + "price_per_day": 5, + "rental_start": "12/17/18", + "rental_end": "6/21/17" + }, + "RNT131": { + "product_code": "PRD74", + "units_rented": 3, + "price_per_day": 18, + "rental_start": "1/15/16", + "rental_end": "5/31/16" + }, + "RNT132": { + "product_code": "PRD23", + "units_rented": 6, + "price_per_day": 32, + "rental_start": "3/17/16", + "rental_end": "2/20/17" + }, + "RNT133": { + "product_code": "PRD0", + "units_rented": 8, + "price_per_day": 19, + "rental_start": "2/14/17", + "rental_end": "9/24/18" + }, + "RNT134": { + "product_code": "PRD64", + "units_rented": 1, + "price_per_day": 37, + "rental_start": "1/23/18", + "rental_end": "9/7/18" + }, + "RNT135": { + "product_code": "PRD79", + "units_rented": 3, + "price_per_day": 11, + "rental_start": "10/13/16", + "rental_end": "8/11/16" + }, + "RNT136": { + "product_code": "PRD79", + "units_rented": 1, + "price_per_day": 5, + "rental_start": "6/10/17", + "rental_end": "10/15/17" + }, + "RNT137": { + "product_code": "PRD74", + "units_rented": 1, + "price_per_day": 5, + "rental_start": "11/6/16", + "rental_end": "9/11/17" + }, + "RNT138": { + "product_code": "PRD23", + "units_rented": 10, + "price_per_day": 22, + "rental_start": "1/4/18", + "rental_end": "12/22/18" + }, + "RNT139": { + "product_code": "PRD13", + "units_rented": 2, + "price_per_day": 23, + "rental_start": "9/13/17", + "rental_end": "5/1/17" + }, + "RNT140": { + "product_code": "PRD70", + "units_rented": 7, + "price_per_day": 7, + "rental_start": "12/14/16", + "rental_end": "2/26/17" + }, + "RNT141": { + "product_code": "PRD63", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "1/20/18", + "rental_end": "3/22/17" + }, + "RNT142": { + "product_code": "PRD66", + "units_rented": 9, + "price_per_day": 16, + "rental_start": "11/15/16", + "rental_end": "5/2/16" + }, + "RNT143": { + "product_code": "PRD38", + "units_rented": 8, + "price_per_day": 39, + "rental_start": "11/20/18", + "rental_end": "1/3/16" + }, + "RNT144": { + "product_code": "PRD51", + "units_rented": 7, + "price_per_day": 35, + "rental_start": "5/18/16", + "rental_end": "5/29/18" + }, + "RNT145": { + "product_code": "PRD31", + "units_rented": 7, + "price_per_day": 31, + "rental_start": "7/28/18", + "rental_end": "7/15/16" + }, + "RNT146": { + "product_code": "PRD56", + "units_rented": 8, + "price_per_day": 38, + "rental_start": "5/8/16", + "rental_end": "9/17/17" + }, + "RNT147": { + "product_code": "PRD94", + "units_rented": 3, + "price_per_day": 11, + "rental_start": "4/8/17", + "rental_end": "10/10/17" + }, + "RNT148": { + "product_code": "PRD33", + "units_rented": 6, + "price_per_day": 13, + "rental_start": "10/20/18", + "rental_end": "9/17/18" + }, + "RNT149": { + "product_code": "PRD34", + "units_rented": 8, + "price_per_day": 20, + "rental_start": "9/29/18", + "rental_end": "11/3/16" + }, + "RNT150": { + "product_code": "PRD88", + "units_rented": 6, + "price_per_day": 8, + "rental_start": "2/3/16", + "rental_end": "7/14/17" + }, + "RNT151": { + "product_code": "PRD93", + "units_rented": 7, + "price_per_day": 25, + "rental_start": "8/11/18", + "rental_end": "8/16/16" + }, + "RNT152": { + "product_code": "PRD89", + "units_rented": 4, + "price_per_day": 36, + "rental_start": "12/24/17", + "rental_end": "12/24/17" + }, + "RNT153": { + "product_code": "PRD12", + "units_rented": 9, + "price_per_day": 15, + "rental_start": "3/31/16", + "rental_end": "8/19/16" + }, + "RNT154": { + "product_code": "PRD35", + "units_rented": 3, + "price_per_day": 16, + "rental_start": "5/24/17", + "rental_end": "3/30/16" + }, + "RNT155": { + "product_code": "PRD30", + "units_rented": 9, + "price_per_day": 22, + "rental_start": "1/7/18", + "rental_end": "7/19/17" + }, + "RNT156": { + "product_code": "PRD2", + "units_rented": 1, + "price_per_day": 5, + "rental_start": "5/8/16", + "rental_end": "5/12/17" + }, + "RNT157": { + "product_code": "PRD72", + "units_rented": 7, + "price_per_day": 32, + "rental_start": "12/23/18", + "rental_end": "5/19/17" + }, + "RNT158": { + "product_code": "PRD3", + "units_rented": 4, + "price_per_day": 12, + "rental_start": "7/10/18", + "rental_end": "3/6/16" + }, + "RNT159": { + "product_code": "PRD51", + "units_rented": 10, + "price_per_day": 40, + "rental_start": "4/14/16", + "rental_end": "9/14/17" + }, + "RNT160": { + "product_code": "PRD61", + "units_rented": 6, + "price_per_day": 12, + "rental_start": "5/18/18", + "rental_end": "3/14/18" + }, + "RNT161": { + "product_code": "PRD13", + "units_rented": 5, + "price_per_day": 9, + "rental_start": "2/23/16", + "rental_end": "3/7/17" + }, + "RNT162": { + "product_code": "PRD52", + "units_rented": 9, + "price_per_day": 37, + "rental_start": "2/27/16", + "rental_end": "11/17/16" + }, + "RNT163": { + "product_code": "PRD43", + "units_rented": 8, + "price_per_day": 24, + "rental_start": "12/16/16", + "rental_end": "9/10/16" + }, + "RNT164": { + "product_code": "PRD71", + "units_rented": 4, + "price_per_day": 21, + "rental_start": "4/24/18", + "rental_end": "8/7/17" + }, + "RNT165": { + "product_code": "PRD33", + "units_rented": 7, + "price_per_day": 12, + "rental_start": "5/29/16", + "rental_end": "9/9/17" + }, + "RNT166": { + "product_code": "PRD60", + "units_rented": 3, + "price_per_day": 37, + "rental_start": "4/14/18", + "rental_end": "2/15/16" + }, + "RNT167": { + "product_code": "PRD34", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "2/3/17", + "rental_end": "12/11/16" + }, + "RNT168": { + "product_code": "PRD44", + "units_rented": 4, + "price_per_day": 39, + "rental_start": "10/15/16", + "rental_end": "5/25/16" + }, + "RNT169": { + "product_code": "PRD0", + "units_rented": 4, + "price_per_day": 28, + "rental_start": "3/18/18", + "rental_end": "9/25/16" + }, + "RNT170": { + "product_code": "PRD54", + "units_rented": 9, + "price_per_day": 15, + "rental_start": "9/16/18", + "rental_end": "1/11/17" + }, + "RNT171": { + "product_code": "PRD89", + "units_rented": 3, + "price_per_day": 36, + "rental_start": "10/3/16", + "rental_end": "8/17/17" + }, + "RNT172": { + "product_code": "PRD21", + "units_rented": 5, + "price_per_day": 15, + "rental_start": "3/29/18", + "rental_end": "4/24/18" + }, + "RNT173": { + "product_code": "PRD31", + "units_rented": 2, + "price_per_day": 24, + "rental_start": "10/12/17", + "rental_end": "6/8/18" + }, + "RNT174": { + "product_code": "PRD40", + "units_rented": 3, + "price_per_day": 22, + "rental_start": "2/5/16", + "rental_end": "2/15/17" + }, + "RNT175": { + "product_code": "PRD48", + "units_rented": 9, + "price_per_day": 39, + "rental_start": "5/16/18", + "rental_end": "3/15/18" + }, + "RNT176": { + "product_code": "PRD10", + "units_rented": 10, + "price_per_day": 12, + "rental_start": "2/25/17", + "rental_end": "5/18/17" + }, + "RNT177": { + "product_code": "PRD27", + "units_rented": 5, + "price_per_day": 32, + "rental_start": "6/6/16", + "rental_end": "9/15/17" + }, + "RNT178": { + "product_code": "PRD35", + "units_rented": 5, + "price_per_day": 40, + "rental_start": "8/1/18", + "rental_end": "4/7/18" + }, + "RNT179": { + "product_code": "PRD16", + "units_rented": 8, + "price_per_day": 6, + "rental_start": "8/24/18", + "rental_end": "8/14/18" + }, + "RNT180": { + "product_code": "PRD12", + "units_rented": 3, + "price_per_day": 27, + "rental_start": "12/29/18", + "rental_end": "9/8/16" + }, + "RNT181": { + "product_code": "PRD90", + "units_rented": 10, + "price_per_day": 40, + "rental_start": "9/13/16", + "rental_end": "12/22/16" + }, + "RNT182": { + "product_code": "PRD7", + "units_rented": 6, + "price_per_day": 23, + "rental_start": "2/8/18", + "rental_end": "9/21/18" + }, + "RNT183": { + "product_code": "PRD10", + "units_rented": 5, + "price_per_day": 24, + "rental_start": "5/31/18", + "rental_end": "4/8/18" + }, + "RNT184": { + "product_code": "PRD66", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "3/12/18", + "rental_end": "9/28/16" + }, + "RNT185": { + "product_code": "PRD39", + "units_rented": 4, + "price_per_day": 35, + "rental_start": "12/11/16", + "rental_end": "1/12/18" + }, + "RNT186": { + "product_code": "PRD48", + "units_rented": 9, + "price_per_day": 39, + "rental_start": "12/23/17", + "rental_end": "2/20/18" + }, + "RNT187": { + "product_code": "PRD12", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "10/5/17", + "rental_end": "1/11/16" + }, + "RNT188": { + "product_code": "PRD76", + "units_rented": 7, + "price_per_day": 14, + "rental_start": "3/20/17", + "rental_end": "10/1/18" + }, + "RNT189": { + "product_code": "PRD54", + "units_rented": 8, + "price_per_day": 18, + "rental_start": "11/20/16", + "rental_end": "8/17/16" + }, + "RNT190": { + "product_code": "PRD45", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "1/29/17", + "rental_end": "10/11/17" + }, + "RNT191": { + "product_code": "PRD69", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "6/1/16", + "rental_end": "11/6/18" + }, + "RNT192": { + "product_code": "PRD59", + "units_rented": 10, + "price_per_day": 31, + "rental_start": "5/10/17", + "rental_end": "4/30/17" + }, + "RNT193": { + "product_code": "PRD50", + "units_rented": 6, + "price_per_day": 36, + "rental_start": "10/19/16", + "rental_end": "2/17/17" + }, + "RNT194": { + "product_code": "PRD49", + "units_rented": 1, + "price_per_day": 35, + "rental_start": "8/14/17", + "rental_end": "2/22/18" + }, + "RNT195": { + "product_code": "PRD93", + "units_rented": 2, + "price_per_day": 17, + "rental_start": "5/4/18", + "rental_end": "1/6/16" + }, + "RNT196": { + "product_code": "PRD92", + "units_rented": 8, + "price_per_day": 19, + "rental_start": "10/28/18", + "rental_end": "5/4/16" + }, + "RNT197": { + "product_code": "PRD69", + "units_rented": 4, + "price_per_day": 33, + "rental_start": "3/2/18", + "rental_end": "11/14/17" + }, + "RNT198": { + "product_code": "PRD45", + "units_rented": 10, + "price_per_day": 20, + "rental_start": "6/1/16", + "rental_end": "12/6/17" + }, + "RNT199": { + "product_code": "PRD95", + "units_rented": 7, + "price_per_day": 23, + "rental_start": "2/22/18", + "rental_end": "5/26/18" + }, + "RNT200": { + "product_code": "PRD9", + "units_rented": 9, + "price_per_day": 39, + "rental_start": "8/6/18", + "rental_end": "8/30/18" + }, + "RNT201": { + "product_code": "PRD14", + "units_rented": 1, + "price_per_day": 17, + "rental_start": "10/12/17", + "rental_end": "9/17/16" + }, + "RNT202": { + "product_code": "PRD93", + "units_rented": 2, + "price_per_day": 34, + "rental_start": "11/4/18", + "rental_end": "2/7/16" + }, + "RNT203": { + "product_code": "PRD85", + "units_rented": 4, + "price_per_day": 25, + "rental_start": "8/21/17", + "rental_end": "8/27/18" + }, + "RNT204": { + "product_code": "PRD70", + "units_rented": 10, + "price_per_day": 26, + "rental_start": "4/15/17", + "rental_end": "4/3/18" + }, + "RNT205": { + "product_code": "PRD46", + "units_rented": 1, + "price_per_day": 25, + "rental_start": "12/4/16", + "rental_end": "3/28/18" + }, + "RNT206": { + "product_code": "PRD59", + "units_rented": 9, + "price_per_day": 12, + "rental_start": "2/16/18", + "rental_end": "2/19/18" + }, + "RNT207": { + "product_code": "PRD21", + "units_rented": 7, + "price_per_day": 21, + "rental_start": "3/15/18", + "rental_end": "6/3/16" + }, + "RNT208": { + "product_code": "PRD86", + "units_rented": 1, + "price_per_day": 16, + "rental_start": "2/24/16", + "rental_end": "2/18/16" + }, + "RNT209": { + "product_code": "PRD95", + "units_rented": 4, + "price_per_day": 14, + "rental_start": "9/12/16", + "rental_end": "12/15/17" + }, + "RNT210": { + "product_code": "PRD2", + "units_rented": 2, + "price_per_day": 6, + "rental_start": "7/5/17", + "rental_end": "1/2/17" + }, + "RNT211": { + "product_code": "PRD89", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "6/15/18", + "rental_end": "7/23/18" + }, + "RNT212": { + "product_code": "PRD16", + "units_rented": 3, + "price_per_day": 27, + "rental_start": "9/3/16", + "rental_end": "9/26/16" + }, + "RNT213": { + "product_code": "PRD44", + "units_rented": 10, + "price_per_day": 28, + "rental_start": "4/9/16", + "rental_end": "9/4/18" + }, + "RNT214": { + "product_code": "PRD6", + "units_rented": 6, + "price_per_day": 26, + "rental_start": "12/4/16", + "rental_end": "6/29/16" + }, + "RNT215": { + "product_code": "PRD36", + "units_rented": 9, + "price_per_day": 19, + "rental_start": "4/25/16", + "rental_end": "8/3/17" + }, + "RNT216": { + "product_code": "PRD6", + "units_rented": 2, + "price_per_day": 16, + "rental_start": "4/20/16", + "rental_end": "2/10/16" + }, + "RNT217": { + "product_code": "PRD11", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "8/18/18", + "rental_end": "8/4/16" + }, + "RNT218": { + "product_code": "PRD20", + "units_rented": 8, + "price_per_day": 40, + "rental_start": "12/11/17", + "rental_end": "12/23/16" + }, + "RNT219": { + "product_code": "PRD79", + "units_rented": 8, + "price_per_day": 30, + "rental_start": "1/24/17", + "rental_end": "12/16/17" + }, + "RNT220": { + "product_code": "PRD69", + "units_rented": 9, + "price_per_day": 11, + "rental_start": "1/1/16", + "rental_end": "2/14/17" + }, + "RNT221": { + "product_code": "PRD12", + "units_rented": 6, + "price_per_day": 40, + "rental_start": "10/26/18", + "rental_end": "7/28/16" + }, + "RNT222": { + "product_code": "PRD97", + "units_rented": 1, + "price_per_day": 23, + "rental_start": "5/5/16", + "rental_end": "2/27/17" + }, + "RNT223": { + "product_code": "PRD51", + "units_rented": 7, + "price_per_day": 27, + "rental_start": "2/3/18", + "rental_end": "4/28/16" + }, + "RNT224": { + "product_code": "PRD10", + "units_rented": 10, + "price_per_day": 34, + "rental_start": "11/5/17", + "rental_end": "10/7/16" + }, + "RNT225": { + "product_code": "PRD51", + "units_rented": 7, + "price_per_day": 25, + "rental_start": "5/15/17", + "rental_end": "12/24/16" + }, + "RNT226": { + "product_code": "PRD90", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "10/19/17", + "rental_end": "12/3/17" + }, + "RNT227": { + "product_code": "PRD32", + "units_rented": 9, + "price_per_day": 17, + "rental_start": "5/11/18", + "rental_end": "2/4/16" + }, + "RNT228": { + "product_code": "PRD61", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "1/28/18", + "rental_end": "12/9/18" + }, + "RNT229": { + "product_code": "PRD75", + "units_rented": 3, + "price_per_day": 10, + "rental_start": "2/23/17", + "rental_end": "11/3/16" + }, + "RNT230": { + "product_code": "PRD99", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "10/27/17", + "rental_end": "1/4/18" + }, + "RNT231": { + "product_code": "PRD20", + "units_rented": 2, + "price_per_day": 35, + "rental_start": "5/25/16", + "rental_end": "12/28/18" + }, + "RNT232": { + "product_code": "PRD26", + "units_rented": 10, + "price_per_day": 26, + "rental_start": "9/30/16", + "rental_end": "10/6/17" + }, + "RNT233": { + "product_code": "PRD35", + "units_rented": 7, + "price_per_day": 9, + "rental_start": "4/27/18", + "rental_end": "7/25/16" + }, + "RNT234": { + "product_code": "PRD2", + "units_rented": 10, + "price_per_day": 13, + "rental_start": "4/25/18", + "rental_end": "1/20/18" + }, + "RNT235": { + "product_code": "PRD34", + "units_rented": 6, + "price_per_day": 24, + "rental_start": "10/11/18", + "rental_end": "10/17/18" + }, + "RNT236": { + "product_code": "PRD16", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "12/17/18", + "rental_end": "3/25/16" + }, + "RNT237": { + "product_code": "PRD9", + "units_rented": 10, + "price_per_day": 12, + "rental_start": "3/25/16", + "rental_end": "12/4/17" + }, + "RNT238": { + "product_code": "PRD43", + "units_rented": 7, + "price_per_day": 5, + "rental_start": "1/1/18", + "rental_end": "8/7/17" + }, + "RNT239": { + "product_code": "PRD79", + "units_rented": 8, + "price_per_day": 20, + "rental_start": "3/26/16", + "rental_end": "4/23/16" + }, + "RNT240": { + "product_code": "PRD20", + "units_rented": 1, + "price_per_day": 14, + "rental_start": "6/17/16", + "rental_end": "12/5/16" + }, + "RNT241": { + "product_code": "PRD97", + "units_rented": 9, + "price_per_day": 28, + "rental_start": "7/2/18", + "rental_end": "12/7/17" + }, + "RNT242": { + "product_code": "PRD14", + "units_rented": 7, + "price_per_day": 9, + "rental_start": "1/31/17", + "rental_end": "2/18/16" + }, + "RNT243": { + "product_code": "PRD0", + "units_rented": 4, + "price_per_day": 13, + "rental_start": "12/8/17", + "rental_end": "10/13/16" + }, + "RNT244": { + "product_code": "PRD23", + "units_rented": 2, + "price_per_day": 12, + "rental_start": "6/25/18", + "rental_end": "9/16/16" + }, + "RNT245": { + "product_code": "PRD0", + "units_rented": 9, + "price_per_day": 39, + "rental_start": "6/11/16", + "rental_end": "9/10/18" + }, + "RNT246": { + "product_code": "PRD85", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "2/2/18", + "rental_end": "8/28/17" + }, + "RNT247": { + "product_code": "PRD33", + "units_rented": 6, + "price_per_day": 9, + "rental_start": "7/10/17", + "rental_end": "6/10/17" + }, + "RNT248": { + "product_code": "PRD79", + "units_rented": 9, + "price_per_day": 33, + "rental_start": "6/23/16", + "rental_end": "7/29/17" + }, + "RNT249": { + "product_code": "PRD6", + "units_rented": 6, + "price_per_day": 6, + "rental_start": "10/28/16", + "rental_end": "2/16/17" + }, + "RNT250": { + "product_code": "PRD83", + "units_rented": 8, + "price_per_day": 24, + "rental_start": "3/23/18", + "rental_end": "4/28/18" + }, + "RNT251": { + "product_code": "PRD58", + "units_rented": 1, + "price_per_day": 27, + "rental_start": "1/12/18", + "rental_end": "10/6/18" + }, + "RNT252": { + "product_code": "PRD5", + "units_rented": 5, + "price_per_day": 21, + "rental_start": "12/30/16", + "rental_end": "8/27/17" + }, + "RNT253": { + "product_code": "PRD10", + "units_rented": 6, + "price_per_day": 28, + "rental_start": "1/11/17", + "rental_end": "12/17/18" + }, + "RNT254": { + "product_code": "PRD13", + "units_rented": 7, + "price_per_day": 8, + "rental_start": "10/31/16", + "rental_end": "4/17/16" + }, + "RNT255": { + "product_code": "PRD10", + "units_rented": 10, + "price_per_day": 17, + "rental_start": "4/1/17", + "rental_end": "9/2/18" + }, + "RNT256": { + "product_code": "PRD60", + "units_rented": 6, + "price_per_day": 26, + "rental_start": "9/5/17", + "rental_end": "11/23/17" + }, + "RNT257": { + "product_code": "PRD0", + "units_rented": 5, + "price_per_day": 20, + "rental_start": "4/4/16", + "rental_end": "12/15/18" + }, + "RNT258": { + "product_code": "PRD70", + "units_rented": 2, + "price_per_day": 18, + "rental_start": "10/21/17", + "rental_end": "4/10/17" + }, + "RNT259": { + "product_code": "PRD86", + "units_rented": 4, + "price_per_day": 34, + "rental_start": "2/14/18", + "rental_end": "8/16/16" + }, + "RNT260": { + "product_code": "PRD17", + "units_rented": 10, + "price_per_day": 16, + "rental_start": "1/28/18", + "rental_end": "1/19/17" + }, + "RNT261": { + "product_code": "PRD82", + "units_rented": 4, + "price_per_day": 15, + "rental_start": "3/14/18", + "rental_end": "11/10/17" + }, + "RNT262": { + "product_code": "PRD59", + "units_rented": 7, + "price_per_day": 11, + "rental_start": "11/24/16", + "rental_end": "3/13/17" + }, + "RNT263": { + "product_code": "PRD90", + "units_rented": 1, + "price_per_day": 33, + "rental_start": "3/3/18", + "rental_end": "12/5/18" + }, + "RNT264": { + "product_code": "PRD50", + "units_rented": 1, + "price_per_day": 15, + "rental_start": "9/25/18", + "rental_end": "9/26/16" + }, + "RNT265": { + "product_code": "PRD15", + "units_rented": 5, + "price_per_day": 16, + "rental_start": "10/8/17", + "rental_end": "10/7/17" + }, + "RNT266": { + "product_code": "PRD35", + "units_rented": 7, + "price_per_day": 39, + "rental_start": "1/7/18", + "rental_end": "1/20/18" + }, + "RNT267": { + "product_code": "PRD44", + "units_rented": 3, + "price_per_day": 26, + "rental_start": "4/12/16", + "rental_end": "8/5/17" + }, + "RNT268": { + "product_code": "PRD27", + "units_rented": 2, + "price_per_day": 15, + "rental_start": "6/10/16", + "rental_end": "7/16/16" + }, + "RNT269": { + "product_code": "PRD5", + "units_rented": 6, + "price_per_day": 39, + "rental_start": "6/17/17", + "rental_end": "11/20/18" + }, + "RNT270": { + "product_code": "PRD19", + "units_rented": 4, + "price_per_day": 19, + "rental_start": "8/30/16", + "rental_end": "7/24/16" + }, + "RNT271": { + "product_code": "PRD33", + "units_rented": 1, + "price_per_day": 11, + "rental_start": "11/27/18", + "rental_end": "8/7/16" + }, + "RNT272": { + "product_code": "PRD57", + "units_rented": 2, + "price_per_day": 24, + "rental_start": "7/31/17", + "rental_end": "5/19/17" + }, + "RNT273": { + "product_code": "PRD96", + "units_rented": 9, + "price_per_day": 12, + "rental_start": "10/27/17", + "rental_end": "6/30/18" + }, + "RNT274": { + "product_code": "PRD3", + "units_rented": 2, + "price_per_day": 38, + "rental_start": "12/15/18", + "rental_end": "2/12/17" + }, + "RNT275": { + "product_code": "PRD17", + "units_rented": 8, + "price_per_day": 22, + "rental_start": "11/14/16", + "rental_end": "12/30/16" + }, + "RNT276": { + "product_code": "PRD84", + "units_rented": 2, + "price_per_day": 27, + "rental_start": "7/2/16", + "rental_end": "4/2/18" + }, + "RNT277": { + "product_code": "PRD28", + "units_rented": 2, + "price_per_day": 5, + "rental_start": "8/7/18", + "rental_end": "10/21/16" + }, + "RNT278": { + "product_code": "PRD64", + "units_rented": 3, + "price_per_day": 36, + "rental_start": "7/25/16", + "rental_end": "12/23/18" + }, + "RNT279": { + "product_code": "PRD14", + "units_rented": 8, + "price_per_day": 34, + "rental_start": "5/23/16", + "rental_end": "4/25/18" + }, + "RNT280": { + "product_code": "PRD14", + "units_rented": 10, + "price_per_day": 9, + "rental_start": "7/25/16", + "rental_end": "8/1/18" + }, + "RNT281": { + "product_code": "PRD29", + "units_rented": 1, + "price_per_day": 6, + "rental_start": "7/18/17", + "rental_end": "5/25/18" + }, + "RNT282": { + "product_code": "PRD28", + "units_rented": 8, + "price_per_day": 20, + "rental_start": "2/3/18", + "rental_end": "9/4/17" + }, + "RNT283": { + "product_code": "PRD85", + "units_rented": 7, + "price_per_day": 12, + "rental_start": "7/18/18", + "rental_end": "6/30/18" + }, + "RNT284": { + "product_code": "PRD40", + "units_rented": 6, + "price_per_day": 36, + "rental_start": "1/17/16", + "rental_end": "12/19/16" + }, + "RNT285": { + "product_code": "PRD19", + "units_rented": 6, + "price_per_day": 33, + "rental_start": "3/31/17", + "rental_end": "5/5/17" + }, + "RNT286": { + "product_code": "PRD1", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "4/26/16", + "rental_end": "3/27/17" + }, + "RNT287": { + "product_code": "PRD28", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "6/9/16", + "rental_end": "1/1/17" + }, + "RNT288": { + "product_code": "PRD74", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "12/31/18", + "rental_end": "9/13/18" + }, + "RNT289": { + "product_code": "PRD75", + "units_rented": 10, + "price_per_day": 27, + "rental_start": "6/11/18", + "rental_end": "7/1/18" + }, + "RNT290": { + "product_code": "PRD90", + "units_rented": 2, + "price_per_day": 26, + "rental_start": "5/17/16", + "rental_end": "5/12/16" + }, + "RNT291": { + "product_code": "PRD19", + "units_rented": 1, + "price_per_day": 14, + "rental_start": "7/26/16", + "rental_end": "10/10/18" + }, + "RNT292": { + "product_code": "PRD14", + "units_rented": 1, + "price_per_day": 29, + "rental_start": "1/13/17", + "rental_end": "3/31/17" + }, + "RNT293": { + "product_code": "PRD75", + "units_rented": 6, + "price_per_day": 8, + "rental_start": "4/6/18", + "rental_end": "12/3/18" + }, + "RNT294": { + "product_code": "PRD40", + "units_rented": 6, + "price_per_day": 16, + "rental_start": "1/14/16", + "rental_end": "11/16/18" + }, + "RNT295": { + "product_code": "PRD71", + "units_rented": 3, + "price_per_day": 35, + "rental_start": "11/10/16", + "rental_end": "4/25/16" + }, + "RNT296": { + "product_code": "PRD84", + "units_rented": 5, + "price_per_day": 24, + "rental_start": "12/8/17", + "rental_end": "5/13/16" + }, + "RNT297": { + "product_code": "PRD61", + "units_rented": 1, + "price_per_day": 5, + "rental_start": "12/29/17", + "rental_end": "9/4/18" + }, + "RNT298": { + "product_code": "PRD29", + "units_rented": 3, + "price_per_day": 20, + "rental_start": "12/11/18", + "rental_end": "7/8/18" + }, + "RNT299": { + "product_code": "PRD69", + "units_rented": 6, + "price_per_day": 39, + "rental_start": "10/13/16", + "rental_end": "10/8/16" + }, + "RNT300": { + "product_code": "PRD18", + "units_rented": 1, + "price_per_day": 27, + "rental_start": "1/27/17", + "rental_end": "6/30/16" + }, + "RNT301": { + "product_code": "PRD89", + "units_rented": 8, + "price_per_day": 15, + "rental_start": "8/10/17", + "rental_end": "1/29/16" + }, + "RNT302": { + "product_code": "PRD37", + "units_rented": 3, + "price_per_day": 6, + "rental_start": "12/2/16", + "rental_end": "2/22/16" + }, + "RNT303": { + "product_code": "PRD13", + "units_rented": 8, + "price_per_day": 30, + "rental_start": "7/2/18", + "rental_end": "5/23/17" + }, + "RNT304": { + "product_code": "PRD11", + "units_rented": 8, + "price_per_day": 20, + "rental_start": "6/29/18", + "rental_end": "12/31/17" + }, + "RNT305": { + "product_code": "PRD12", + "units_rented": 7, + "price_per_day": 19, + "rental_start": "1/10/18", + "rental_end": "4/20/16" + }, + "RNT306": { + "product_code": "PRD18", + "units_rented": 1, + "price_per_day": 40, + "rental_start": "8/6/18", + "rental_end": "1/21/17" + }, + "RNT307": { + "product_code": "PRD90", + "units_rented": 9, + "price_per_day": 10, + "rental_start": "11/4/17", + "rental_end": "6/18/18" + }, + "RNT308": { + "product_code": "PRD23", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "7/25/16", + "rental_end": "4/28/16" + }, + "RNT309": { + "product_code": "PRD14", + "units_rented": 5, + "price_per_day": 35, + "rental_start": "12/3/17", + "rental_end": "10/26/17" + }, + "RNT310": { + "product_code": "PRD29", + "units_rented": 10, + "price_per_day": 13, + "rental_start": "11/28/18", + "rental_end": "7/5/16" + }, + "RNT311": { + "product_code": "PRD45", + "units_rented": 8, + "price_per_day": 31, + "rental_start": "12/24/18", + "rental_end": "5/19/17" + }, + "RNT312": { + "product_code": "PRD98", + "units_rented": 1, + "price_per_day": 34, + "rental_start": "6/17/17", + "rental_end": "3/26/17" + }, + "RNT313": { + "product_code": "PRD75", + "units_rented": 8, + "price_per_day": 13, + "rental_start": "1/23/18", + "rental_end": "2/17/17" + }, + "RNT314": { + "product_code": "PRD71", + "units_rented": 8, + "price_per_day": 39, + "rental_start": "7/25/18", + "rental_end": "3/6/17" + }, + "RNT315": { + "product_code": "PRD86", + "units_rented": 3, + "price_per_day": 35, + "rental_start": "9/19/17", + "rental_end": "12/21/16" + }, + "RNT316": { + "product_code": "PRD92", + "units_rented": 6, + "price_per_day": 16, + "rental_start": "1/9/17", + "rental_end": "4/14/16" + }, + "RNT317": { + "product_code": "PRD41", + "units_rented": 3, + "price_per_day": 14, + "rental_start": "9/12/16", + "rental_end": "9/15/18" + }, + "RNT318": { + "product_code": "PRD95", + "units_rented": 3, + "price_per_day": 37, + "rental_start": "12/29/16", + "rental_end": "11/5/17" + }, + "RNT319": { + "product_code": "PRD96", + "units_rented": 6, + "price_per_day": 38, + "rental_start": "2/7/16", + "rental_end": "12/24/18" + }, + "RNT320": { + "product_code": "PRD90", + "units_rented": 5, + "price_per_day": 14, + "rental_start": "10/16/18", + "rental_end": "8/25/17" + }, + "RNT321": { + "product_code": "PRD65", + "units_rented": 9, + "price_per_day": 17, + "rental_start": "4/18/18", + "rental_end": "6/9/17" + }, + "RNT322": { + "product_code": "PRD29", + "units_rented": 4, + "price_per_day": 37, + "rental_start": "1/27/17", + "rental_end": "6/6/17" + }, + "RNT323": { + "product_code": "PRD82", + "units_rented": 4, + "price_per_day": 21, + "rental_start": "8/15/16", + "rental_end": "2/2/17" + }, + "RNT324": { + "product_code": "PRD18", + "units_rented": 5, + "price_per_day": 18, + "rental_start": "12/29/18", + "rental_end": "2/3/16" + }, + "RNT325": { + "product_code": "PRD42", + "units_rented": 1, + "price_per_day": 34, + "rental_start": "5/18/18", + "rental_end": "6/10/16" + }, + "RNT326": { + "product_code": "PRD28", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "1/5/16", + "rental_end": "7/18/17" + }, + "RNT327": { + "product_code": "PRD10", + "units_rented": 7, + "price_per_day": 31, + "rental_start": "4/19/16", + "rental_end": "1/10/18" + }, + "RNT328": { + "product_code": "PRD26", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "8/25/17", + "rental_end": "12/5/17" + }, + "RNT329": { + "product_code": "PRD85", + "units_rented": 9, + "price_per_day": 40, + "rental_start": "7/16/16", + "rental_end": "8/6/17" + }, + "RNT330": { + "product_code": "PRD18", + "units_rented": 3, + "price_per_day": 25, + "rental_start": "1/20/17", + "rental_end": "5/5/17" + }, + "RNT331": { + "product_code": "PRD68", + "units_rented": 2, + "price_per_day": 38, + "rental_start": "7/8/17", + "rental_end": "7/6/17" + }, + "RNT332": { + "product_code": "PRD30", + "units_rented": 5, + "price_per_day": 13, + "rental_start": "8/8/16", + "rental_end": "1/8/18" + }, + "RNT333": { + "product_code": "PRD24", + "units_rented": 2, + "price_per_day": 6, + "rental_start": "2/25/16", + "rental_end": "9/30/18" + }, + "RNT334": { + "product_code": "PRD82", + "units_rented": 5, + "price_per_day": 33, + "rental_start": "2/21/17", + "rental_end": "4/27/17" + }, + "RNT335": { + "product_code": "PRD37", + "units_rented": 3, + "price_per_day": 10, + "rental_start": "12/19/17", + "rental_end": "12/4/17" + }, + "RNT336": { + "product_code": "PRD95", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "9/3/17", + "rental_end": "12/13/16" + }, + "RNT337": { + "product_code": "PRD31", + "units_rented": 9, + "price_per_day": 25, + "rental_start": "12/16/17", + "rental_end": "3/25/17" + }, + "RNT338": { + "product_code": "PRD29", + "units_rented": 3, + "price_per_day": 29, + "rental_start": "1/23/17", + "rental_end": "11/23/17" + }, + "RNT339": { + "product_code": "PRD43", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "7/12/17", + "rental_end": "3/1/16" + }, + "RNT340": { + "product_code": "PRD81", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "1/23/16", + "rental_end": "12/9/17" + }, + "RNT341": { + "product_code": "PRD11", + "units_rented": 3, + "price_per_day": 31, + "rental_start": "9/23/16", + "rental_end": "8/30/17" + }, + "RNT342": { + "product_code": "PRD91", + "units_rented": 5, + "price_per_day": 15, + "rental_start": "12/23/16", + "rental_end": "6/21/18" + }, + "RNT343": { + "product_code": "PRD73", + "units_rented": 3, + "price_per_day": 32, + "rental_start": "2/15/17", + "rental_end": "1/17/17" + }, + "RNT344": { + "product_code": "PRD61", + "units_rented": 1, + "price_per_day": 26, + "rental_start": "8/3/18", + "rental_end": "8/27/18" + }, + "RNT345": { + "product_code": "PRD44", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "5/15/17", + "rental_end": "10/22/16" + }, + "RNT346": { + "product_code": "PRD59", + "units_rented": 7, + "price_per_day": 27, + "rental_start": "9/17/18", + "rental_end": "3/21/17" + }, + "RNT347": { + "product_code": "PRD32", + "units_rented": 6, + "price_per_day": 18, + "rental_start": "4/17/18", + "rental_end": "9/21/17" + }, + "RNT348": { + "product_code": "PRD37", + "units_rented": 4, + "price_per_day": 34, + "rental_start": "2/19/16", + "rental_end": "5/28/16" + }, + "RNT349": { + "product_code": "PRD0", + "units_rented": 6, + "price_per_day": 15, + "rental_start": "10/11/16", + "rental_end": "4/5/18" + }, + "RNT350": { + "product_code": "PRD22", + "units_rented": 1, + "price_per_day": 28, + "rental_start": "11/12/16", + "rental_end": "3/14/17" + }, + "RNT351": { + "product_code": "PRD66", + "units_rented": 2, + "price_per_day": 34, + "rental_start": "1/7/16", + "rental_end": "6/3/17" + }, + "RNT352": { + "product_code": "PRD92", + "units_rented": 8, + "price_per_day": 33, + "rental_start": "7/16/18", + "rental_end": "1/15/17" + }, + "RNT353": { + "product_code": "PRD38", + "units_rented": 4, + "price_per_day": 38, + "rental_start": "10/4/17", + "rental_end": "12/13/16" + }, + "RNT354": { + "product_code": "PRD36", + "units_rented": 10, + "price_per_day": 12, + "rental_start": "9/17/16", + "rental_end": "10/17/17" + }, + "RNT355": { + "product_code": "PRD29", + "units_rented": 3, + "price_per_day": 12, + "rental_start": "9/13/18", + "rental_end": "7/30/18" + }, + "RNT356": { + "product_code": "PRD59", + "units_rented": 9, + "price_per_day": 7, + "rental_start": "1/16/18", + "rental_end": "8/21/17" + }, + "RNT357": { + "product_code": "PRD28", + "units_rented": 10, + "price_per_day": 33, + "rental_start": "3/16/18", + "rental_end": "8/29/18" + }, + "RNT358": { + "product_code": "PRD46", + "units_rented": 9, + "price_per_day": 7, + "rental_start": "9/15/16", + "rental_end": "9/19/17" + }, + "RNT359": { + "product_code": "PRD30", + "units_rented": 5, + "price_per_day": 32, + "rental_start": "8/20/16", + "rental_end": "8/13/17" + }, + "RNT360": { + "product_code": "PRD96", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "1/29/16", + "rental_end": "3/3/17" + }, + "RNT361": { + "product_code": "PRD31", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "1/29/18", + "rental_end": "3/5/16" + }, + "RNT362": { + "product_code": "PRD99", + "units_rented": 2, + "price_per_day": 19, + "rental_start": "3/18/17", + "rental_end": "10/3/18" + }, + "RNT363": { + "product_code": "PRD40", + "units_rented": 3, + "price_per_day": 19, + "rental_start": "6/12/18", + "rental_end": "5/21/18" + }, + "RNT364": { + "product_code": "PRD51", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "6/24/18", + "rental_end": "5/14/18" + }, + "RNT365": { + "product_code": "PRD76", + "units_rented": 2, + "price_per_day": 34, + "rental_start": "9/29/16", + "rental_end": "11/18/17" + }, + "RNT366": { + "product_code": "PRD73", + "units_rented": 1, + "price_per_day": 34, + "rental_start": "7/24/18", + "rental_end": "10/8/17" + }, + "RNT367": { + "product_code": "PRD71", + "units_rented": 6, + "price_per_day": 37, + "rental_start": "8/12/17", + "rental_end": "11/26/17" + }, + "RNT368": { + "product_code": "PRD31", + "units_rented": 9, + "price_per_day": 27, + "rental_start": "3/9/17", + "rental_end": "6/18/17" + }, + "RNT369": { + "product_code": "PRD2", + "units_rented": 2, + "price_per_day": 20, + "rental_start": "6/1/18", + "rental_end": "9/11/18" + }, + "RNT370": { + "product_code": "PRD3", + "units_rented": 10, + "price_per_day": 28, + "rental_start": "7/23/16", + "rental_end": "2/23/18" + }, + "RNT371": { + "product_code": "PRD2", + "units_rented": 2, + "price_per_day": 30, + "rental_start": "11/20/18", + "rental_end": "6/10/17" + }, + "RNT372": { + "product_code": "PRD40", + "units_rented": 6, + "price_per_day": 26, + "rental_start": "9/14/17", + "rental_end": "9/17/16" + }, + "RNT373": { + "product_code": "PRD30", + "units_rented": 2, + "price_per_day": 21, + "rental_start": "9/17/17", + "rental_end": "12/24/17" + }, + "RNT374": { + "product_code": "PRD85", + "units_rented": 6, + "price_per_day": 9, + "rental_start": "6/28/18", + "rental_end": "1/15/18" + }, + "RNT375": { + "product_code": "PRD1", + "units_rented": 5, + "price_per_day": 8, + "rental_start": "5/18/17", + "rental_end": "7/17/17" + }, + "RNT376": { + "product_code": "PRD75", + "units_rented": 10, + "price_per_day": 23, + "rental_start": "11/20/17", + "rental_end": "4/20/17" + }, + "RNT377": { + "product_code": "PRD76", + "units_rented": 1, + "price_per_day": 21, + "rental_start": "4/9/16", + "rental_end": "3/10/18" + }, + "RNT378": { + "product_code": "PRD68", + "units_rented": 5, + "price_per_day": 28, + "rental_start": "6/24/16", + "rental_end": "12/19/17" + }, + "RNT379": { + "product_code": "PRD44", + "units_rented": 10, + "price_per_day": 17, + "rental_start": "9/11/18", + "rental_end": "11/21/16" + }, + "RNT380": { + "product_code": "PRD12", + "units_rented": 10, + "price_per_day": 24, + "rental_start": "3/6/16", + "rental_end": "5/23/17" + }, + "RNT381": { + "product_code": "PRD30", + "units_rented": 3, + "price_per_day": 19, + "rental_start": "5/28/18", + "rental_end": "12/26/16" + }, + "RNT382": { + "product_code": "PRD95", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "5/19/17", + "rental_end": "12/8/18" + }, + "RNT383": { + "product_code": "PRD58", + "units_rented": 9, + "price_per_day": 9, + "rental_start": "5/28/17", + "rental_end": "5/6/17" + }, + "RNT384": { + "product_code": "PRD73", + "units_rented": 1, + "price_per_day": 34, + "rental_start": "11/28/17", + "rental_end": "5/29/17" + }, + "RNT385": { + "product_code": "PRD29", + "units_rented": 9, + "price_per_day": 18, + "rental_start": "12/17/16", + "rental_end": "8/30/18" + }, + "RNT386": { + "product_code": "PRD99", + "units_rented": 4, + "price_per_day": 38, + "rental_start": "1/5/17", + "rental_end": "6/9/16" + }, + "RNT387": { + "product_code": "PRD38", + "units_rented": 3, + "price_per_day": 40, + "rental_start": "12/28/18", + "rental_end": "7/18/16" + }, + "RNT388": { + "product_code": "PRD38", + "units_rented": 9, + "price_per_day": 5, + "rental_start": "7/21/18", + "rental_end": "12/11/16" + }, + "RNT389": { + "product_code": "PRD71", + "units_rented": 10, + "price_per_day": 27, + "rental_start": "4/6/17", + "rental_end": "8/25/18" + }, + "RNT390": { + "product_code": "PRD81", + "units_rented": 7, + "price_per_day": 5, + "rental_start": "12/16/16", + "rental_end": "10/19/17" + }, + "RNT391": { + "product_code": "PRD2", + "units_rented": 1, + "price_per_day": 27, + "rental_start": "8/18/17", + "rental_end": "8/6/17" + }, + "RNT392": { + "product_code": "PRD64", + "units_rented": 9, + "price_per_day": 21, + "rental_start": "7/17/18", + "rental_end": "4/4/18" + }, + "RNT393": { + "product_code": "PRD49", + "units_rented": 8, + "price_per_day": 15, + "rental_start": "3/10/16", + "rental_end": "4/6/17" + }, + "RNT394": { + "product_code": "PRD11", + "units_rented": 3, + "price_per_day": 27, + "rental_start": "2/15/18", + "rental_end": "1/10/17" + }, + "RNT395": { + "product_code": "PRD22", + "units_rented": 5, + "price_per_day": 6, + "rental_start": "3/31/18", + "rental_end": "12/29/17" + }, + "RNT396": { + "product_code": "PRD10", + "units_rented": 8, + "price_per_day": 5, + "rental_start": "8/9/16", + "rental_end": "5/16/18" + }, + "RNT397": { + "product_code": "PRD81", + "units_rented": 4, + "price_per_day": 18, + "rental_start": "6/22/17", + "rental_end": "5/11/16" + }, + "RNT398": { + "product_code": "PRD46", + "units_rented": 9, + "price_per_day": 16, + "rental_start": "5/27/18", + "rental_end": "6/5/18" + }, + "RNT399": { + "product_code": "PRD10", + "units_rented": 5, + "price_per_day": 35, + "rental_start": "1/21/16", + "rental_end": "10/11/17" + }, + "RNT400": { + "product_code": "PRD59", + "units_rented": 5, + "price_per_day": 27, + "rental_start": "10/12/18", + "rental_end": "3/6/17" + }, + "RNT401": { + "product_code": "PRD86", + "units_rented": 1, + "price_per_day": 36, + "rental_start": "1/1/18", + "rental_end": "5/10/18" + }, + "RNT402": { + "product_code": "PRD69", + "units_rented": 9, + "price_per_day": 24, + "rental_start": "3/8/17", + "rental_end": "12/3/17" + }, + "RNT403": { + "product_code": "PRD59", + "units_rented": 2, + "price_per_day": 6, + "rental_start": "8/16/16", + "rental_end": "10/7/17" + }, + "RNT404": { + "product_code": "PRD95", + "units_rented": 7, + "price_per_day": 40, + "rental_start": "9/1/16", + "rental_end": "11/23/17" + }, + "RNT405": { + "product_code": "PRD48", + "units_rented": 3, + "price_per_day": 18, + "rental_start": "10/9/18", + "rental_end": "4/17/17" + }, + "RNT406": { + "product_code": "PRD49", + "units_rented": 5, + "price_per_day": 13, + "rental_start": "3/2/17", + "rental_end": "1/5/18" + }, + "RNT407": { + "product_code": "PRD75", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "8/7/16", + "rental_end": "3/18/17" + }, + "RNT408": { + "product_code": "PRD42", + "units_rented": 2, + "price_per_day": 37, + "rental_start": "2/1/17", + "rental_end": "1/2/17" + }, + "RNT409": { + "product_code": "PRD12", + "units_rented": 10, + "price_per_day": 24, + "rental_start": "8/16/17", + "rental_end": "11/18/16" + }, + "RNT410": { + "product_code": "PRD56", + "units_rented": 10, + "price_per_day": 14, + "rental_start": "8/8/18", + "rental_end": "9/7/18" + }, + "RNT411": { + "product_code": "PRD99", + "units_rented": 3, + "price_per_day": 16, + "rental_start": "10/7/16", + "rental_end": "6/2/18" + }, + "RNT412": { + "product_code": "PRD58", + "units_rented": 3, + "price_per_day": 33, + "rental_start": "6/30/18", + "rental_end": "9/16/17" + }, + "RNT413": { + "product_code": "PRD6", + "units_rented": 2, + "price_per_day": 5, + "rental_start": "9/22/18", + "rental_end": "10/1/17" + }, + "RNT414": { + "product_code": "PRD65", + "units_rented": 8, + "price_per_day": 38, + "rental_start": "8/5/17", + "rental_end": "11/4/16" + }, + "RNT415": { + "product_code": "PRD26", + "units_rented": 1, + "price_per_day": 9, + "rental_start": "4/12/16", + "rental_end": "9/13/17" + }, + "RNT416": { + "product_code": "PRD71", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "10/26/17", + "rental_end": "2/18/17" + }, + "RNT417": { + "product_code": "PRD14", + "units_rented": 10, + "price_per_day": 37, + "rental_start": "5/4/16", + "rental_end": "9/22/16" + }, + "RNT418": { + "product_code": "PRD31", + "units_rented": 6, + "price_per_day": 22, + "rental_start": "9/29/16", + "rental_end": "6/30/17" + }, + "RNT419": { + "product_code": "PRD12", + "units_rented": 9, + "price_per_day": 10, + "rental_start": "2/3/16", + "rental_end": "9/2/18" + }, + "RNT420": { + "product_code": "PRD49", + "units_rented": 7, + "price_per_day": 20, + "rental_start": "8/22/16", + "rental_end": "11/27/18" + }, + "RNT421": { + "product_code": "PRD92", + "units_rented": 9, + "price_per_day": 9, + "rental_start": "12/6/17", + "rental_end": "4/14/16" + }, + "RNT422": { + "product_code": "PRD14", + "units_rented": 4, + "price_per_day": 21, + "rental_start": "12/24/16", + "rental_end": "7/18/16" + }, + "RNT423": { + "product_code": "PRD45", + "units_rented": 6, + "price_per_day": 35, + "rental_start": "10/17/16", + "rental_end": "1/25/16" + }, + "RNT424": { + "product_code": "PRD5", + "units_rented": 8, + "price_per_day": 22, + "rental_start": "9/27/18", + "rental_end": "4/27/16" + }, + "RNT425": { + "product_code": "PRD26", + "units_rented": 5, + "price_per_day": 35, + "rental_start": "1/30/17", + "rental_end": "6/23/18" + }, + "RNT426": { + "product_code": "PRD33", + "units_rented": 7, + "price_per_day": 23, + "rental_start": "3/6/16", + "rental_end": "4/26/17" + }, + "RNT427": { + "product_code": "PRD59", + "units_rented": 9, + "price_per_day": 11, + "rental_start": "5/5/18", + "rental_end": "1/9/17" + }, + "RNT428": { + "product_code": "PRD86", + "units_rented": 7, + "price_per_day": 15, + "rental_start": "11/11/16", + "rental_end": "6/11/16" + }, + "RNT429": { + "product_code": "PRD9", + "units_rented": 10, + "price_per_day": 30, + "rental_start": "2/13/16", + "rental_end": "9/4/16" + }, + "RNT430": { + "product_code": "PRD57", + "units_rented": 2, + "price_per_day": 15, + "rental_start": "5/3/18", + "rental_end": "4/11/18" + }, + "RNT431": { + "product_code": "PRD90", + "units_rented": 6, + "price_per_day": 9, + "rental_start": "3/30/16", + "rental_end": "7/23/18" + }, + "RNT432": { + "product_code": "PRD12", + "units_rented": 3, + "price_per_day": 19, + "rental_start": "12/24/17", + "rental_end": "12/27/18" + }, + "RNT433": { + "product_code": "PRD31", + "units_rented": 8, + "price_per_day": 25, + "rental_start": "1/31/16", + "rental_end": "11/6/18" + }, + "RNT434": { + "product_code": "PRD18", + "units_rented": 10, + "price_per_day": 29, + "rental_start": "8/18/17", + "rental_end": "11/3/18" + }, + "RNT435": { + "product_code": "PRD70", + "units_rented": 1, + "price_per_day": 32, + "rental_start": "11/22/16", + "rental_end": "1/24/16" + }, + "RNT436": { + "product_code": "PRD37", + "units_rented": 4, + "price_per_day": 10, + "rental_start": "4/17/18", + "rental_end": "5/7/17" + }, + "RNT437": { + "product_code": "PRD39", + "units_rented": 5, + "price_per_day": 32, + "rental_start": "8/31/16", + "rental_end": "9/17/17" + }, + "RNT438": { + "product_code": "PRD10", + "units_rented": 10, + "price_per_day": 8, + "rental_start": "4/24/16", + "rental_end": "6/29/16" + }, + "RNT439": { + "product_code": "PRD76", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "4/30/18", + "rental_end": "7/24/18" + }, + "RNT440": { + "product_code": "PRD43", + "units_rented": 1, + "price_per_day": 36, + "rental_start": "11/24/18", + "rental_end": "12/3/16" + }, + "RNT441": { + "product_code": "PRD33", + "units_rented": 4, + "price_per_day": 12, + "rental_start": "6/1/16", + "rental_end": "5/1/18" + }, + "RNT442": { + "product_code": "PRD68", + "units_rented": 8, + "price_per_day": 13, + "rental_start": "2/6/17", + "rental_end": "8/21/18" + }, + "RNT443": { + "product_code": "PRD82", + "units_rented": 9, + "price_per_day": 27, + "rental_start": "8/7/18", + "rental_end": "2/18/16" + }, + "RNT444": { + "product_code": "PRD0", + "units_rented": 1, + "price_per_day": 40, + "rental_start": "6/16/17", + "rental_end": "12/8/17" + }, + "RNT445": { + "product_code": "PRD87", + "units_rented": 6, + "price_per_day": 16, + "rental_start": "2/22/18", + "rental_end": "10/24/17" + }, + "RNT446": { + "product_code": "PRD55", + "units_rented": 4, + "price_per_day": 18, + "rental_start": "6/30/18", + "rental_end": "6/26/16" + }, + "RNT447": { + "product_code": "PRD67", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "11/14/17", + "rental_end": "7/7/17" + }, + "RNT448": { + "product_code": "PRD33", + "units_rented": 7, + "price_per_day": 29, + "rental_start": "6/20/17", + "rental_end": "12/25/17" + }, + "RNT449": { + "product_code": "PRD89", + "units_rented": 6, + "price_per_day": 37, + "rental_start": "10/17/18", + "rental_end": "7/30/17" + }, + "RNT450": { + "product_code": "PRD40", + "units_rented": 8, + "price_per_day": 22, + "rental_start": "12/31/16", + "rental_end": "12/25/17" + }, + "RNT451": { + "product_code": "PRD3", + "units_rented": 2, + "price_per_day": 6, + "rental_start": "3/23/17", + "rental_end": "10/16/16" + }, + "RNT452": { + "product_code": "PRD57", + "units_rented": 7, + "price_per_day": 18, + "rental_start": "2/6/17", + "rental_end": "11/17/18" + }, + "RNT453": { + "product_code": "PRD52", + "units_rented": 1, + "price_per_day": 34, + "rental_start": "10/10/18", + "rental_end": "7/23/16" + }, + "RNT454": { + "product_code": "PRD46", + "units_rented": 2, + "price_per_day": 5, + "rental_start": "9/28/18", + "rental_end": "8/25/18" + }, + "RNT455": { + "product_code": "PRD73", + "units_rented": 7, + "price_per_day": 7, + "rental_start": "11/16/16", + "rental_end": "5/3/17" + }, + "RNT456": { + "product_code": "PRD24", + "units_rented": 6, + "price_per_day": 19, + "rental_start": "2/16/16", + "rental_end": "4/23/16" + }, + "RNT457": { + "product_code": "PRD56", + "units_rented": 5, + "price_per_day": 31, + "rental_start": "8/6/18", + "rental_end": "11/25/16" + }, + "RNT458": { + "product_code": "PRD70", + "units_rented": 3, + "price_per_day": 7, + "rental_start": "9/24/17", + "rental_end": "2/26/18" + }, + "RNT459": { + "product_code": "PRD92", + "units_rented": 8, + "price_per_day": 35, + "rental_start": "5/23/16", + "rental_end": "2/25/17" + }, + "RNT460": { + "product_code": "PRD23", + "units_rented": 5, + "price_per_day": 29, + "rental_start": "11/17/16", + "rental_end": "3/15/18" + }, + "RNT461": { + "product_code": "PRD80", + "units_rented": 2, + "price_per_day": 11, + "rental_start": "7/21/18", + "rental_end": "6/6/16" + }, + "RNT462": { + "product_code": "PRD82", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "6/9/18", + "rental_end": "5/2/18" + }, + "RNT463": { + "product_code": "PRD6", + "units_rented": 5, + "price_per_day": 39, + "rental_start": "11/18/18", + "rental_end": "3/14/18" + }, + "RNT464": { + "product_code": "PRD80", + "units_rented": 2, + "price_per_day": 6, + "rental_start": "3/31/18", + "rental_end": "7/23/18" + }, + "RNT465": { + "product_code": "PRD81", + "units_rented": 3, + "price_per_day": 37, + "rental_start": "4/28/18", + "rental_end": "3/7/17" + }, + "RNT466": { + "product_code": "PRD93", + "units_rented": 3, + "price_per_day": 7, + "rental_start": "1/14/17", + "rental_end": "8/20/18" + }, + "RNT467": { + "product_code": "PRD65", + "units_rented": 8, + "price_per_day": 28, + "rental_start": "5/18/18", + "rental_end": "5/23/16" + }, + "RNT468": { + "product_code": "PRD90", + "units_rented": 5, + "price_per_day": 6, + "rental_start": "5/12/16", + "rental_end": "7/19/16" + }, + "RNT469": { + "product_code": "PRD49", + "units_rented": 5, + "price_per_day": 10, + "rental_start": "12/27/16", + "rental_end": "11/21/18" + }, + "RNT470": { + "product_code": "PRD74", + "units_rented": 2, + "price_per_day": 23, + "rental_start": "3/4/18", + "rental_end": "7/1/18" + }, + "RNT471": { + "product_code": "PRD52", + "units_rented": 5, + "price_per_day": 7, + "rental_start": "11/25/16", + "rental_end": "11/22/18" + }, + "RNT472": { + "product_code": "PRD44", + "units_rented": 9, + "price_per_day": 36, + "rental_start": "4/25/17", + "rental_end": "3/5/17" + }, + "RNT473": { + "product_code": "PRD22", + "units_rented": 8, + "price_per_day": 30, + "rental_start": "1/25/17", + "rental_end": "12/3/18" + }, + "RNT474": { + "product_code": "PRD81", + "units_rented": 5, + "price_per_day": 35, + "rental_start": "5/23/17", + "rental_end": "6/4/17" + }, + "RNT475": { + "product_code": "PRD31", + "units_rented": 10, + "price_per_day": 6, + "rental_start": "8/15/17", + "rental_end": "7/29/18" + }, + "RNT476": { + "product_code": "PRD40", + "units_rented": 4, + "price_per_day": 36, + "rental_start": "7/28/18", + "rental_end": "11/26/16" + }, + "RNT477": { + "product_code": "PRD15", + "units_rented": 9, + "price_per_day": 5, + "rental_start": "8/24/16", + "rental_end": "1/23/18" + }, + "RNT478": { + "product_code": "PRD39", + "units_rented": 3, + "price_per_day": 36, + "rental_start": "1/12/16", + "rental_end": "3/29/16" + }, + "RNT479": { + "product_code": "PRD59", + "units_rented": 10, + "price_per_day": 22, + "rental_start": "9/13/16", + "rental_end": "9/28/16" + }, + "RNT480": { + "product_code": "PRD42", + "units_rented": 3, + "price_per_day": 8, + "rental_start": "8/2/18", + "rental_end": "4/8/17" + }, + "RNT481": { + "product_code": "PRD76", + "units_rented": 8, + "price_per_day": 21, + "rental_start": "5/16/17", + "rental_end": "9/4/17" + }, + "RNT482": { + "product_code": "PRD96", + "units_rented": 7, + "price_per_day": 13, + "rental_start": "1/25/16", + "rental_end": "1/24/17" + }, + "RNT483": { + "product_code": "PRD63", + "units_rented": 3, + "price_per_day": 23, + "rental_start": "1/13/17", + "rental_end": "3/19/18" + }, + "RNT484": { + "product_code": "PRD40", + "units_rented": 6, + "price_per_day": 14, + "rental_start": "6/23/16", + "rental_end": "9/7/17" + }, + "RNT485": { + "product_code": "PRD56", + "units_rented": 7, + "price_per_day": 38, + "rental_start": "3/26/18", + "rental_end": "1/29/17" + }, + "RNT486": { + "product_code": "PRD20", + "units_rented": 1, + "price_per_day": 6, + "rental_start": "10/26/17", + "rental_end": "10/9/18" + }, + "RNT487": { + "product_code": "PRD93", + "units_rented": 5, + "price_per_day": 36, + "rental_start": "3/12/17", + "rental_end": "4/28/16" + }, + "RNT488": { + "product_code": "PRD66", + "units_rented": 3, + "price_per_day": 23, + "rental_start": "3/8/16", + "rental_end": "2/15/18" + }, + "RNT489": { + "product_code": "PRD69", + "units_rented": 6, + "price_per_day": 19, + "rental_start": "8/21/18", + "rental_end": "5/9/18" + }, + "RNT490": { + "product_code": "PRD58", + "units_rented": 5, + "price_per_day": 19, + "rental_start": "9/23/17", + "rental_end": "8/17/17" + }, + "RNT491": { + "product_code": "PRD14", + "units_rented": 10, + "price_per_day": 15, + "rental_start": "6/2/18", + "rental_end": "2/3/17" + }, + "RNT492": { + "product_code": "PRD26", + "units_rented": 6, + "price_per_day": 11, + "rental_start": "1/22/17", + "rental_end": "10/10/17" + }, + "RNT493": { + "product_code": "PRD95", + "units_rented": 6, + "price_per_day": 12, + "rental_start": "8/23/18", + "rental_end": "10/10/16" + }, + "RNT494": { + "product_code": "PRD88", + "units_rented": 7, + "price_per_day": 23, + "rental_start": "7/31/16", + "rental_end": "12/29/16" + }, + "RNT495": { + "product_code": "PRD23", + "units_rented": 10, + "price_per_day": 7, + "rental_start": "6/22/17", + "rental_end": "7/31/16" + }, + "RNT496": { + "product_code": "PRD8", + "units_rented": 7, + "price_per_day": 26, + "rental_start": "11/28/17", + "rental_end": "12/5/16" + }, + "RNT497": { + "product_code": "PRD12", + "units_rented": 4, + "price_per_day": 17, + "rental_start": "6/17/18", + "rental_end": "4/20/17" + }, + "RNT498": { + "product_code": "PRD95", + "units_rented": 6, + "price_per_day": 14, + "rental_start": "5/1/16", + "rental_end": "4/30/17" + }, + "RNT499": { + "product_code": "PRD64", + "units_rented": 10, + "price_per_day": 23, + "rental_start": "8/18/17", + "rental_end": "4/20/18" + }, + "RNT500": { + "product_code": "PRD88", + "units_rented": 5, + "price_per_day": 27, + "rental_start": "3/16/16", + "rental_end": "6/5/16" + }, + "RNT501": { + "product_code": "PRD51", + "units_rented": 2, + "price_per_day": 27, + "rental_start": "10/30/16", + "rental_end": "7/4/16" + }, + "RNT502": { + "product_code": "PRD97", + "units_rented": 9, + "price_per_day": 15, + "rental_start": "2/26/17", + "rental_end": "7/2/18" + }, + "RNT503": { + "product_code": "PRD37", + "units_rented": 3, + "price_per_day": 39, + "rental_start": "3/15/17", + "rental_end": "11/22/16" + }, + "RNT504": { + "product_code": "PRD88", + "units_rented": 2, + "price_per_day": 22, + "rental_start": "12/22/16", + "rental_end": "3/7/18" + }, + "RNT505": { + "product_code": "PRD28", + "units_rented": 6, + "price_per_day": 20, + "rental_start": "5/18/16", + "rental_end": "10/4/16" + }, + "RNT506": { + "product_code": "PRD97", + "units_rented": 10, + "price_per_day": 36, + "rental_start": "1/25/18", + "rental_end": "11/19/18" + }, + "RNT507": { + "product_code": "PRD1", + "units_rented": 4, + "price_per_day": 6, + "rental_start": "6/20/18", + "rental_end": "6/1/17" + }, + "RNT508": { + "product_code": "PRD53", + "units_rented": 8, + "price_per_day": 31, + "rental_start": "5/31/17", + "rental_end": "3/21/16" + }, + "RNT509": { + "product_code": "PRD78", + "units_rented": 6, + "price_per_day": 12, + "rental_start": "12/18/18", + "rental_end": "3/17/18" + }, + "RNT510": { + "product_code": "PRD74", + "units_rented": 5, + "price_per_day": 17, + "rental_start": "7/14/16", + "rental_end": "7/29/16" + }, + "RNT511": { + "product_code": "PRD23", + "units_rented": 5, + "price_per_day": 23, + "rental_start": "3/27/18", + "rental_end": "12/27/18" + }, + "RNT512": { + "product_code": "PRD29", + "units_rented": 4, + "price_per_day": 8, + "rental_start": "11/15/17", + "rental_end": "11/3/17" + }, + "RNT513": { + "product_code": "PRD2", + "units_rented": 6, + "price_per_day": 25, + "rental_start": "12/22/18", + "rental_end": "7/6/18" + }, + "RNT514": { + "product_code": "PRD23", + "units_rented": 9, + "price_per_day": 34, + "rental_start": "8/18/18", + "rental_end": "9/25/17" + }, + "RNT515": { + "product_code": "PRD24", + "units_rented": 8, + "price_per_day": 18, + "rental_start": "4/22/18", + "rental_end": "9/18/17" + }, + "RNT516": { + "product_code": "PRD91", + "units_rented": 3, + "price_per_day": 28, + "rental_start": "3/15/18", + "rental_end": "4/15/17" + }, + "RNT517": { + "product_code": "PRD74", + "units_rented": 5, + "price_per_day": 14, + "rental_start": "8/17/18", + "rental_end": "12/20/16" + }, + "RNT518": { + "product_code": "PRD41", + "units_rented": 2, + "price_per_day": 25, + "rental_start": "6/10/18", + "rental_end": "9/29/16" + }, + "RNT519": { + "product_code": "PRD10", + "units_rented": 5, + "price_per_day": 7, + "rental_start": "8/27/17", + "rental_end": "8/28/17" + }, + "RNT520": { + "product_code": "PRD96", + "units_rented": 6, + "price_per_day": 18, + "rental_start": "8/15/17", + "rental_end": "4/10/17" + }, + "RNT521": { + "product_code": "PRD98", + "units_rented": 8, + "price_per_day": 23, + "rental_start": "2/5/17", + "rental_end": "9/27/17" + }, + "RNT522": { + "product_code": "PRD85", + "units_rented": 8, + "price_per_day": 15, + "rental_start": "5/10/18", + "rental_end": "11/22/17" + }, + "RNT523": { + "product_code": "PRD53", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "1/23/16", + "rental_end": "4/2/16" + }, + "RNT524": { + "product_code": "PRD63", + "units_rented": 1, + "price_per_day": 37, + "rental_start": "7/29/18", + "rental_end": "3/22/18" + }, + "RNT525": { + "product_code": "PRD86", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "2/18/18", + "rental_end": "10/26/17" + }, + "RNT526": { + "product_code": "PRD2", + "units_rented": 3, + "price_per_day": 37, + "rental_start": "4/24/16", + "rental_end": "2/4/18" + }, + "RNT527": { + "product_code": "PRD99", + "units_rented": 1, + "price_per_day": 10, + "rental_start": "4/28/16", + "rental_end": "1/12/18" + }, + "RNT528": { + "product_code": "PRD59", + "units_rented": 4, + "price_per_day": 28, + "rental_start": "5/30/18", + "rental_end": "2/6/16" + }, + "RNT529": { + "product_code": "PRD96", + "units_rented": 9, + "price_per_day": 40, + "rental_start": "9/12/16", + "rental_end": "12/3/16" + }, + "RNT530": { + "product_code": "PRD10", + "units_rented": 6, + "price_per_day": 38, + "rental_start": "3/11/16", + "rental_end": "7/13/17" + }, + "RNT531": { + "product_code": "PRD5", + "units_rented": 4, + "price_per_day": 19, + "rental_start": "10/5/17", + "rental_end": "11/26/18" + }, + "RNT532": { + "product_code": "PRD81", + "units_rented": 10, + "price_per_day": 34, + "rental_start": "12/7/18", + "rental_end": "10/30/17" + }, + "RNT533": { + "product_code": "PRD66", + "units_rented": 1, + "price_per_day": 14, + "rental_start": "3/29/18", + "rental_end": "12/28/16" + }, + "RNT534": { + "product_code": "PRD30", + "units_rented": 5, + "price_per_day": 11, + "rental_start": "6/9/16", + "rental_end": "6/24/17" + }, + "RNT535": { + "product_code": "PRD79", + "units_rented": 7, + "price_per_day": 26, + "rental_start": "6/5/18", + "rental_end": "11/22/16" + }, + "RNT536": { + "product_code": "PRD94", + "units_rented": 6, + "price_per_day": 39, + "rental_start": "12/29/18", + "rental_end": "7/3/18" + }, + "RNT537": { + "product_code": "PRD71", + "units_rented": 1, + "price_per_day": 36, + "rental_start": "6/30/17", + "rental_end": "8/29/16" + }, + "RNT538": { + "product_code": "PRD5", + "units_rented": 10, + "price_per_day": 34, + "rental_start": "11/24/16", + "rental_end": "2/22/16" + }, + "RNT539": { + "product_code": "PRD74", + "units_rented": 8, + "price_per_day": 23, + "rental_start": "7/28/17", + "rental_end": "7/3/16" + }, + "RNT540": { + "product_code": "PRD84", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "11/20/17", + "rental_end": "1/11/18" + }, + "RNT541": { + "product_code": "PRD54", + "units_rented": 7, + "price_per_day": 20, + "rental_start": "8/12/18", + "rental_end": "5/5/16" + }, + "RNT542": { + "product_code": "PRD44", + "units_rented": 7, + "price_per_day": 31, + "rental_start": "12/20/17", + "rental_end": "11/19/18" + }, + "RNT543": { + "product_code": "PRD26", + "units_rented": 5, + "price_per_day": 14, + "rental_start": "2/27/17", + "rental_end": "3/4/17" + }, + "RNT544": { + "product_code": "PRD53", + "units_rented": 2, + "price_per_day": 14, + "rental_start": "1/9/18", + "rental_end": "6/19/17" + }, + "RNT545": { + "product_code": "PRD66", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "11/8/18", + "rental_end": "9/27/17" + }, + "RNT546": { + "product_code": "PRD81", + "units_rented": 9, + "price_per_day": 37, + "rental_start": "11/10/16", + "rental_end": "6/16/16" + }, + "RNT547": { + "product_code": "PRD28", + "units_rented": 3, + "price_per_day": 15, + "rental_start": "5/28/16", + "rental_end": "12/2/17" + }, + "RNT548": { + "product_code": "PRD58", + "units_rented": 2, + "price_per_day": 39, + "rental_start": "10/27/18", + "rental_end": "10/20/17" + }, + "RNT549": { + "product_code": "PRD0", + "units_rented": 6, + "price_per_day": 28, + "rental_start": "7/20/17", + "rental_end": "10/14/17" + }, + "RNT550": { + "product_code": "PRD40", + "units_rented": 7, + "price_per_day": 39, + "rental_start": "9/5/17", + "rental_end": "5/30/16" + }, + "RNT551": { + "product_code": "PRD34", + "units_rented": 9, + "price_per_day": 10, + "rental_start": "6/24/18", + "rental_end": "8/8/17" + }, + "RNT552": { + "product_code": "PRD16", + "units_rented": 7, + "price_per_day": 27, + "rental_start": "1/11/16", + "rental_end": "1/6/18" + }, + "RNT553": { + "product_code": "PRD75", + "units_rented": 4, + "price_per_day": 24, + "rental_start": "12/17/16", + "rental_end": "7/31/17" + }, + "RNT554": { + "product_code": "PRD70", + "units_rented": 4, + "price_per_day": 6, + "rental_start": "5/7/16", + "rental_end": "3/10/18" + }, + "RNT555": { + "product_code": "PRD42", + "units_rented": 10, + "price_per_day": 40, + "rental_start": "6/15/17", + "rental_end": "4/15/17" + }, + "RNT556": { + "product_code": "PRD81", + "units_rented": 1, + "price_per_day": 36, + "rental_start": "11/23/17", + "rental_end": "11/9/18" + }, + "RNT557": { + "product_code": "PRD99", + "units_rented": 3, + "price_per_day": 39, + "rental_start": "3/18/16", + "rental_end": "7/16/17" + }, + "RNT558": { + "product_code": "PRD45", + "units_rented": 8, + "price_per_day": 28, + "rental_start": "9/24/18", + "rental_end": "6/10/18" + }, + "RNT559": { + "product_code": "PRD82", + "units_rented": 7, + "price_per_day": 10, + "rental_start": "11/25/17", + "rental_end": "7/28/18" + }, + "RNT560": { + "product_code": "PRD0", + "units_rented": 2, + "price_per_day": 15, + "rental_start": "6/20/16", + "rental_end": "1/18/17" + }, + "RNT561": { + "product_code": "PRD35", + "units_rented": 1, + "price_per_day": 30, + "rental_start": "7/14/18", + "rental_end": "5/15/16" + }, + "RNT562": { + "product_code": "PRD9", + "units_rented": 7, + "price_per_day": 32, + "rental_start": "11/18/18", + "rental_end": "8/14/18" + }, + "RNT563": { + "product_code": "PRD49", + "units_rented": 3, + "price_per_day": 24, + "rental_start": "7/19/17", + "rental_end": "6/11/18" + }, + "RNT564": { + "product_code": "PRD72", + "units_rented": 8, + "price_per_day": 17, + "rental_start": "7/26/17", + "rental_end": "4/11/18" + }, + "RNT565": { + "product_code": "PRD37", + "units_rented": 6, + "price_per_day": 36, + "rental_start": "6/4/17", + "rental_end": "8/20/17" + }, + "RNT566": { + "product_code": "PRD3", + "units_rented": 3, + "price_per_day": 33, + "rental_start": "11/25/18", + "rental_end": "2/27/16" + }, + "RNT567": { + "product_code": "PRD49", + "units_rented": 1, + "price_per_day": 28, + "rental_start": "11/7/16", + "rental_end": "12/2/17" + }, + "RNT568": { + "product_code": "PRD85", + "units_rented": 1, + "price_per_day": 26, + "rental_start": "4/17/17", + "rental_end": "9/17/18" + }, + "RNT569": { + "product_code": "PRD43", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "10/1/18", + "rental_end": "5/30/18" + }, + "RNT570": { + "product_code": "PRD7", + "units_rented": 4, + "price_per_day": 38, + "rental_start": "11/21/17", + "rental_end": "7/13/17" + }, + "RNT571": { + "product_code": "PRD40", + "units_rented": 5, + "price_per_day": 12, + "rental_start": "7/3/16", + "rental_end": "7/10/16" + }, + "RNT572": { + "product_code": "PRD38", + "units_rented": 9, + "price_per_day": 10, + "rental_start": "10/13/18", + "rental_end": "8/7/16" + }, + "RNT573": { + "product_code": "PRD62", + "units_rented": 4, + "price_per_day": 23, + "rental_start": "2/20/18", + "rental_end": "3/12/18" + }, + "RNT574": { + "product_code": "PRD13", + "units_rented": 2, + "price_per_day": 9, + "rental_start": "5/18/16", + "rental_end": "8/19/18" + }, + "RNT575": { + "product_code": "PRD91", + "units_rented": 9, + "price_per_day": 12, + "rental_start": "8/1/17", + "rental_end": "1/22/17" + }, + "RNT576": { + "product_code": "PRD95", + "units_rented": 3, + "price_per_day": 39, + "rental_start": "10/7/16", + "rental_end": "6/9/18" + }, + "RNT577": { + "product_code": "PRD89", + "units_rented": 8, + "price_per_day": 26, + "rental_start": "1/6/17", + "rental_end": "4/23/18" + }, + "RNT578": { + "product_code": "PRD79", + "units_rented": 2, + "price_per_day": 40, + "rental_start": "1/5/16", + "rental_end": "3/9/16" + }, + "RNT579": { + "product_code": "PRD31", + "units_rented": 10, + "price_per_day": 26, + "rental_start": "7/14/17", + "rental_end": "9/5/17" + }, + "RNT580": { + "product_code": "PRD81", + "units_rented": 9, + "price_per_day": 25, + "rental_start": "7/2/18", + "rental_end": "4/24/17" + }, + "RNT581": { + "product_code": "PRD33", + "units_rented": 3, + "price_per_day": 24, + "rental_start": "8/3/16", + "rental_end": "5/9/18" + }, + "RNT582": { + "product_code": "PRD10", + "units_rented": 4, + "price_per_day": 35, + "rental_start": "5/2/17", + "rental_end": "4/28/17" + }, + "RNT583": { + "product_code": "PRD3", + "units_rented": 1, + "price_per_day": 39, + "rental_start": "6/15/17", + "rental_end": "5/19/18" + }, + "RNT584": { + "product_code": "PRD37", + "units_rented": 10, + "price_per_day": 18, + "rental_start": "4/16/16", + "rental_end": "10/6/18" + }, + "RNT585": { + "product_code": "PRD75", + "units_rented": 1, + "price_per_day": 16, + "rental_start": "2/9/18", + "rental_end": "1/15/16" + }, + "RNT586": { + "product_code": "PRD73", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "1/27/17", + "rental_end": "7/5/16" + }, + "RNT587": { + "product_code": "PRD63", + "units_rented": 3, + "price_per_day": 27, + "rental_start": "5/1/18", + "rental_end": "3/20/17" + }, + "RNT588": { + "product_code": "PRD70", + "units_rented": 5, + "price_per_day": 6, + "rental_start": "5/13/16", + "rental_end": "9/23/17" + }, + "RNT589": { + "product_code": "PRD60", + "units_rented": 10, + "price_per_day": 16, + "rental_start": "4/3/16", + "rental_end": "6/1/16" + }, + "RNT590": { + "product_code": "PRD67", + "units_rented": 7, + "price_per_day": 40, + "rental_start": "12/23/18", + "rental_end": "6/26/17" + }, + "RNT591": { + "product_code": "PRD73", + "units_rented": 4, + "price_per_day": 22, + "rental_start": "6/2/18", + "rental_end": "3/21/18" + }, + "RNT592": { + "product_code": "PRD1", + "units_rented": 4, + "price_per_day": 21, + "rental_start": "8/26/16", + "rental_end": "5/4/16" + }, + "RNT593": { + "product_code": "PRD69", + "units_rented": 1, + "price_per_day": 37, + "rental_start": "11/26/16", + "rental_end": "9/23/16" + }, + "RNT594": { + "product_code": "PRD51", + "units_rented": 7, + "price_per_day": 30, + "rental_start": "5/6/16", + "rental_end": "8/21/17" + }, + "RNT595": { + "product_code": "PRD24", + "units_rented": 5, + "price_per_day": 32, + "rental_start": "2/23/17", + "rental_end": "1/2/16" + }, + "RNT596": { + "product_code": "PRD72", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "3/9/17", + "rental_end": "10/2/17" + }, + "RNT597": { + "product_code": "PRD45", + "units_rented": 7, + "price_per_day": 37, + "rental_start": "10/29/18", + "rental_end": "2/21/17" + }, + "RNT598": { + "product_code": "PRD48", + "units_rented": 7, + "price_per_day": 9, + "rental_start": "3/2/18", + "rental_end": "8/29/16" + }, + "RNT599": { + "product_code": "PRD87", + "units_rented": 8, + "price_per_day": 21, + "rental_start": "6/17/18", + "rental_end": "2/12/16" + }, + "RNT600": { + "product_code": "PRD99", + "units_rented": 10, + "price_per_day": 25, + "rental_start": "10/8/16", + "rental_end": "8/20/17" + }, + "RNT601": { + "product_code": "PRD71", + "units_rented": 5, + "price_per_day": 32, + "rental_start": "6/12/17", + "rental_end": "1/12/17" + }, + "RNT602": { + "product_code": "PRD24", + "units_rented": 8, + "price_per_day": 31, + "rental_start": "10/10/16", + "rental_end": "4/12/16" + }, + "RNT603": { + "product_code": "PRD65", + "units_rented": 1, + "price_per_day": 9, + "rental_start": "9/17/17", + "rental_end": "2/7/16" + }, + "RNT604": { + "product_code": "PRD72", + "units_rented": 6, + "price_per_day": 6, + "rental_start": "7/14/17", + "rental_end": "7/6/16" + }, + "RNT605": { + "product_code": "PRD48", + "units_rented": 7, + "price_per_day": 33, + "rental_start": "11/4/17", + "rental_end": "9/6/16" + }, + "RNT606": { + "product_code": "PRD61", + "units_rented": 10, + "price_per_day": 39, + "rental_start": "10/21/18", + "rental_end": "5/31/16" + }, + "RNT607": { + "product_code": "PRD83", + "units_rented": 2, + "price_per_day": 35, + "rental_start": "4/12/17", + "rental_end": "10/16/18" + }, + "RNT608": { + "product_code": "PRD38", + "units_rented": 2, + "price_per_day": 21, + "rental_start": "7/12/16", + "rental_end": "7/31/16" + }, + "RNT609": { + "product_code": "PRD96", + "units_rented": 5, + "price_per_day": 18, + "rental_start": "1/16/16", + "rental_end": "7/24/18" + }, + "RNT610": { + "product_code": "PRD94", + "units_rented": 9, + "price_per_day": 24, + "rental_start": "1/23/18", + "rental_end": "11/4/18" + }, + "RNT611": { + "product_code": "PRD97", + "units_rented": 4, + "price_per_day": 33, + "rental_start": "3/5/18", + "rental_end": "1/30/18" + }, + "RNT612": { + "product_code": "PRD90", + "units_rented": 2, + "price_per_day": 32, + "rental_start": "12/12/16", + "rental_end": "8/29/17" + }, + "RNT613": { + "product_code": "PRD99", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "10/4/18", + "rental_end": "1/17/18" + }, + "RNT614": { + "product_code": "PRD56", + "units_rented": 1, + "price_per_day": 16, + "rental_start": "3/6/18", + "rental_end": "12/7/18" + }, + "RNT615": { + "product_code": "PRD29", + "units_rented": 4, + "price_per_day": 40, + "rental_start": "9/30/17", + "rental_end": "6/29/17" + }, + "RNT616": { + "product_code": "PRD99", + "units_rented": 2, + "price_per_day": 35, + "rental_start": "8/24/16", + "rental_end": "4/27/17" + }, + "RNT617": { + "product_code": "PRD87", + "units_rented": 10, + "price_per_day": 20, + "rental_start": "5/28/17", + "rental_end": "4/15/18" + }, + "RNT618": { + "product_code": "PRD96", + "units_rented": 9, + "price_per_day": 38, + "rental_start": "7/25/17", + "rental_end": "1/3/18" + }, + "RNT619": { + "product_code": "PRD30", + "units_rented": 6, + "price_per_day": 13, + "rental_start": "7/24/17", + "rental_end": "8/21/17" + }, + "RNT620": { + "product_code": "PRD81", + "units_rented": 2, + "price_per_day": 16, + "rental_start": "8/13/16", + "rental_end": "1/19/18" + }, + "RNT621": { + "product_code": "PRD40", + "units_rented": 3, + "price_per_day": 39, + "rental_start": "4/26/16", + "rental_end": "3/15/18" + }, + "RNT622": { + "product_code": "PRD40", + "units_rented": 3, + "price_per_day": 32, + "rental_start": "8/22/16", + "rental_end": "4/18/16" + }, + "RNT623": { + "product_code": "PRD44", + "units_rented": 5, + "price_per_day": 39, + "rental_start": "4/18/16", + "rental_end": "6/30/16" + }, + "RNT624": { + "product_code": "PRD15", + "units_rented": 8, + "price_per_day": 34, + "rental_start": "1/20/17", + "rental_end": "4/2/17" + }, + "RNT625": { + "product_code": "PRD7", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "4/15/16", + "rental_end": "5/1/16" + }, + "RNT626": { + "product_code": "PRD11", + "units_rented": 9, + "price_per_day": 32, + "rental_start": "7/22/18", + "rental_end": "8/1/17" + }, + "RNT627": { + "product_code": "PRD91", + "units_rented": 6, + "price_per_day": 21, + "rental_start": "8/23/16", + "rental_end": "12/31/18" + }, + "RNT628": { + "product_code": "PRD81", + "units_rented": 3, + "price_per_day": 7, + "rental_start": "9/1/17", + "rental_end": "12/7/18" + }, + "RNT629": { + "product_code": "PRD81", + "units_rented": 5, + "price_per_day": 19, + "rental_start": "1/2/17", + "rental_end": "8/31/17" + }, + "RNT630": { + "product_code": "PRD68", + "units_rented": 6, + "price_per_day": 37, + "rental_start": "11/27/16", + "rental_end": "9/15/16" + }, + "RNT631": { + "product_code": "PRD68", + "units_rented": 8, + "price_per_day": 25, + "rental_start": "2/8/16", + "rental_end": "10/5/18" + }, + "RNT632": { + "product_code": "PRD45", + "units_rented": 7, + "price_per_day": 18, + "rental_start": "1/13/16", + "rental_end": "1/7/16" + }, + "RNT633": { + "product_code": "PRD54", + "units_rented": 9, + "price_per_day": 6, + "rental_start": "7/9/18", + "rental_end": "2/1/18" + }, + "RNT634": { + "product_code": "PRD99", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "9/16/18", + "rental_end": "8/7/18" + }, + "RNT635": { + "product_code": "PRD81", + "units_rented": 2, + "price_per_day": 11, + "rental_start": "3/2/16", + "rental_end": "1/22/17" + }, + "RNT636": { + "product_code": "PRD81", + "units_rented": 7, + "price_per_day": 38, + "rental_start": "11/2/18", + "rental_end": "9/15/17" + }, + "RNT637": { + "product_code": "PRD85", + "units_rented": 1, + "price_per_day": 17, + "rental_start": "4/24/16", + "rental_end": "11/28/17" + }, + "RNT638": { + "product_code": "PRD15", + "units_rented": 9, + "price_per_day": 17, + "rental_start": "2/24/17", + "rental_end": "3/20/16" + }, + "RNT639": { + "product_code": "PRD47", + "units_rented": 5, + "price_per_day": 23, + "rental_start": "12/9/18", + "rental_end": "9/10/17" + }, + "RNT640": { + "product_code": "PRD35", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "9/9/17", + "rental_end": "4/29/16" + }, + "RNT641": { + "product_code": "PRD94", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "8/30/16", + "rental_end": "5/10/18" + }, + "RNT642": { + "product_code": "PRD14", + "units_rented": 8, + "price_per_day": 28, + "rental_start": "7/25/16", + "rental_end": "7/3/16" + }, + "RNT643": { + "product_code": "PRD59", + "units_rented": 7, + "price_per_day": 32, + "rental_start": "10/20/18", + "rental_end": "2/13/16" + }, + "RNT644": { + "product_code": "PRD45", + "units_rented": 6, + "price_per_day": 11, + "rental_start": "1/22/18", + "rental_end": "2/27/18" + }, + "RNT645": { + "product_code": "PRD65", + "units_rented": 4, + "price_per_day": 29, + "rental_start": "12/29/16", + "rental_end": "4/12/17" + }, + "RNT646": { + "product_code": "PRD8", + "units_rented": 5, + "price_per_day": 39, + "rental_start": "4/13/16", + "rental_end": "9/17/18" + }, + "RNT647": { + "product_code": "PRD8", + "units_rented": 2, + "price_per_day": 7, + "rental_start": "4/5/17", + "rental_end": "9/8/16" + }, + "RNT648": { + "product_code": "PRD53", + "units_rented": 4, + "price_per_day": 11, + "rental_start": "7/19/18", + "rental_end": "6/26/17" + }, + "RNT649": { + "product_code": "PRD64", + "units_rented": 9, + "price_per_day": 37, + "rental_start": "7/17/18", + "rental_end": "11/16/17" + }, + "RNT650": { + "product_code": "PRD47", + "units_rented": 10, + "price_per_day": 11, + "rental_start": "1/26/16", + "rental_end": "6/10/17" + }, + "RNT651": { + "product_code": "PRD94", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "9/13/18", + "rental_end": "1/27/16" + }, + "RNT652": { + "product_code": "PRD46", + "units_rented": 3, + "price_per_day": 26, + "rental_start": "3/13/16", + "rental_end": "1/2/17" + }, + "RNT653": { + "product_code": "PRD54", + "units_rented": 10, + "price_per_day": 12, + "rental_start": "8/22/17", + "rental_end": "3/25/17" + }, + "RNT654": { + "product_code": "PRD95", + "units_rented": 6, + "price_per_day": 10, + "rental_start": "5/2/18", + "rental_end": "12/31/18" + }, + "RNT655": { + "product_code": "PRD3", + "units_rented": 1, + "price_per_day": 32, + "rental_start": "10/20/18", + "rental_end": "11/3/18" + }, + "RNT656": { + "product_code": "PRD34", + "units_rented": 7, + "price_per_day": 10, + "rental_start": "10/5/18", + "rental_end": "7/4/16" + }, + "RNT657": { + "product_code": "PRD81", + "units_rented": 8, + "price_per_day": 26, + "rental_start": "8/5/16", + "rental_end": "11/15/18" + }, + "RNT658": { + "product_code": "PRD96", + "units_rented": 5, + "price_per_day": 29, + "rental_start": "8/9/16", + "rental_end": "11/27/18" + }, + "RNT659": { + "product_code": "PRD9", + "units_rented": 10, + "price_per_day": 23, + "rental_start": "9/14/18", + "rental_end": "9/6/17" + }, + "RNT660": { + "product_code": "PRD89", + "units_rented": 1, + "price_per_day": 37, + "rental_start": "2/15/16", + "rental_end": "12/18/16" + }, + "RNT661": { + "product_code": "PRD56", + "units_rented": 7, + "price_per_day": 37, + "rental_start": "2/5/18", + "rental_end": "7/18/18" + }, + "RNT662": { + "product_code": "PRD12", + "units_rented": 5, + "price_per_day": 30, + "rental_start": "4/27/18", + "rental_end": "2/13/18" + }, + "RNT663": { + "product_code": "PRD85", + "units_rented": 8, + "price_per_day": 34, + "rental_start": "1/3/18", + "rental_end": "1/20/17" + }, + "RNT664": { + "product_code": "PRD4", + "units_rented": 3, + "price_per_day": 11, + "rental_start": "7/2/18", + "rental_end": "8/20/16" + }, + "RNT665": { + "product_code": "PRD78", + "units_rented": 5, + "price_per_day": 21, + "rental_start": "9/8/17", + "rental_end": "2/4/17" + }, + "RNT666": { + "product_code": "PRD75", + "units_rented": 6, + "price_per_day": 22, + "rental_start": "11/21/16", + "rental_end": "9/1/17" + }, + "RNT667": { + "product_code": "PRD30", + "units_rented": 2, + "price_per_day": 25, + "rental_start": "1/4/18", + "rental_end": "3/31/16" + }, + "RNT668": { + "product_code": "PRD85", + "units_rented": 6, + "price_per_day": 17, + "rental_start": "2/17/16", + "rental_end": "1/1/16" + }, + "RNT669": { + "product_code": "PRD43", + "units_rented": 3, + "price_per_day": 38, + "rental_start": "7/28/18", + "rental_end": "12/16/18" + }, + "RNT670": { + "product_code": "PRD65", + "units_rented": 5, + "price_per_day": 20, + "rental_start": "11/27/16", + "rental_end": "1/30/16" + }, + "RNT671": { + "product_code": "PRD51", + "units_rented": 6, + "price_per_day": 21, + "rental_start": "3/5/18", + "rental_end": "6/16/17" + }, + "RNT672": { + "product_code": "PRD64", + "units_rented": 10, + "price_per_day": 14, + "rental_start": "6/16/16", + "rental_end": "4/9/18" + }, + "RNT673": { + "product_code": "PRD88", + "units_rented": 3, + "price_per_day": 9, + "rental_start": "1/31/16", + "rental_end": "10/4/16" + }, + "RNT674": { + "product_code": "PRD56", + "units_rented": 8, + "price_per_day": 25, + "rental_start": "7/24/18", + "rental_end": "4/24/17" + }, + "RNT675": { + "product_code": "PRD48", + "units_rented": 5, + "price_per_day": 18, + "rental_start": "2/19/18", + "rental_end": "2/22/18" + }, + "RNT676": { + "product_code": "PRD46", + "units_rented": 3, + "price_per_day": 20, + "rental_start": "10/13/17", + "rental_end": "11/7/18" + }, + "RNT677": { + "product_code": "PRD69", + "units_rented": 10, + "price_per_day": 40, + "rental_start": "9/3/17", + "rental_end": "8/17/17" + }, + "RNT678": { + "product_code": "PRD44", + "units_rented": 8, + "price_per_day": 25, + "rental_start": "11/27/16", + "rental_end": "11/13/16" + }, + "RNT679": { + "product_code": "PRD26", + "units_rented": 5, + "price_per_day": 29, + "rental_start": "11/21/17", + "rental_end": "2/3/16" + }, + "RNT680": { + "product_code": "PRD21", + "units_rented": 4, + "price_per_day": 33, + "rental_start": "12/28/16", + "rental_end": "12/3/18" + }, + "RNT681": { + "product_code": "PRD70", + "units_rented": 1, + "price_per_day": 40, + "rental_start": "4/29/16", + "rental_end": "9/19/18" + }, + "RNT682": { + "product_code": "PRD68", + "units_rented": 10, + "price_per_day": 29, + "rental_start": "12/31/18", + "rental_end": "10/19/18" + }, + "RNT683": { + "product_code": "PRD17", + "units_rented": 4, + "price_per_day": 17, + "rental_start": "1/10/17", + "rental_end": "4/12/18" + }, + "RNT684": { + "product_code": "PRD74", + "units_rented": 3, + "price_per_day": 25, + "rental_start": "6/26/17", + "rental_end": "4/3/16" + }, + "RNT685": { + "product_code": "PRD17", + "units_rented": 6, + "price_per_day": 25, + "rental_start": "2/24/17", + "rental_end": "3/3/17" + }, + "RNT686": { + "product_code": "PRD81", + "units_rented": 9, + "price_per_day": 34, + "rental_start": "12/21/16", + "rental_end": "10/28/18" + }, + "RNT687": { + "product_code": "PRD37", + "units_rented": 8, + "price_per_day": 33, + "rental_start": "5/8/18", + "rental_end": "5/30/18" + }, + "RNT688": { + "product_code": "PRD74", + "units_rented": 6, + "price_per_day": 7, + "rental_start": "7/6/18", + "rental_end": "6/2/18" + }, + "RNT689": { + "product_code": "PRD1", + "units_rented": 4, + "price_per_day": 19, + "rental_start": "10/19/16", + "rental_end": "12/20/16" + }, + "RNT690": { + "product_code": "PRD30", + "units_rented": 1, + "price_per_day": 37, + "rental_start": "12/20/17", + "rental_end": "6/15/18" + }, + "RNT691": { + "product_code": "PRD84", + "units_rented": 5, + "price_per_day": 36, + "rental_start": "9/19/18", + "rental_end": "9/10/16" + }, + "RNT692": { + "product_code": "PRD50", + "units_rented": 10, + "price_per_day": 18, + "rental_start": "8/27/17", + "rental_end": "7/29/17" + }, + "RNT693": { + "product_code": "PRD80", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "5/16/16", + "rental_end": "4/12/18" + }, + "RNT694": { + "product_code": "PRD12", + "units_rented": 9, + "price_per_day": 26, + "rental_start": "12/9/18", + "rental_end": "9/15/17" + }, + "RNT695": { + "product_code": "PRD47", + "units_rented": 5, + "price_per_day": 25, + "rental_start": "7/14/16", + "rental_end": "3/5/16" + }, + "RNT696": { + "product_code": "PRD12", + "units_rented": 2, + "price_per_day": 39, + "rental_start": "11/17/17", + "rental_end": "5/18/18" + }, + "RNT697": { + "product_code": "PRD24", + "units_rented": 4, + "price_per_day": 32, + "rental_start": "11/28/17", + "rental_end": "8/21/18" + }, + "RNT698": { + "product_code": "PRD69", + "units_rented": 1, + "price_per_day": 38, + "rental_start": "4/2/18", + "rental_end": "11/22/16" + }, + "RNT699": { + "product_code": "PRD66", + "units_rented": 4, + "price_per_day": 6, + "rental_start": "6/7/18", + "rental_end": "7/24/18" + }, + "RNT700": { + "product_code": "PRD44", + "units_rented": 4, + "price_per_day": 28, + "rental_start": "6/1/16", + "rental_end": "10/27/18" + }, + "RNT701": { + "product_code": "PRD42", + "units_rented": 5, + "price_per_day": 22, + "rental_start": "10/24/17", + "rental_end": "10/11/18" + }, + "RNT702": { + "product_code": "PRD88", + "units_rented": 6, + "price_per_day": 15, + "rental_start": "9/26/17", + "rental_end": "12/8/16" + }, + "RNT703": { + "product_code": "PRD41", + "units_rented": 6, + "price_per_day": 9, + "rental_start": "6/15/18", + "rental_end": "3/1/18" + }, + "RNT704": { + "product_code": "PRD6", + "units_rented": 4, + "price_per_day": 19, + "rental_start": "12/23/17", + "rental_end": "4/2/16" + }, + "RNT705": { + "product_code": "PRD74", + "units_rented": 5, + "price_per_day": 12, + "rental_start": "2/25/17", + "rental_end": "6/23/17" + }, + "RNT706": { + "product_code": "PRD59", + "units_rented": 5, + "price_per_day": 20, + "rental_start": "9/8/17", + "rental_end": "5/17/17" + }, + "RNT707": { + "product_code": "PRD13", + "units_rented": 9, + "price_per_day": 24, + "rental_start": "4/10/16", + "rental_end": "10/13/18" + }, + "RNT708": { + "product_code": "PRD28", + "units_rented": 7, + "price_per_day": 16, + "rental_start": "7/29/16", + "rental_end": "1/15/17" + }, + "RNT709": { + "product_code": "PRD26", + "units_rented": 9, + "price_per_day": 12, + "rental_start": "5/18/17", + "rental_end": "1/15/17" + }, + "RNT710": { + "product_code": "PRD58", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "11/17/16", + "rental_end": "12/29/18" + }, + "RNT711": { + "product_code": "PRD41", + "units_rented": 1, + "price_per_day": 9, + "rental_start": "4/25/18", + "rental_end": "4/25/17" + }, + "RNT712": { + "product_code": "PRD74", + "units_rented": 3, + "price_per_day": 10, + "rental_start": "10/9/17", + "rental_end": "8/8/16" + }, + "RNT713": { + "product_code": "PRD11", + "units_rented": 2, + "price_per_day": 14, + "rental_start": "9/3/18", + "rental_end": "11/27/18" + }, + "RNT714": { + "product_code": "PRD18", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "4/9/16", + "rental_end": "10/18/17" + }, + "RNT715": { + "product_code": "PRD78", + "units_rented": 3, + "price_per_day": 27, + "rental_start": "8/23/17", + "rental_end": "6/23/16" + }, + "RNT716": { + "product_code": "PRD12", + "units_rented": 6, + "price_per_day": 22, + "rental_start": "9/16/16", + "rental_end": "11/27/16" + }, + "RNT717": { + "product_code": "PRD90", + "units_rented": 3, + "price_per_day": 31, + "rental_start": "9/25/18", + "rental_end": "1/12/16" + }, + "RNT718": { + "product_code": "PRD87", + "units_rented": 5, + "price_per_day": 19, + "rental_start": "3/25/18", + "rental_end": "4/26/18" + }, + "RNT719": { + "product_code": "PRD18", + "units_rented": 6, + "price_per_day": 24, + "rental_start": "9/22/16", + "rental_end": "4/5/16" + }, + "RNT720": { + "product_code": "PRD58", + "units_rented": 6, + "price_per_day": 36, + "rental_start": "1/29/16", + "rental_end": "4/18/18" + }, + "RNT721": { + "product_code": "PRD58", + "units_rented": 2, + "price_per_day": 28, + "rental_start": "9/2/18", + "rental_end": "2/13/18" + }, + "RNT722": { + "product_code": "PRD24", + "units_rented": 8, + "price_per_day": 22, + "rental_start": "10/6/17", + "rental_end": "3/8/16" + }, + "RNT723": { + "product_code": "PRD46", + "units_rented": 8, + "price_per_day": 28, + "rental_start": "2/13/16", + "rental_end": "3/8/17" + }, + "RNT724": { + "product_code": "PRD82", + "units_rented": 9, + "price_per_day": 11, + "rental_start": "1/3/16", + "rental_end": "10/29/18" + }, + "RNT725": { + "product_code": "PRD71", + "units_rented": 7, + "price_per_day": 32, + "rental_start": "2/19/17", + "rental_end": "11/17/16" + }, + "RNT726": { + "product_code": "PRD22", + "units_rented": 2, + "price_per_day": 39, + "rental_start": "11/24/17", + "rental_end": "5/6/16" + }, + "RNT727": { + "product_code": "PRD69", + "units_rented": 9, + "price_per_day": 24, + "rental_start": "1/18/17", + "rental_end": "7/15/18" + }, + "RNT728": { + "product_code": "PRD48", + "units_rented": 7, + "price_per_day": 20, + "rental_start": "7/27/17", + "rental_end": "7/23/18" + }, + "RNT729": { + "product_code": "PRD16", + "units_rented": 3, + "price_per_day": 39, + "rental_start": "8/18/17", + "rental_end": "4/23/17" + }, + "RNT730": { + "product_code": "PRD18", + "units_rented": 4, + "price_per_day": 16, + "rental_start": "12/20/16", + "rental_end": "8/23/18" + }, + "RNT731": { + "product_code": "PRD30", + "units_rented": 1, + "price_per_day": 10, + "rental_start": "11/17/17", + "rental_end": "9/2/17" + }, + "RNT732": { + "product_code": "PRD96", + "units_rented": 5, + "price_per_day": 35, + "rental_start": "8/18/17", + "rental_end": "11/24/16" + }, + "RNT733": { + "product_code": "PRD40", + "units_rented": 1, + "price_per_day": 32, + "rental_start": "5/26/17", + "rental_end": "11/5/16" + }, + "RNT734": { + "product_code": "PRD4", + "units_rented": 9, + "price_per_day": 27, + "rental_start": "4/3/16", + "rental_end": "10/25/17" + }, + "RNT735": { + "product_code": "PRD22", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "1/15/18", + "rental_end": "11/3/18" + }, + "RNT736": { + "product_code": "PRD31", + "units_rented": 10, + "price_per_day": 37, + "rental_start": "4/13/16", + "rental_end": "6/9/17" + }, + "RNT737": { + "product_code": "PRD92", + "units_rented": 1, + "price_per_day": 20, + "rental_start": "1/4/16", + "rental_end": "12/6/16" + }, + "RNT738": { + "product_code": "PRD59", + "units_rented": 4, + "price_per_day": 11, + "rental_start": "11/3/16", + "rental_end": "7/1/17" + }, + "RNT739": { + "product_code": "PRD73", + "units_rented": 5, + "price_per_day": 37, + "rental_start": "9/18/17", + "rental_end": "6/2/18" + }, + "RNT740": { + "product_code": "PRD81", + "units_rented": 7, + "price_per_day": 32, + "rental_start": "2/16/18", + "rental_end": "10/13/17" + }, + "RNT741": { + "product_code": "PRD1", + "units_rented": 3, + "price_per_day": 6, + "rental_start": "4/21/16", + "rental_end": "2/7/18" + }, + "RNT742": { + "product_code": "PRD9", + "units_rented": 4, + "price_per_day": 26, + "rental_start": "4/24/16", + "rental_end": "8/21/17" + }, + "RNT743": { + "product_code": "PRD44", + "units_rented": 10, + "price_per_day": 32, + "rental_start": "6/28/16", + "rental_end": "12/22/18" + }, + "RNT744": { + "product_code": "PRD39", + "units_rented": 1, + "price_per_day": 15, + "rental_start": "4/28/16", + "rental_end": "8/27/17" + }, + "RNT745": { + "product_code": "PRD36", + "units_rented": 6, + "price_per_day": 21, + "rental_start": "9/2/18", + "rental_end": "10/18/17" + }, + "RNT746": { + "product_code": "PRD40", + "units_rented": 5, + "price_per_day": 28, + "rental_start": "10/16/17", + "rental_end": "8/8/17" + }, + "RNT747": { + "product_code": "PRD65", + "units_rented": 3, + "price_per_day": 22, + "rental_start": "7/1/16", + "rental_end": "4/11/18" + }, + "RNT748": { + "product_code": "PRD91", + "units_rented": 3, + "price_per_day": 7, + "rental_start": "9/14/17", + "rental_end": "3/30/17" + }, + "RNT749": { + "product_code": "PRD70", + "units_rented": 4, + "price_per_day": 36, + "rental_start": "7/6/17", + "rental_end": "1/11/18" + }, + "RNT750": { + "product_code": "PRD67", + "units_rented": 1, + "price_per_day": 40, + "rental_start": "1/6/17", + "rental_end": "8/22/16" + }, + "RNT751": { + "product_code": "PRD2", + "units_rented": 4, + "price_per_day": 33, + "rental_start": "12/9/17", + "rental_end": "5/20/17" + }, + "RNT752": { + "product_code": "PRD1", + "units_rented": 6, + "price_per_day": 34, + "rental_start": "5/21/17", + "rental_end": "10/29/18" + }, + "RNT753": { + "product_code": "PRD81", + "units_rented": 10, + "price_per_day": 25, + "rental_start": "9/19/18", + "rental_end": "7/10/18" + }, + "RNT754": { + "product_code": "PRD80", + "units_rented": 10, + "price_per_day": 22, + "rental_start": "3/28/17", + "rental_end": "9/18/18" + }, + "RNT755": { + "product_code": "PRD28", + "units_rented": 7, + "price_per_day": 8, + "rental_start": "2/4/16", + "rental_end": "3/30/17" + }, + "RNT756": { + "product_code": "PRD44", + "units_rented": 6, + "price_per_day": 14, + "rental_start": "12/3/17", + "rental_end": "7/14/17" + }, + "RNT757": { + "product_code": "PRD52", + "units_rented": 1, + "price_per_day": 14, + "rental_start": "12/13/18", + "rental_end": "7/6/18" + }, + "RNT758": { + "product_code": "PRD34", + "units_rented": 1, + "price_per_day": 19, + "rental_start": "11/21/16", + "rental_end": "8/31/17" + }, + "RNT759": { + "product_code": "PRD53", + "units_rented": 5, + "price_per_day": 11, + "rental_start": "2/10/18", + "rental_end": "1/5/16" + }, + "RNT760": { + "product_code": "PRD11", + "units_rented": 7, + "price_per_day": 14, + "rental_start": "11/23/16", + "rental_end": "5/9/18" + }, + "RNT761": { + "product_code": "PRD2", + "units_rented": 5, + "price_per_day": 40, + "rental_start": "3/21/16", + "rental_end": "11/27/17" + }, + "RNT762": { + "product_code": "PRD78", + "units_rented": 8, + "price_per_day": 26, + "rental_start": "8/1/16", + "rental_end": "3/2/17" + }, + "RNT763": { + "product_code": "PRD43", + "units_rented": 7, + "price_per_day": 31, + "rental_start": "1/10/18", + "rental_end": "5/21/18" + }, + "RNT764": { + "product_code": "PRD26", + "units_rented": 5, + "price_per_day": 13, + "rental_start": "9/13/16", + "rental_end": "2/2/18" + }, + "RNT765": { + "product_code": "PRD25", + "units_rented": 6, + "price_per_day": 10, + "rental_start": "9/13/16", + "rental_end": "4/28/17" + }, + "RNT766": { + "product_code": "PRD86", + "units_rented": 4, + "price_per_day": 25, + "rental_start": "3/15/18", + "rental_end": "7/28/17" + }, + "RNT767": { + "product_code": "PRD29", + "units_rented": 10, + "price_per_day": 23, + "rental_start": "9/25/16", + "rental_end": "3/2/18" + }, + "RNT768": { + "product_code": "PRD68", + "units_rented": 1, + "price_per_day": 10, + "rental_start": "3/8/17", + "rental_end": "9/5/18" + }, + "RNT769": { + "product_code": "PRD51", + "units_rented": 4, + "price_per_day": 28, + "rental_start": "11/12/17", + "rental_end": "11/18/18" + }, + "RNT770": { + "product_code": "PRD83", + "units_rented": 7, + "price_per_day": 36, + "rental_start": "12/2/18", + "rental_end": "1/6/16" + }, + "RNT771": { + "product_code": "PRD65", + "units_rented": 9, + "price_per_day": 17, + "rental_start": "5/4/16", + "rental_end": "6/12/16" + }, + "RNT772": { + "product_code": "PRD71", + "units_rented": 7, + "price_per_day": 20, + "rental_start": "6/18/18", + "rental_end": "2/21/18" + }, + "RNT773": { + "product_code": "PRD14", + "units_rented": 4, + "price_per_day": 24, + "rental_start": "10/23/16", + "rental_end": "10/13/16" + }, + "RNT774": { + "product_code": "PRD30", + "units_rented": 1, + "price_per_day": 36, + "rental_start": "7/13/18", + "rental_end": "12/28/16" + }, + "RNT775": { + "product_code": "PRD2", + "units_rented": 3, + "price_per_day": 36, + "rental_start": "4/20/17", + "rental_end": "10/10/18" + }, + "RNT776": { + "product_code": "PRD70", + "units_rented": 1, + "price_per_day": 14, + "rental_start": "6/19/16", + "rental_end": "" + }, + "RNT777": { + "product_code": "PRD15", + "units_rented": 9, + "price_per_day": 39, + "rental_start": "8/11/17", + "rental_end": "10/7/18" + }, + "RNT778": { + "product_code": "PRD65", + "units_rented": 5, + "price_per_day": 39, + "rental_start": "1/13/18", + "rental_end": "1/3/17" + }, + "RNT779": { + "product_code": "PRD37", + "units_rented": 5, + "price_per_day": 23, + "rental_start": "1/31/17", + "rental_end": "8/21/16" + }, + "RNT780": { + "product_code": "PRD67", + "units_rented": 7, + "price_per_day": 21, + "rental_start": "8/21/18", + "rental_end": "10/5/18" + }, + "RNT781": { + "product_code": "PRD61", + "units_rented": 9, + "price_per_day": 26, + "rental_start": "1/31/16", + "rental_end": "7/19/17" + }, + "RNT782": { + "product_code": "PRD14", + "units_rented": 10, + "price_per_day": 22, + "rental_start": "1/25/18", + "rental_end": "4/16/17" + }, + "RNT783": { + "product_code": "PRD98", + "units_rented": 10, + "price_per_day": 13, + "rental_start": "11/27/18", + "rental_end": "3/22/17" + }, + "RNT784": { + "product_code": "PRD53", + "units_rented": 5, + "price_per_day": 31, + "rental_start": "12/31/17", + "rental_end": "7/7/18" + }, + "RNT785": { + "product_code": "PRD15", + "units_rented": 5, + "price_per_day": 28, + "rental_start": "7/31/18", + "rental_end": "12/20/18" + }, + "RNT786": { + "product_code": "PRD79", + "units_rented": 7, + "price_per_day": 14, + "rental_start": "12/1/16", + "rental_end": "2/25/18" + }, + "RNT787": { + "product_code": "PRD31", + "units_rented": 10, + "price_per_day": 6, + "rental_start": "10/14/17", + "rental_end": "2/15/18" + }, + "RNT788": { + "product_code": "PRD10", + "units_rented": 4, + "price_per_day": 27, + "rental_start": "2/24/16", + "rental_end": "7/31/16" + }, + "RNT789": { + "product_code": "PRD7", + "units_rented": 7, + "price_per_day": 26, + "rental_start": "4/10/18", + "rental_end": "6/4/18" + }, + "RNT790": { + "product_code": "PRD55", + "units_rented": 7, + "price_per_day": 11, + "rental_start": "3/30/17", + "rental_end": "2/24/16" + }, + "RNT791": { + "product_code": "PRD92", + "units_rented": 9, + "price_per_day": 27, + "rental_start": "3/18/18", + "rental_end": "6/3/17" + }, + "RNT792": { + "product_code": "PRD82", + "units_rented": 1, + "price_per_day": 13, + "rental_start": "12/24/17", + "rental_end": "12/8/18" + }, + "RNT793": { + "product_code": "PRD55", + "units_rented": 1, + "price_per_day": 22, + "rental_start": "1/16/16", + "rental_end": "2/7/16" + }, + "RNT794": { + "product_code": "PRD54", + "units_rented": 5, + "price_per_day": 39, + "rental_start": "12/30/18", + "rental_end": "4/30/16" + }, + "RNT795": { + "product_code": "PRD83", + "units_rented": 8, + "price_per_day": 19, + "rental_start": "1/25/18", + "rental_end": "9/15/17" + }, + "RNT796": { + "product_code": "PRD90", + "units_rented": 10, + "price_per_day": 32, + "rental_start": "1/13/18", + "rental_end": "6/8/17" + }, + "RNT797": { + "product_code": "PRD56", + "units_rented": 5, + "price_per_day": 13, + "rental_start": "2/2/16", + "rental_end": "2/6/17" + }, + "RNT798": { + "product_code": "PRD58", + "units_rented": 7, + "price_per_day": 36, + "rental_start": "10/9/16", + "rental_end": "9/5/18" + }, + "RNT799": { + "product_code": "PRD23", + "units_rented": 2, + "price_per_day": 33, + "rental_start": "3/12/17", + "rental_end": "4/22/18" + }, + "RNT800": { + "product_code": "PRD66", + "units_rented": 3, + "price_per_day": 25, + "rental_start": "5/15/16", + "rental_end": "3/13/18" + }, + "RNT801": { + "product_code": "PRD54", + "units_rented": 8, + "price_per_day": 34, + "rental_start": "6/25/17", + "rental_end": "5/19/18" + }, + "RNT802": { + "product_code": "PRD37", + "units_rented": 10, + "price_per_day": 9, + "rental_start": "4/17/17", + "rental_end": "12/13/17" + }, + "RNT803": { + "product_code": "PRD32", + "units_rented": 10, + "price_per_day": 5, + "rental_start": "10/17/16", + "rental_end": "2/10/16" + }, + "RNT804": { + "product_code": "PRD19", + "units_rented": 2, + "price_per_day": 38, + "rental_start": "9/30/16", + "rental_end": "4/8/17" + }, + "RNT805": { + "product_code": "PRD41", + "units_rented": 9, + "price_per_day": 8, + "rental_start": "3/8/18", + "rental_end": "4/24/18" + }, + "RNT806": { + "product_code": "PRD9", + "units_rented": 3, + "price_per_day": 32, + "rental_start": "10/24/16", + "rental_end": "11/2/16" + }, + "RNT807": { + "product_code": "PRD12", + "units_rented": 7, + "price_per_day": 26, + "rental_start": "4/3/18", + "rental_end": "7/19/17" + }, + "RNT808": { + "product_code": "PRD67", + "units_rented": 9, + "price_per_day": 10, + "rental_start": "7/25/17", + "rental_end": "12/15/16" + }, + "RNT809": { + "product_code": "PRD18", + "units_rented": 3, + "price_per_day": 17, + "rental_start": "12/4/17", + "rental_end": "4/7/17" + }, + "RNT810": { + "product_code": "PRD47", + "units_rented": 7, + "price_per_day": 29, + "rental_start": "9/3/16", + "rental_end": "10/26/18" + }, + "RNT811": { + "product_code": "PRD92", + "units_rented": 2, + "price_per_day": 14, + "rental_start": "1/23/16", + "rental_end": "10/25/16" + }, + "RNT812": { + "product_code": "PRD23", + "units_rented": 8, + "price_per_day": 26, + "rental_start": "10/25/16", + "rental_end": "8/18/16" + }, + "RNT813": { + "product_code": "PRD11", + "units_rented": 9, + "price_per_day": 8, + "rental_start": "6/6/16", + "rental_end": "12/14/18" + }, + "RNT814": { + "product_code": "PRD32", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "5/16/18", + "rental_end": "5/3/17" + }, + "RNT815": { + "product_code": "PRD58", + "units_rented": 7, + "price_per_day": 39, + "rental_start": "11/29/17", + "rental_end": "3/26/17" + }, + "RNT816": { + "product_code": "PRD72", + "units_rented": 8, + "price_per_day": 8, + "rental_start": "12/20/17", + "rental_end": "7/6/17" + }, + "RNT817": { + "product_code": "PRD66", + "units_rented": 7, + "price_per_day": 36, + "rental_start": "11/27/18", + "rental_end": "2/11/16" + }, + "RNT818": { + "product_code": "PRD36", + "units_rented": 10, + "price_per_day": 40, + "rental_start": "11/13/17", + "rental_end": "5/13/16" + }, + "RNT819": { + "product_code": "PRD84", + "units_rented": 7, + "price_per_day": 20, + "rental_start": "12/7/17", + "rental_end": "9/25/17" + }, + "RNT820": { + "product_code": "PRD97", + "units_rented": 2, + "price_per_day": 10, + "rental_start": "5/3/16", + "rental_end": "4/25/16" + }, + "RNT821": { + "product_code": "PRD79", + "units_rented": 8, + "price_per_day": 9, + "rental_start": "3/29/17", + "rental_end": "10/12/18" + }, + "RNT822": { + "product_code": "PRD26", + "units_rented": 9, + "price_per_day": 22, + "rental_start": "12/15/17", + "rental_end": "8/11/17" + }, + "RNT823": { + "product_code": "PRD98", + "units_rented": 7, + "price_per_day": 5, + "rental_start": "1/12/17", + "rental_end": "9/15/17" + }, + "RNT824": { + "product_code": "PRD86", + "units_rented": 6, + "price_per_day": 27, + "rental_start": "2/5/16", + "rental_end": "10/23/17" + }, + "RNT825": { + "product_code": "PRD67", + "units_rented": 7, + "price_per_day": 19, + "rental_start": "3/18/18", + "rental_end": "11/25/17" + }, + "RNT826": { + "product_code": "PRD61", + "units_rented": 6, + "price_per_day": 11, + "rental_start": "3/6/17", + "rental_end": "4/2/18" + }, + "RNT827": { + "product_code": "PRD64", + "units_rented": 10, + "price_per_day": 9, + "rental_start": "6/25/16", + "rental_end": "12/17/16" + }, + "RNT828": { + "product_code": "PRD7", + "units_rented": 4, + "price_per_day": 30, + "rental_start": "7/24/16", + "rental_end": "6/29/18" + }, + "RNT829": { + "product_code": "PRD3", + "units_rented": 3, + "price_per_day": 25, + "rental_start": "6/5/16", + "rental_end": "8/28/17" + }, + "RNT830": { + "product_code": "PRD53", + "units_rented": 10, + "price_per_day": 20, + "rental_start": "8/18/16", + "rental_end": "11/8/16" + }, + "RNT831": { + "product_code": "PRD10", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "2/28/17", + "rental_end": "2/25/17" + }, + "RNT832": { + "product_code": "PRD42", + "units_rented": 9, + "price_per_day": 13, + "rental_start": "4/7/16", + "rental_end": "12/11/18" + }, + "RNT833": { + "product_code": "PRD47", + "units_rented": 8, + "price_per_day": 26, + "rental_start": "5/16/16", + "rental_end": "6/23/18" + }, + "RNT834": { + "product_code": "PRD51", + "units_rented": 5, + "price_per_day": 39, + "rental_start": "10/28/16", + "rental_end": "10/5/18" + }, + "RNT835": { + "product_code": "PRD2", + "units_rented": 6, + "price_per_day": 22, + "rental_start": "8/24/17", + "rental_end": "1/8/16" + }, + "RNT836": { + "product_code": "PRD32", + "units_rented": 4, + "price_per_day": 20, + "rental_start": "7/14/16", + "rental_end": "7/9/16" + }, + "RNT837": { + "product_code": "PRD82", + "units_rented": 4, + "price_per_day": 8, + "rental_start": "7/28/17", + "rental_end": "10/28/17" + }, + "RNT838": { + "product_code": "PRD74", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "9/18/16", + "rental_end": "10/12/18" + }, + "RNT839": { + "product_code": "PRD67", + "units_rented": 1, + "price_per_day": 9, + "rental_start": "12/21/18", + "rental_end": "6/25/18" + }, + "RNT840": { + "product_code": "PRD63", + "units_rented": 10, + "price_per_day": 19, + "rental_start": "11/1/18", + "rental_end": "2/4/17" + }, + "RNT841": { + "product_code": "PRD33", + "units_rented": 7, + "price_per_day": 19, + "rental_start": "5/11/16", + "rental_end": "7/27/17" + }, + "RNT842": { + "product_code": "PRD91", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "10/16/17", + "rental_end": "4/16/16" + }, + "RNT843": { + "product_code": "PRD79", + "units_rented": 0, + "price_per_day": 34, + "rental_start": "11/7/17", + "rental_end": "6/26/16" + }, + "RNT844": { + "product_code": "PRD26", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "4/14/18", + "rental_end": "9/9/17" + }, + "RNT845": { + "product_code": "PRD81", + "units_rented": 10, + "price_per_day": 32, + "rental_start": "4/6/16", + "rental_end": "7/15/17" + }, + "RNT846": { + "product_code": "PRD89", + "units_rented": 2, + "price_per_day": 27, + "rental_start": "9/8/17", + "rental_end": "6/29/16" + }, + "RNT847": { + "product_code": "PRD88", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "10/19/18", + "rental_end": "3/7/18" + }, + "RNT848": { + "product_code": "PRD72", + "units_rented": 7, + "price_per_day": 28, + "rental_start": "8/23/17", + "rental_end": "11/4/17" + }, + "RNT849": { + "product_code": "PRD58", + "units_rented": 7, + "price_per_day": 6, + "rental_start": "7/19/18", + "rental_end": "8/18/16" + }, + "RNT850": { + "product_code": "PRD95", + "units_rented": 8, + "price_per_day": 38, + "rental_start": "3/9/16", + "rental_end": "9/11/16" + }, + "RNT851": { + "product_code": "PRD8", + "units_rented": 5, + "price_per_day": 23, + "rental_start": "3/18/17", + "rental_end": "5/7/18" + }, + "RNT852": { + "product_code": "PRD50", + "units_rented": 8, + "price_per_day": 35, + "rental_start": "7/31/16", + "rental_end": "9/20/17" + }, + "RNT853": { + "product_code": "PRD88", + "units_rented": 4, + "price_per_day": 15, + "rental_start": "5/14/18", + "rental_end": "2/9/16" + }, + "RNT854": { + "product_code": "PRD84", + "units_rented": 8, + "price_per_day": 39, + "rental_start": "8/11/16", + "rental_end": "12/2/18" + }, + "RNT855": { + "product_code": "PRD28", + "units_rented": 2, + "price_per_day": 23, + "rental_start": "10/6/18", + "rental_end": "6/16/18" + }, + "RNT856": { + "product_code": "PRD81", + "units_rented": 5, + "price_per_day": 23, + "rental_start": "3/6/17", + "rental_end": "10/14/17" + }, + "RNT857": { + "product_code": "PRD20", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "6/17/17", + "rental_end": "7/27/17" + }, + "RNT858": { + "product_code": "PRD61", + "units_rented": 6, + "price_per_day": 25, + "rental_start": "8/15/18", + "rental_end": "6/7/18" + }, + "RNT859": { + "product_code": "PRD48", + "units_rented": 1, + "price_per_day": 12, + "rental_start": "6/1/16", + "rental_end": "10/5/16" + }, + "RNT860": { + "product_code": "PRD22", + "units_rented": 5, + "price_per_day": 10, + "rental_start": "5/5/18", + "rental_end": "12/16/18" + }, + "RNT861": { + "product_code": "PRD52", + "units_rented": 5, + "price_per_day": 24, + "rental_start": "1/30/18", + "rental_end": "9/12/16" + }, + "RNT862": { + "product_code": "PRD94", + "units_rented": 2, + "price_per_day": 24, + "rental_start": "5/4/16", + "rental_end": "5/28/16" + }, + "RNT863": { + "product_code": "PRD42", + "units_rented": 2, + "price_per_day": 24, + "rental_start": "11/5/16", + "rental_end": "3/31/16" + }, + "RNT864": { + "product_code": "PRD53", + "units_rented": 6, + "price_per_day": 12, + "rental_start": "1/20/18", + "rental_end": "1/12/18" + }, + "RNT865": { + "product_code": "PRD84", + "units_rented": 3, + "price_per_day": 24, + "rental_start": "1/16/18", + "rental_end": "4/14/18" + }, + "RNT866": { + "product_code": "PRD57", + "units_rented": 9, + "price_per_day": 38, + "rental_start": "1/1/18", + "rental_end": "5/7/17" + }, + "RNT867": { + "product_code": "PRD60", + "units_rented": 7, + "price_per_day": 19, + "rental_start": "6/14/17", + "rental_end": "1/19/17" + }, + "RNT868": { + "product_code": "PRD14", + "units_rented": 5, + "price_per_day": 37, + "rental_start": "12/10/16", + "rental_end": "5/26/17" + }, + "RNT869": { + "product_code": "PRD74", + "units_rented": 10, + "price_per_day": 26, + "rental_start": "9/27/17", + "rental_end": "12/2/16" + }, + "RNT870": { + "product_code": "PRD9", + "units_rented": 7, + "price_per_day": 7, + "rental_start": "9/13/16", + "rental_end": "11/26/18" + }, + "RNT871": { + "product_code": "PRD25", + "units_rented": 7, + "price_per_day": 29, + "rental_start": "4/30/17", + "rental_end": "2/20/17" + }, + "RNT872": { + "product_code": "PRD26", + "units_rented": 8, + "price_per_day": 26, + "rental_start": "1/13/16", + "rental_end": "5/7/17" + }, + "RNT873": { + "product_code": "PRD16", + "units_rented": 3, + "price_per_day": 5, + "rental_start": "2/8/18", + "rental_end": "11/24/17" + }, + "RNT874": { + "product_code": "PRD83", + "units_rented": 9, + "price_per_day": 38, + "rental_start": "8/11/18", + "rental_end": "8/8/18" + }, + "RNT875": { + "product_code": "PRD96", + "units_rented": 8, + "price_per_day": 15, + "rental_start": "6/4/16", + "rental_end": "7/24/16" + }, + "RNT876": { + "product_code": "PRD60", + "units_rented": 4, + "price_per_day": 26, + "rental_start": "4/30/17", + "rental_end": "9/20/16" + }, + "RNT877": { + "product_code": "PRD43", + "units_rented": 3, + "price_per_day": 14, + "rental_start": "12/27/16", + "rental_end": "8/1/18" + }, + "RNT878": { + "product_code": "PRD72", + "units_rented": 3, + "price_per_day": 8, + "rental_start": "8/15/18", + "rental_end": "8/25/18" + }, + "RNT879": { + "product_code": "PRD44", + "units_rented": 5, + "price_per_day": 24, + "rental_start": "5/5/18", + "rental_end": "6/11/16" + }, + "RNT880": { + "product_code": "PRD60", + "units_rented": 7, + "price_per_day": 29, + "rental_start": "7/10/17", + "rental_end": "8/30/17" + }, + "RNT881": { + "product_code": "PRD97", + "units_rented": 7, + "price_per_day": 8, + "rental_start": "3/16/17", + "rental_end": "3/30/18" + }, + "RNT882": { + "product_code": "PRD3", + "units_rented": 6, + "price_per_day": 28, + "rental_start": "1/27/18", + "rental_end": "4/13/16" + }, + "RNT883": { + "product_code": "PRD28", + "units_rented": 6, + "price_per_day": 19, + "rental_start": "6/14/18", + "rental_end": "11/20/17" + }, + "RNT884": { + "product_code": "PRD1", + "units_rented": 4, + "price_per_day": 11, + "rental_start": "12/3/16", + "rental_end": "5/1/16" + }, + "RNT885": { + "product_code": "PRD3", + "units_rented": 1, + "price_per_day": 15, + "rental_start": "1/28/17", + "rental_end": "2/10/18" + }, + "RNT886": { + "product_code": "PRD33", + "units_rented": 2, + "price_per_day": 24, + "rental_start": "1/24/17", + "rental_end": "10/23/16" + }, + "RNT887": { + "product_code": "PRD81", + "units_rented": 3, + "price_per_day": 32, + "rental_start": "4/14/17", + "rental_end": "7/4/18" + }, + "RNT888": { + "product_code": "PRD56", + "units_rented": 9, + "price_per_day": 13, + "rental_start": "12/11/17", + "rental_end": "6/16/18" + }, + "RNT889": { + "product_code": "PRD73", + "units_rented": 10, + "price_per_day": 21, + "rental_start": "2/2/18", + "rental_end": "11/30/18" + }, + "RNT890": { + "product_code": "PRD91", + "units_rented": 6, + "price_per_day": 8, + "rental_start": "6/12/18", + "rental_end": "3/21/16" + }, + "RNT891": { + "product_code": "PRD79", + "units_rented": 1, + "price_per_day": 28, + "rental_start": "12/10/16", + "rental_end": "6/24/18" + }, + "RNT892": { + "product_code": "PRD6", + "units_rented": 3, + "price_per_day": 8, + "rental_start": "3/29/17", + "rental_end": "11/20/16" + }, + "RNT893": { + "product_code": "PRD20", + "units_rented": 2, + "price_per_day": 26, + "rental_start": "8/4/17", + "rental_end": "10/27/16" + }, + "RNT894": { + "product_code": "PRD29", + "units_rented": 5, + "price_per_day": 13, + "rental_start": "3/6/17", + "rental_end": "12/7/16" + }, + "RNT895": { + "product_code": "PRD9", + "units_rented": 6, + "price_per_day": 40, + "rental_start": "7/6/18", + "rental_end": "1/4/16" + }, + "RNT896": { + "product_code": "PRD74", + "units_rented": 4, + "price_per_day": 30, + "rental_start": "10/9/17", + "rental_end": "7/7/17" + }, + "RNT897": { + "product_code": "PRD48", + "units_rented": 5, + "price_per_day": 26, + "rental_start": "1/28/16", + "rental_end": "7/7/16" + }, + "RNT898": { + "product_code": "PRD7", + "units_rented": 2, + "price_per_day": 31, + "rental_start": "8/30/17", + "rental_end": "11/18/16" + }, + "RNT899": { + "product_code": "PRD67", + "units_rented": 9, + "price_per_day": 6, + "rental_start": "2/24/16", + "rental_end": "7/15/16" + }, + "RNT900": { + "product_code": "PRD45", + "units_rented": 9, + "price_per_day": 21, + "rental_start": "5/10/17", + "rental_end": "6/28/18" + }, + "RNT901": { + "product_code": "PRD69", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "4/8/17", + "rental_end": "11/19/16" + }, + "RNT902": { + "product_code": "PRD98", + "units_rented": 9, + "price_per_day": 21, + "rental_start": "1/10/17", + "rental_end": "4/3/17" + }, + "RNT903": { + "product_code": "PRD55", + "units_rented": 8, + "price_per_day": 14, + "rental_start": "4/22/18", + "rental_end": "12/26/17" + }, + "RNT904": { + "product_code": "PRD67", + "units_rented": 8, + "price_per_day": 9, + "rental_start": "2/18/17", + "rental_end": "3/15/17" + }, + "RNT905": { + "product_code": "PRD77", + "units_rented": 7, + "price_per_day": 27, + "rental_start": "9/6/17", + "rental_end": "8/21/17" + }, + "RNT906": { + "product_code": "PRD67", + "units_rented": 7, + "price_per_day": 16, + "rental_start": "2/9/16", + "rental_end": "5/13/16" + }, + "RNT907": { + "product_code": "PRD44", + "units_rented": 10, + "price_per_day": 5, + "rental_start": "3/5/17", + "rental_end": "9/9/17" + }, + "RNT908": { + "product_code": "PRD55", + "units_rented": 2, + "price_per_day": 27, + "rental_start": "3/6/16", + "rental_end": "5/25/17" + }, + "RNT909": { + "product_code": "PRD52", + "units_rented": 3, + "price_per_day": 15, + "rental_start": "5/23/18", + "rental_end": "5/17/16" + }, + "RNT910": { + "product_code": "PRD78", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "6/7/17", + "rental_end": "6/23/17" + }, + "RNT911": { + "product_code": "PRD55", + "units_rented": 6, + "price_per_day": 20, + "rental_start": "10/14/16", + "rental_end": "1/17/16" + }, + "RNT912": { + "product_code": "PRD54", + "units_rented": 6, + "price_per_day": 22, + "rental_start": "11/20/18", + "rental_end": "9/5/16" + }, + "RNT913": { + "product_code": "PRD33", + "units_rented": 9, + "price_per_day": 7, + "rental_start": "1/30/16", + "rental_end": "5/26/17" + }, + "RNT914": { + "product_code": "PRD56", + "units_rented": 3, + "price_per_day": 38, + "rental_start": "7/4/18", + "rental_end": "7/3/16" + }, + "RNT915": { + "product_code": "PRD35", + "units_rented": 1, + "price_per_day": 16, + "rental_start": "8/9/18", + "rental_end": "12/19/17" + }, + "RNT916": { + "product_code": "PRD81", + "units_rented": 2, + "price_per_day": 25, + "rental_start": "3/6/16", + "rental_end": "12/8/18" + }, + "RNT917": { + "product_code": "PRD75", + "units_rented": 5, + "price_per_day": 33, + "rental_start": "2/17/17", + "rental_end": "5/30/16" + }, + "RNT918": { + "product_code": "PRD0", + "units_rented": 2, + "price_per_day": 39, + "rental_start": "8/10/18", + "rental_end": "7/20/18" + }, + "RNT919": { + "product_code": "PRD2", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "4/17/18", + "rental_end": "2/25/17" + }, + "RNT920": { + "product_code": "PRD9", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "2/17/16", + "rental_end": "12/25/18" + }, + "RNT921": { + "product_code": "PRD81", + "units_rented": 4, + "price_per_day": 30, + "rental_start": "3/11/17", + "rental_end": "7/11/18" + }, + "RNT922": { + "product_code": "PRD3", + "units_rented": 6, + "price_per_day": 5, + "rental_start": "1/20/18", + "rental_end": "6/13/17" + }, + "RNT923": { + "product_code": "PRD47", + "units_rented": 10, + "price_per_day": 23, + "rental_start": "11/15/16", + "rental_end": "9/10/17" + }, + "RNT924": { + "product_code": "PRD79", + "units_rented": 9, + "price_per_day": 31, + "rental_start": "5/12/18", + "rental_end": "4/3/16" + }, + "RNT925": { + "product_code": "PRD72", + "units_rented": 10, + "price_per_day": 31, + "rental_start": "1/15/17", + "rental_end": "6/26/18" + }, + "RNT926": { + "product_code": "PRD44", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "9/8/17", + "rental_end": "4/12/17" + }, + "RNT927": { + "product_code": "PRD61", + "units_rented": 3, + "price_per_day": 19, + "rental_start": "8/17/17", + "rental_end": "7/18/17" + }, + "RNT928": { + "product_code": "PRD66", + "units_rented": 3, + "price_per_day": 11, + "rental_start": "10/10/17", + "rental_end": "4/1/16" + }, + "RNT929": { + "product_code": "PRD40", + "units_rented": 10, + "price_per_day": 8, + "rental_start": "12/6/16", + "rental_end": "12/2/17" + }, + "RNT930": { + "product_code": "PRD50", + "units_rented": 4, + "price_per_day": 32, + "rental_start": "1/11/17", + "rental_end": "8/4/16" + }, + "RNT931": { + "product_code": "PRD94", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "3/17/18", + "rental_end": "11/24/16" + }, + "RNT932": { + "product_code": "PRD63", + "units_rented": 3, + "price_per_day": 40, + "rental_start": "5/15/18", + "rental_end": "4/30/16" + }, + "RNT933": { + "product_code": "PRD57", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "4/4/16", + "rental_end": "7/31/16" + }, + "RNT934": { + "product_code": "PRD6", + "units_rented": 10, + "price_per_day": 36, + "rental_start": "10/21/16", + "rental_end": "12/15/18" + }, + "RNT935": { + "product_code": "PRD97", + "units_rented": 5, + "price_per_day": 20, + "rental_start": "3/2/18", + "rental_end": "2/21/18" + }, + "RNT936": { + "product_code": "PRD82", + "units_rented": 5, + "price_per_day": 29, + "rental_start": "9/30/16", + "rental_end": "3/11/17" + }, + "RNT937": { + "product_code": "PRD57", + "units_rented": 10, + "price_per_day": 19, + "rental_start": "3/27/17", + "rental_end": "3/14/17" + }, + "RNT938": { + "product_code": "PRD6", + "units_rented": 5, + "price_per_day": 36, + "rental_start": "6/30/17", + "rental_end": "8/7/16" + }, + "RNT939": { + "product_code": "PRD94", + "units_rented": 1, + "price_per_day": 33, + "rental_start": "12/10/17", + "rental_end": "3/23/16" + }, + "RNT940": { + "product_code": "PRD2", + "units_rented": 6, + "price_per_day": 13, + "rental_start": "10/23/16", + "rental_end": "10/15/16" + }, + "RNT941": { + "product_code": "PRD85", + "units_rented": 8, + "price_per_day": 40, + "rental_start": "8/25/16", + "rental_end": "3/27/17" + }, + "RNT942": { + "product_code": "PRD29", + "units_rented": 3, + "price_per_day": 35, + "rental_start": "4/7/17", + "rental_end": "2/21/17" + }, + "RNT943": { + "product_code": "PRD78", + "units_rented": 1, + "price_per_day": 35, + "rental_start": "7/19/17", + "rental_end": "2/10/16" + }, + "RNT944": { + "product_code": "PRD26", + "units_rented": 9, + "price_per_day": 18, + "rental_start": "7/19/18", + "rental_end": "7/22/17" + }, + "RNT945": { + "product_code": "PRD94", + "units_rented": 5, + "price_per_day": 28, + "rental_start": "9/30/16", + "rental_end": "11/10/16" + }, + "RNT946": { + "product_code": "PRD81", + "units_rented": 4, + "price_per_day": 39, + "rental_start": "11/12/17", + "rental_end": "8/19/17" + }, + "RNT947": { + "product_code": "PRD72", + "units_rented": 4, + "price_per_day": 8, + "rental_start": "11/26/16", + "rental_end": "9/11/16" + }, + "RNT948": { + "product_code": "PRD90", + "units_rented": 8, + "price_per_day": 7, + "rental_start": "11/30/18", + "rental_end": "5/9/17" + }, + "RNT949": { + "product_code": "PRD50", + "units_rented": 4, + "price_per_day": 21, + "rental_start": "8/30/16", + "rental_end": "1/19/16" + }, + "RNT950": { + "product_code": "PRD64", + "units_rented": 3, + "price_per_day": 11, + "rental_start": "7/25/17", + "rental_end": "10/6/18" + }, + "RNT951": { + "product_code": "PRD99", + "units_rented": 2, + "price_per_day": 5, + "rental_start": "8/27/18", + "rental_end": "12/16/16" + }, + "RNT952": { + "product_code": "PRD70", + "units_rented": 7, + "price_per_day": 28, + "rental_start": "8/21/17", + "rental_end": "9/21/17" + }, + "RNT953": { + "product_code": "PRD41", + "units_rented": 5, + "price_per_day": 38, + "rental_start": "3/17/16", + "rental_end": "11/16/18" + }, + "RNT954": { + "product_code": "PRD27", + "units_rented": 3, + "price_per_day": 21, + "rental_start": "4/10/16", + "rental_end": "10/21/16" + }, + "RNT955": { + "product_code": "PRD74", + "units_rented": 7, + "price_per_day": 35, + "rental_start": "10/15/17", + "rental_end": "7/9/17" + }, + "RNT956": { + "product_code": "PRD43", + "units_rented": 6, + "price_per_day": 16, + "rental_start": "5/17/16", + "rental_end": "2/29/16" + }, + "RNT957": { + "product_code": "PRD28", + "units_rented": 9, + "price_per_day": 30, + "rental_start": "6/14/18", + "rental_end": "11/1/17" + }, + "RNT958": { + "product_code": "PRD82", + "units_rented": 10, + "price_per_day": 24, + "rental_start": "6/21/17", + "rental_end": "11/13/16" + }, + "RNT959": { + "product_code": "PRD92", + "units_rented": 1, + "price_per_day": 19, + "rental_start": "2/8/17", + "rental_end": "7/21/16" + }, + "RNT960": { + "product_code": "PRD30", + "units_rented": 6, + "price_per_day": 22, + "rental_start": "3/1/18", + "rental_end": "10/22/16" + }, + "RNT961": { + "product_code": "PRD67", + "units_rented": 2, + "price_per_day": 14, + "rental_start": "5/14/18", + "rental_end": "3/19/18" + }, + "RNT962": { + "product_code": "PRD27", + "units_rented": 7, + "price_per_day": 19, + "rental_start": "8/20/17", + "rental_end": "6/25/17" + }, + "RNT963": { + "product_code": "PRD20", + "units_rented": 7, + "price_per_day": 16, + "rental_start": "1/16/17", + "rental_end": "12/13/16" + }, + "RNT964": { + "product_code": "PRD97", + "units_rented": 2, + "price_per_day": 11, + "rental_start": "1/25/16", + "rental_end": "3/26/16" + }, + "RNT965": { + "product_code": "PRD19", + "units_rented": 10, + "price_per_day": 30, + "rental_start": "12/15/17", + "rental_end": "10/13/17" + }, + "RNT966": { + "product_code": "PRD60", + "units_rented": 9, + "price_per_day": 22, + "rental_start": "5/17/17", + "rental_end": "6/25/18" + }, + "RNT967": { + "product_code": "PRD14", + "units_rented": 5, + "price_per_day": 26, + "rental_start": "10/18/18", + "rental_end": "4/6/17" + }, + "RNT968": { + "product_code": "PRD82", + "units_rented": 7, + "price_per_day": 35, + "rental_start": "6/11/16", + "rental_end": "1/17/17" + }, + "RNT969": { + "product_code": "PRD77", + "units_rented": 1, + "price_per_day": 36, + "rental_start": "6/28/18", + "rental_end": "5/27/16" + }, + "RNT970": { + "product_code": "PRD61", + "units_rented": 1, + "price_per_day": 22, + "rental_start": "2/26/18", + "rental_end": "4/19/16" + }, + "RNT971": { + "product_code": "PRD78", + "units_rented": 5, + "price_per_day": 20, + "rental_start": "11/20/17", + "rental_end": "1/13/17" + }, + "RNT972": { + "product_code": "PRD6", + "units_rented": 3, + "price_per_day": 40, + "rental_start": "4/2/17", + "rental_end": "8/24/18" + }, + "RNT973": { + "product_code": "PRD11", + "units_rented": 9, + "price_per_day": 14, + "rental_start": "9/13/17", + "rental_end": "4/28/18" + }, + "RNT974": { + "product_code": "PRD66", + "units_rented": 6, + "price_per_day": 30, + "rental_start": "10/23/18", + "rental_end": "2/28/18" + }, + "RNT975": { + "product_code": "PRD77", + "units_rented": 7, + "price_per_day": 39, + "rental_start": "5/9/16", + "rental_end": "5/26/16" + }, + "RNT976": { + "product_code": "PRD42", + "units_rented": 5, + "price_per_day": 32, + "rental_start": "1/27/16", + "rental_end": "8/5/16" + }, + "RNT977": { + "product_code": "PRD23", + "units_rented": 8, + "price_per_day": 37, + "rental_start": "4/5/17", + "rental_end": "10/10/16" + }, + "RNT978": { + "product_code": "PRD57", + "units_rented": 3, + "price_per_day": 39, + "rental_start": "1/4/16", + "rental_end": "11/15/16" + }, + "RNT979": { + "product_code": "PRD48", + "units_rented": 4, + "price_per_day": 5, + "rental_start": "9/23/17", + "rental_end": "4/16/16" + }, + "RNT980": { + "product_code": "PRD66", + "units_rented": 5, + "price_per_day": 40, + "rental_start": "11/16/17", + "rental_end": "12/7/17" + }, + "RNT981": { + "product_code": "PRD76", + "units_rented": 10, + "price_per_day": 18, + "rental_start": "2/28/17", + "rental_end": "2/2/18" + }, + "RNT982": { + "product_code": "PRD39", + "units_rented": 10, + "price_per_day": 7, + "rental_start": "11/3/16", + "rental_end": "3/16/16" + }, + "RNT983": { + "product_code": "PRD46", + "units_rented": 2, + "price_per_day": 29, + "rental_start": "11/11/16", + "rental_end": "1/16/16" + }, + "RNT984": { + "product_code": "PRD48", + "units_rented": 7, + "price_per_day": 17, + "rental_start": "10/8/17", + "rental_end": "11/26/18" + }, + "RNT985": { + "product_code": "PRD63", + "units_rented": 1, + "price_per_day": 14, + "rental_start": "11/8/16", + "rental_end": "6/30/16" + }, + "RNT986": { + "product_code": "PRD40", + "units_rented": 2, + "price_per_day": 31, + "rental_start": "11/20/18", + "rental_end": "3/11/16" + }, + "RNT987": { + "product_code": "PRD23", + "units_rented": 7, + "price_per_day": 34, + "rental_start": "9/10/17", + "rental_end": "2/28/16" + }, + "RNT988": { + "product_code": "PRD66", + "units_rented": 10, + "price_per_day": 33, + "rental_start": "3/8/18", + "rental_end": "8/22/18" + }, + "RNT989": { + "product_code": "PRD19", + "units_rented": 10, + "price_per_day": 30, + "rental_start": "10/25/18", + "rental_end": "4/7/16" + }, + "RNT990": { + "product_code": "PRD9", + "units_rented": 9, + "price_per_day": 7, + "rental_start": "5/7/16", + "rental_end": "4/24/18" + }, + "RNT991": { + "product_code": "PRD71", + "units_rented": 9, + "price_per_day": 38, + "rental_start": "6/17/16", + "rental_end": "11/18/16" + }, + "RNT992": { + "product_code": "PRD68", + "units_rented": 5, + "price_per_day": 37, + "rental_start": "3/10/18", + "rental_end": "9/8/18" + }, + "RNT993": { + "product_code": "PRD87", + "units_rented": 8, + "price_per_day": 24, + "rental_start": "5/26/16", + "rental_end": "12/10/17" + }, + "RNT994": { + "product_code": "PRD42", + "units_rented": 5, + "price_per_day": 30, + "rental_start": "6/4/17", + "rental_end": "1/2/17" + }, + "RNT995": { + "product_code": "PRD0", + "units_rented": 10, + "price_per_day": 10, + "rental_start": "9/7/16", + "rental_end": "1/28/18" + }, + "RNT996": { + "product_code": "PRD4", + "units_rented": 6, + "price_per_day": 40, + "rental_start": "7/5/16", + "rental_end": "1/25/18" + }, + "RNT997": { + "product_code": "PRD30", + "units_rented": 1, + "price_per_day": 11, + "rental_start": "4/25/16", + "rental_end": "1/29/18" + }, + "RNT998": { + "product_code": "PRD73", + "units_rented": 7, + "price_per_day": 30, + "rental_start": "9/2/18", + "rental_end": "4/14/16" + }, + "RNT999": { + "product_code": "PRD69", + "units_rented": 8, + "price_per_day": 36, + "rental_start": "10/12/18", + "rental_end": "10/2/16" + } +} \ No newline at end of file diff --git a/students/Justin_Jameson/lesson09/assignment/src/testing deco.py b/students/Justin_Jameson/lesson09/assignment/src/testing deco.py new file mode 100644 index 0000000..52da4e4 --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/testing deco.py @@ -0,0 +1,35 @@ +import logging +import functools + +logging.basicConfig(filename='example.log', level=logging.DEBUG) + +do_debug = input('Debug? Y/N: ') + +def debug(func): + """Print the function signature and return value""" + if do_debug.lower() == 'y': + @functools.wraps(func) + def wrapper_debug(*args, **kwargs): + args_repr = [repr(a) for a in args] + kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()] + signature = ", ".join(args_repr + kwargs_repr) + logging.debug(f"Calling {func.__name__}({signature})") + value = func(*args, **kwargs) + logging.info(f"{func.__name__!r} returned {value!r}") + return value + return wrapper_debug + else: + @functools.wraps(func) + def debug_disabled(*args, **kwargs): + # print("Debug has been disabled") + returned_value = func(*args, **kwargs) + return returned_value + + return debug_disabled + + +@debug +def some_function(): + return"Just a funciton" + +print(some_function()) \ No newline at end of file diff --git a/students/Justin_Jameson/lesson09/assignment/src/testing for time.py b/students/Justin_Jameson/lesson09/assignment/src/testing for time.py new file mode 100644 index 0000000..28fc84b --- /dev/null +++ b/students/Justin_Jameson/lesson09/assignment/src/testing for time.py @@ -0,0 +1 @@ +import datetime \ No newline at end of file diff --git a/students/template_student/lesson09/assignment/tests/test_database.py b/students/Justin_Jameson/lesson09/assignment/tests/test_database.py old mode 100755 new mode 100644 similarity index 97% rename from students/template_student/lesson09/assignment/tests/test_database.py rename to students/Justin_Jameson/lesson09/assignment/tests/test_database.py index 3ecf267..5b2cfd7 --- a/students/template_student/lesson09/assignment/tests/test_database.py +++ b/students/Justin_Jameson/lesson09/assignment/tests/test_database.py @@ -1,39 +1,39 @@ -import pytest -import os - -import database as l - -@pytest.fixture -def _show_available_products(): - return { - 'P000001':{'description':'Chair Red leather','product_type':'livingroom','quantity_available':'21'}, - 'P000002':{'description':'Table Oak','product_type':'livingroom','quantity_available':'4'}, - 'P000003':{'description':'Couch Green cloth','product_type':'livingroom','quantity_available':'10'}, - 'P000004':{'description':'Dining table Plastic','product_type':'Kitchen','quantity_available':'23'}, - 'P000005':{'description':'Stool Black ash','product_type':'Kitchen','quantity_available':'12'} - } - -@pytest.fixture -def _show_rentals(): - return { - 'C000001':{'name':'Shea Boehm','address':'3343 Sallie Gateway','phone_number':'508.104.0644','email':'Alexander.Weber@monroe.com'}, - 'C000003':{'name':'Elfrieda Skiles','address':'3180 Mose Row','phone_number':'839)825-0058','email':'Mylene_Smitham@hannah.co.uk'} - } - -def test_import_data(): - dir = os.path.dirname(os.path.abspath(__file__)) - added, errors = l.import_data(dir, "products.csv", "customers.csv", "rentals.csv") - for add in added: - assert isinstance(add, int) - for error in errors: - assert isinstance(error, int) - assert added == (5,11,9) - assert errors == (0,0,0) - -def test_show_available_products(_show_available_products): - students_response = l.show_available_products() - assert students_response == _show_available_products - -def test_show_rentals(_show_rentals): - students_response = l.show_rentals("P000003") - assert students_response == _show_rentals +import pytest +import os + +import database as l + +@pytest.fixture +def _show_available_products(): + return { + 'P000001':{'description':'Chair Red leather','product_type':'livingroom','quantity_available':'21'}, + 'P000002':{'description':'Table Oak','product_type':'livingroom','quantity_available':'4'}, + 'P000003':{'description':'Couch Green cloth','product_type':'livingroom','quantity_available':'10'}, + 'P000004':{'description':'Dining table Plastic','product_type':'Kitchen','quantity_available':'23'}, + 'P000005':{'description':'Stool Black ash','product_type':'Kitchen','quantity_available':'12'} + } + +@pytest.fixture +def _show_rentals(): + return { + 'C000001':{'name':'Shea Boehm','address':'3343 Sallie Gateway','phone_number':'508.104.0644','email':'Alexander.Weber@monroe.com'}, + 'C000003':{'name':'Elfrieda Skiles','address':'3180 Mose Row','phone_number':'839)825-0058','email':'Mylene_Smitham@hannah.co.uk'} + } + +def test_import_data(): + dir = os.path.dirname(os.path.abspath(__file__)) + added, errors = l.import_data(dir, "products.csv", "customers.csv", "rentals.csv") + for add in added: + assert isinstance(add, int) + for error in errors: + assert isinstance(error, int) + assert added == (5,11,9) + assert errors == (0,0,0) + +def test_show_available_products(_show_available_products): + students_response = l.show_available_products() + assert students_response == _show_available_products + +def test_show_rentals(_show_rentals): + students_response = l.show_rentals("P000003") + assert students_response == _show_rentals diff --git a/students/template_student/lesson09/assignment/tests/test_jpgdiscover.py b/students/Justin_Jameson/lesson09/assignment/tests/test_jpgdiscover.py old mode 100755 new mode 100644 similarity index 96% rename from students/template_student/lesson09/assignment/tests/test_jpgdiscover.py rename to students/Justin_Jameson/lesson09/assignment/tests/test_jpgdiscover.py index 826f4fc..20d7a10 --- a/students/template_student/lesson09/assignment/tests/test_jpgdiscover.py +++ b/students/Justin_Jameson/lesson09/assignment/tests/test_jpgdiscover.py @@ -1,21 +1,21 @@ -""" -grade l9 part 3 -""" -import pytest - -import jpgdiscover as sut - -@pytest.fixture -def _test_list_jpg_files(): - """ structure from test """ - return [ - "tests/lesson09/data/furniture/chair", ["metal_chair_back_isometric_400_clr_17527.png"], - "tests/lesson09/data/furniture/chair/couch", ["sofa_400_clr_10056.png"], - "tests/lesson09/data/furniture/table", ["basic_desk_main_400_clr_17523.png", "desk_isometric_back_400_clr_17524.png", "table_with_cloth_400_clr_10664.png"], - "tests/lesson09/data/new", ["chairs_balancing_stacked_400_clr_11525.png", "hotel_room_400_clr_12721.png"], - "tests/lesson09/data/old", ["couple_on_swing_bench_400_clr_12844.png", "sitting_in_chair_relaxing_400_clr_6028.png"]] - -def test_list_jpg_files(_test_list_jpg_files): - """ student geneartes """ - jpgs = sut.list_jpg_files("tests/lesson09/data/") - assert jpgs == _test_list_jpg_files +""" +grade l9 part 3 +""" +import pytest + +import jpgdiscover as sut + +@pytest.fixture +def _test_list_jpg_files(): + """ structure from test """ + return [ + "tests/lesson09/data/furniture/chair", ["metal_chair_back_isometric_400_clr_17527.png"], + "tests/lesson09/data/furniture/chair/couch", ["sofa_400_clr_10056.png"], + "tests/lesson09/data/furniture/table", ["basic_desk_main_400_clr_17523.png", "desk_isometric_back_400_clr_17524.png", "table_with_cloth_400_clr_10664.png"], + "tests/lesson09/data/new", ["chairs_balancing_stacked_400_clr_11525.png", "hotel_room_400_clr_12721.png"], + "tests/lesson09/data/old", ["couple_on_swing_bench_400_clr_12844.png", "sitting_in_chair_relaxing_400_clr_6028.png"]] + +def test_list_jpg_files(_test_list_jpg_files): + """ student geneartes """ + jpgs = sut.list_jpg_files("tests/lesson09/data/") + assert jpgs == _test_list_jpg_files diff --git a/students/template_student/lesson08/activity/README.md b/students/Justin_Jameson/lesson10/activity/README.md similarity index 100% rename from students/template_student/lesson08/activity/README.md rename to students/Justin_Jameson/lesson10/activity/README.md diff --git a/students/template_student/lesson10/assignment/README.md b/students/Justin_Jameson/lesson10/assignment/README.md old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson10/assignment/README.md rename to students/Justin_Jameson/lesson10/assignment/README.md diff --git a/students/template_student/lesson10/assignment/data/customer.csv b/students/Justin_Jameson/lesson10/assignment/data/customer.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson10/assignment/data/customer.csv rename to students/Justin_Jameson/lesson10/assignment/data/customer.csv diff --git a/students/template_student/lesson10/assignment/data/product.csv b/students/Justin_Jameson/lesson10/assignment/data/product.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson10/assignment/data/product.csv rename to students/Justin_Jameson/lesson10/assignment/data/product.csv diff --git a/students/template_student/lesson10/assignment/data/rental.csv b/students/Justin_Jameson/lesson10/assignment/data/rental.csv old mode 100755 new mode 100644 similarity index 100% rename from students/template_student/lesson10/assignment/data/rental.csv rename to students/Justin_Jameson/lesson10/assignment/data/rental.csv diff --git a/students/template_student/lesson08/assignment/pylintrc b/students/Justin_Jameson/lesson10/assignment/pylintrc similarity index 100% rename from students/template_student/lesson08/assignment/pylintrc rename to students/Justin_Jameson/lesson10/assignment/pylintrc diff --git a/students/Justin_Jameson/lesson10/assignment/src/Justin Jameson lesson 10.zip b/students/Justin_Jameson/lesson10/assignment/src/Justin Jameson lesson 10.zip new file mode 100644 index 0000000..e4c0ed4 Binary files /dev/null and b/students/Justin_Jameson/lesson10/assignment/src/Justin Jameson lesson 10.zip differ diff --git a/students/template_student/lesson10/assignment/src/databse.py b/students/Justin_Jameson/lesson10/assignment/src/databse.py similarity index 100% rename from students/template_student/lesson10/assignment/src/databse.py rename to students/Justin_Jameson/lesson10/assignment/src/databse.py diff --git a/students/template_student/lesson01/assignment/inventory_management/electricAppliancesClass.py b/students/template_student/lesson01/assignment/inventory_management/electricAppliancesClass.py deleted file mode 100755 index 291f199..0000000 --- a/students/template_student/lesson01/assignment/inventory_management/electricAppliancesClass.py +++ /dev/null @@ -1,22 +0,0 @@ -# Electric appliances class -from inventoryClass import inventory - -class electricAppliances(inventory): - - def __init__(self, productCode, description, marketPrice, rentalPrice, brand, voltage): - inventory.__init__(self,productCode,description,marketPrice,rentalPrice) # Creates common instance variables from the parent class - - - self.brand = brand - self.voltage = voltage - - def returnAsDictionary(self): - outputDict = {} - outputDict['productCode'] = self.productCode - outputDict['description'] = self.description - outputDict['marketPrice'] = self.marketPrice - outputDict['rentalPrice'] = self.rentalPrice - outputDict['brand'] = self.brand - outputDict['voltage'] = self.voltage - - return outputDict \ No newline at end of file diff --git a/students/template_student/lesson01/assignment/inventory_management/furnitureClass.py b/students/template_student/lesson01/assignment/inventory_management/furnitureClass.py deleted file mode 100755 index 9a98aa7..0000000 --- a/students/template_student/lesson01/assignment/inventory_management/furnitureClass.py +++ /dev/null @@ -1,21 +0,0 @@ -# Furniture class -from inventoryClass import inventory - -class furniture(inventory): - - def __init__(self, productCode, description, marketPrice, rentalPrice, material, size): - inventory.__init__(self,productCode,description,marketPrice,rentalPrice) # Creates common instance variables from the parent class - - self.material = material - self.size = size - - def returnAsDictionary(self): - outputDict = {} - outputDict['productCode'] = self.productCode - outputDict['description'] = self.description - outputDict['marketPrice'] = self.marketPrice - outputDict['rentalPrice'] = self.rentalPrice - outputDict['material'] = self.material - outputDict['size'] = self.size - - return outputDict \ No newline at end of file diff --git a/students/template_student/lesson01/assignment/inventory_management/inventoryClass.py b/students/template_student/lesson01/assignment/inventory_management/inventoryClass.py deleted file mode 100755 index 40c7fd3..0000000 --- a/students/template_student/lesson01/assignment/inventory_management/inventoryClass.py +++ /dev/null @@ -1,17 +0,0 @@ -# Inventory class -class inventory: - - def __init__(self, productCode, description, marketPrice, rentalPrice): - self.productCode = productCode - self.description = description - self.marketPrice = marketPrice - self.rentalPrice = rentalPrice - - def returnAsDictionary(self): - outputDict = {} - outputDict['productCode'] = self.productCode - outputDict['description'] = self.description - outputDict['marketPrice'] = self.marketPrice - outputDict['rentalPrice'] = self.rentalPrice - - return outputDict \ No newline at end of file diff --git a/students/template_student/lesson01/assignment/inventory_management/main.py b/students/template_student/lesson01/assignment/inventory_management/main.py deleted file mode 100755 index 4b82694..0000000 --- a/students/template_student/lesson01/assignment/inventory_management/main.py +++ /dev/null @@ -1,69 +0,0 @@ -# Launches the user interface for the inventory management system -import sys -import market_prices -import inventoryClass -import furnitureClass -import electricAppliancesClass - -def mainMenu(user_prompt=None): - valid_prompts = {"1": addNewItem, - "2": itemInfo, - "q": exitProgram} - options = list(valid_prompts.keys()) - - while user_prompt not in valid_prompts: - options_str = ("{}" + (", {}") * (len(options)-1)).format(*options) - print("Please choose from the following options ({options_str}):") - print("1. Add a new item to the inventory") - print("2. Get item information") - print("q. Quit") - user_prompt = input(">") - return valid_prompts.get(user_prompt) - -def getPrice(itemCode): - print("Get price") - -def addNewItem(): - global fullInventory - itemCode = input("Enter item code: ") - itemDescription = input("Enter item description: ") - itemRentalPrice = input("Enter item rental price: ") - - # Get price from the market prices module - itemPrice = market_prices.get_latest_price(itemCode) - - isFurniture = input("Is this item a piece of furniture? (Y/N): ") - if isFurniture.lower() == "y": - itemMaterial = input("Enter item material: ") - itemSize = input("Enter item size (S,M,L,XL): ") - newItem = furnitureClass.furniture(itemCode,itemDescription,itemPrice,itemRentalPrice,itemMaterial,itemSize) - else: - isElectricAppliance = input("Is this item an electric appliance? (Y/N): ") - if isElectricAppliance.lower() == "y": - itemBrand = input("Enter item brand: ") - itemVoltage = input("Enter item voltage: ") - newItem = electricAppliancesClass.electricAppliances(itemCode,itemDescription,itemPrice,itemRentalPrice,itemBrand,itemVoltage) - else: - newItem = inventoryClass.inventory(itemCode,itemDescription,itemPrice,itemRentalPrice) - fullInventory[itemCode] = newItem.returnAsDictionary() - print("New inventory item added") - - -def itemInfo(): - itemCode = input("Enter item code: ") - if itemCode in fullInventory: - printDict = fullInventory[itemCode] - for k,v in printDict.items(): - print("{}:{}".format(k,v)) - else: - print("Item not found in inventory") - -def exitProgram(): - sys.exit() - -if __name__ == '__main__': - fullInventory = {} - while True: - print(fullInventory) - mainMenu()() - input("Press Enter to continue...........") diff --git a/students/template_student/lesson01/assignment/inventory_management/market_prices.py b/students/template_student/lesson01/assignment/inventory_management/market_prices.py deleted file mode 100755 index a486cc8..0000000 --- a/students/template_student/lesson01/assignment/inventory_management/market_prices.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_latest_price(item_code): - return 24 - # Raise an exception to force the user to Mock its output \ No newline at end of file diff --git a/students/template_student/lesson02/assignment/src/charges_calc.py b/students/template_student/lesson02/assignment/src/charges_calc.py deleted file mode 100755 index 2a4496a..0000000 --- a/students/template_student/lesson02/assignment/src/charges_calc.py +++ /dev/null @@ -1,47 +0,0 @@ -''' -Returns total price paid for individual rentals -''' -import argparse -import json -import datetime -import math - -def parse_cmd_arguments(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-i', '--input', help='input JSON file', required=True) - parser.add_argument('-o', '--output', help='ouput JSON file', required=True) - - return parser.parse_args() - - -def load_rentals_file(filename): - with open(filename) as file: - try: - data = json.load(file) - except: - exit(0) - return data - -def calculate_additional_fields(data): - for value in data.values(): - try: - rental_start = datetime.datetime.strptime(value['rental_start'], '%m/%d/%y') - rental_end = datetime.datetime.strptime(value['rental_end'], '%m/%d/%y') - value['total_days'] = (rental_end - rental_start).days - value['total_price'] = value['total_days'] * value['price_per_day'] - value['sqrt_total_price'] = math.sqrt(value['total_price']) - value['unit_cost'] = value['total_price'] / value['units_rented'] - except: - exit(0) - - return data - -def save_to_json(filename, data): - with open(filename, 'w') as file: - json.dump(data, file) - -if __name__ == "__main__": - args = parse_cmd_arguments() - data = load_rentals_file(args.input) - data = calculate_additional_fields(data) - save_to_json(args.output, data) diff --git a/students/template_student/lesson04/assignment/src/basic_operations.py b/students/template_student/lesson04/assignment/src/basic_operations.py deleted file mode 100755 index e69de29..0000000 diff --git a/students/template_student/lesson05/assignment/src/database.py b/students/template_student/lesson05/assignment/src/database.py deleted file mode 100755 index e69de29..0000000 diff --git a/students/template_student/lesson08/assignment/data/test_items.csv b/students/template_student/lesson08/assignment/data/test_items.csv deleted file mode 100755 index ce43d9b..0000000 --- a/students/template_student/lesson08/assignment/data/test_items.csv +++ /dev/null @@ -1,4 +0,0 @@ -LR01,Small lamp,7.50 -LR02,Television,28.00 -BR07,LED lamp,5.50 -KT08,Basic refrigerator,40.00 \ No newline at end of file diff --git a/students/template_student/lesson08/assignment/src/inventory.py b/students/template_student/lesson08/assignment/src/inventory.py deleted file mode 100755 index e69de29..0000000 diff --git a/students/template_student/lesson09/assignment/src/database.py b/students/template_student/lesson09/assignment/src/database.py deleted file mode 100755 index e69de29..0000000 diff --git a/students/template_student/lesson09/assignment/src/jpgdiscover.py b/students/template_student/lesson09/assignment/src/jpgdiscover.py deleted file mode 100755 index e69de29..0000000