class MyClass(js.JsonSaveable): x = js.Int() y = js.Float() lst = js.List() def __init__(self, x, lst): self.x = x self.lst = lst
class Donor(js.JsonSaveable): _name = js.String() _donations = js.List() def __init__(self, name, donations=None): self.name = name if donations == None: self._donations = [] else: self._donations = list(donations) # self.donations = donations @property def name(self): return self._name @name.setter def name(self, value): self._name = value @property def donations(self): return self._donations def add_donation(self, amount): try: self.donations.append(float(amount)) # Handle error if user doesn't input a valid numerical donation except ValueError: print('Not a valid donation.') prompt_donation(self.name) # Create email to donor thanking them for their generous donation def create_email(self, amount): return '\nDear {},\n\nThank you so much for generous donation of ${}.\n\n\t\t\tSincerely,\n\t\t\tPython Donation Team'.format( self.name, amount) def sum_donations(self): return sum(self.donations) def number_donations(self): return len(self.donations) def avg_donations(self): return self.sum_donations() / self.number_donations() def multiply_donations(self, factor): self._donations = list(map(lambda x: x * factor, self.donations)) return self._donations def filter_donations(self, min_donation=0, max_donation=99999999999999999): self._donations = list( filter(lambda x: int(min_donation) <= x <= int(max_donation), self.donations)) return self._donations
class DonorGroup(js.JsonSaveable): """Donor group initialized with first Donor class Donors are kept in a dictionary created in DonorGroup""" donor_list_js = js.List() donor_dict_js = js.Dict() def __init__(self, donor=None, file_path=None): self.donor_list_js = [donor.fullname_js] self.donor_dict_js = {donor.fullname_js: donor.donations_js} self.file_path = file_path def add_donor(self, new_donor): self.donor_list_js.append(new_donor) self.donor_dict_js[new_donor.fullname_js] = new_donor.donations_js return self.donor_list_js @property def create_report(self): rows = [(donor, sum(self.donor_dict_js[donor]),len(self.donor_dict_js[donor]),np.mean(self.donor_dict_js[donor])) for donor in self.donor_dict_js] #rows.sort(key = takeSecond, reverse = True) print('{:<20s} |{:>15s}|{:>12s} |{:>15s}'.format('Donor Name','Total Given','Num Gifts','Average Gift')) for i in ['{:<20s} ${:15,.2f} {:12d} ${:15,.2f}'.format(*row) for row in rows]: print(i) return "report created" @property def send_letters(self): return self.file_path @send_letters.setter def send_letters(self, letter_dir): self.file_path = letter_dir try: os.chdir(self.file_path) except FileNotFoundError: print("\nNOT A VALID FILE PATH") for donor in self.donor_dict_js: letter_text = f"""Dear {donor}, \n\nThank you for your generous donation of ${sum(self.donor_dict_js[donor]):,.2f}. Thanks to you we will finally be able to begin construction on the children's wing at Dark Place Hospital\n\nYours Truly,\nGarth Marenghi""" with open(donor.replace(" ","_").lower() + '_donations.txt', 'w') as donation_letter: donation_letter.write(letter_text) def challenge(self, factor, min_donation=None, max_donation=None): get_donations = [[globals()[d.split(" ")[0].lower()].fullname, globals()[d.split(" ")[0].lower()].donation] for d in self.donor_list_js] if min_donation and max_donation: filtered_donations = [[d[0], list(filter(lambda x: x >= min_donation and x <= max_donation, d[1]))] for d in get_donations] elif min_donation: filtered_donations = [[d[0], list(filter(lambda x: x >= min_donation, d[1]))] for d in get_donations] elif max_donation: filtered_donations = [[d[0], list(filter(lambda x: x <= max_donation, d[1]))] for d in get_donations] else: filtered_donations = get_donations new_donors = [Donor(d[0], list(map(lambda x: x * factor, d[1]))) for d in filtered_donations] #new donor group created dg_factored = DonorGroup(new_donors[0]) d = 1 while d + 1 <= len(new_donors): dg_factored.add_donor = new_donors[d] d += 1 return dg_factored def projection(self, factor, min_donation = None, max_donation = None): dg_factored = self.challenge(factor, min_donation, max_donation) contribution = sum([sum(dg_factored.donor_dict_js[d]) for d in dg_factored.donor_list_js]) return contribution def __repr__(self): return "Donor Group: {}".format(self.donor_list_js) #load donors from JSON file def load_donors_json(self): with open('donor_db.json','r') as donor_file: donor_db = json.load(donor_file) print('donor db loaded') return donor_db #save donor dict to json file def save_donors_json(self): donors_json = json.dumps(self.donor_dict_js) with open('donor_db.json', 'w') as donor_file: donor_file.write(donors_json) print('JSON file created')
class Donor(js.JsonSaveable): """takes full name and creates donor record need a donor and a donation to create a donor record""" first_js = js.String() last_js = js.String() fullname_js = js.String() donations_js = js.List() def __init__(self, fullname, donations=None): if len(fullname.split(" ")) == 1: first = "Mr/Ms" last = fullname.split(" ")[0] elif len(fullname.split(" ")) == 2: first, last = fullname.split(" ") else: first = fullname.split(" ")[0] last = fullname.split(" ")[len(fullname.split(" "))-1] self.first_js = first self.last_js = last self.fullname_js = fullname if donations: self.donations_js = donations else: self.donations_js = [] @classmethod def add_donation(cls, new_donation): cls.donations_js.append(new_donation) return cls.donations_js @property def sum_donations(self): return sum(self.donations_js) @property def count_donations(self): return len(self.donations_js) @property def avg_donations(self): return sum(self.donations_js) / len(self.donations_js) def thank_you(self): """sends thank you for latest donation""" newest_donation = self.donations_js[len(self.donations_js)-1] thankyou = f"""\nDear {self.first_js}, \n\nThank you for your generous donation of ${newest_donation:,.2f}. Thanks to you, we will finally be able to begin construction on the {self.last_js} Memorial Children's wing at The Dark Place Hospital\n\nYours Truly,\nGarth Marenghi\n""" print(thankyou) def __lt__(self, other): return self.sum_donations < other.sum_donations def __gt__(self, other): return self.sum_donations > other.sum_donations def __eq__(self, other): return self.sum_donations == other.sum_donations def __ne__(self, other): return self.sum_donations != other.sum_donations def __repr__(self): return "Donor Record: {}, {}".format(self.last_js, self.first_js)
class DonorCollection(js.JsonSaveable): _donors = js.List() def __init__(self, donors=None): if donors == None: donors = [] else: self._donors = donors @property def donors(self): return self._donors # Display list of donors by name def donor_list(self): list_donors = '' for donor in self.donors: list_donors += donor.name + '\n' return list_donors # Set donor def set_donor(self, full_name): exists = False # Check if existing donor for donor in self.donors: if donor.name == full_name: exists = True break # Not existing donor, so create new donor if not exists: donor = Donor(full_name) donors.add_donor(donor) return donor # Add new donor to donor collection def add_donor(self, donor): self.donors.append(donor) def sort_on_total_donation(self): return (sorted(self.donors, key=total_donation_key, reverse=True)) # Create report def create_report(self): #Create list of summarized donations so that total can be sorted sorted_donors = donors.sort_on_total_donation() # Print summarized data report = '\nDonor Name | Total Given | Num Gifts | Average Gift\n' report += '-' * 66 + '\n' for donor in sorted_donors: if donor.donations != []: report += f'{donor.name: <27}${donor.sum_donations(): >12.2f}{donor.number_donations(): >12} ${round(donor.avg_donations(),2): >11.2f}\n' print(report) return report # Send letters to everyone def send_letters(self): now = datetime.datetime.now() now = str(now.year) + '-' + str(now.month) + "-" + str(now.day) path = os.getcwd() + '/letters' # Change directory to letters directory, if it doesn't exist, create it try: os.chdir(path) except FileNotFoundError: os.makedirs(path) os.chdir(path) # Loop through each donor and send thank you email try: for donor in self.donors: with open(donor.name + '_' + str(now) + '.txt', 'w') as outfile: print(donor.name) outfile.write(donor.create_email(donor.donations[-1])) print('\nThe thank you emails were sent!') except: print('\nThere was an error sending the thank you emails.') # Apply multiplication factor to each donor list def challenge(self, factor=3, min_donation=0, max_donation=99999999999999): donors_copy = deepcopy(self.donors) for donor in donors_copy: donor.filter_donations(min_donation, max_donation) donor.multiply_donations(factor) return donors_copy @classmethod # Load donors from json file def load_donors(cls): with open('donors.json', 'r') as file: donor_load = json.load(file) donors = cls.from_json_dict(donor_load) print('Donors JSON loaded') return donors @classmethod # Save donors to json file def save_donors(cls): donor_save = donors.to_json() with open('donors.json', 'w') as file: file.write(donor_save) print('Donors JSON saved') return donors