class Donor(): name = String() donations = List() def __init__(self, name, donations=[]): self.name = name self.donations = [] for donation in donations: self.donations.append(donation) def new_donation(self, amount): self.donations.append(amount) def write_note(self, current_donation=0): note = [ "Dear {},\n".format(self.name), '\nThank you for your generous donations \ totaling ${:,}.'.format(self.total_donated), "\nThe money will be put to good use." "\n\nSincerely, \n -The Team" ] if current_donation > 0: curr = ("This donation of ${:,} " "really helps.".format(current_donation)) note.insert(2, curr) return "".join(note) @property def total_donated(self): return sum(self.donations) @property def number_of_donations(self): return len(self.donations) @property def average_donation(self): return sum(self.donations) / len(self.donations) def __str__(self): return "{:17} ${:14,.2f}{:13} ${:13,.2f}".format\ (self.name, self.total_donated, self.number_of_donations, self.average_donation) def __repr__(self): return "Donor(\'{}\', {})".format(self.name, self.donations) def __lt__(self, other): return self.total_donated < other.total_donated def __gt__(self, other): return self.total_donated > other.total_donated def __eq__(self, other): return self.total_donated == other.total_donated def __ne__(self, other): return self.total_donated != other.total_donated
class Donor(): name = String() donations = List() def __init__(self, name, donations=[]): self.name = name self.donations = [] for donation in donations: self.donations.append(donation) def new_donation(self, amount): self.donations.append(amount) def write_note(self, curr_donation=0): note = [ "Dear {},\n".format(self.name), "\nThank you for your generosity to our cause.\n", "You have now given a total of ${:,}.".format(self.tot_given), "\nWe greatly appreciate your contributions!" "\n\nThank you!\nAlex Laws" ] if curr_donation > 0: curr = ("Your recent gift of ${:,} " "is very helpful. ".format(curr_donation)) note.insert(2, curr) return "".join(note) @property def tot_given(self): return sum(self.donations) @property def num_donations(self): return len(self.donations) @property def avg_donation(self): return sum(self.donations) / len(self.donations) def __str__(self): return "{:17} ${:14,.2f} {:13} ${:13,.2f}".format( self.name, self.tot_given, self.num_donations, self.avg_donation) def __repr__(self): return "Donor(\'{}\', {})".format(self.name, self.donations) def __lt__(self, other): return self.tot_given < other.tot_given def __gt__(self, other): return self.tot_given > other.tot_given def __eq__(self, other): return self.tot_given == other.tot_given def __ne__(self, other): return self.tot_given != other.tot_given
class Donor: _name = String() _donations = List() _total_donations = Float() """ An individual donor, consisting of a name, a list of donations and a set of properties for commonly used attributes including total donations, average donations, and number of donations """ def __init__(self, name, donations=None): self._name = name if donations is None: self._donations = [] else: self._donations = donations self._total_donations = 0 for donation in self._donations: self._total_donations += donation @property def total_donations(self): return self._total_donations @property def name(self): return self._name @property def avg_donation(self): return self._total_donations / self.num_donations @property def num_donations(self): return len(self._donations) def add_donation(self, donation): """ Add a new donation entry for this donor :param donation: the new donation amount """ self._donations.append(donation) self._total_donations += donation def create_thank_you(self, donation): """ Prints a thank for you the given donor and amount :param donation: dictionary containing name of the donor to thank and the amount donated :returns: formatted thank you string """ return f"Dear {self.name},\nThank you for your very generous donation of ${donation:.2f}. It \nwill go very far in supporting the Human Fund, \"Money for \nPeople.\"\n{'Sincerely':>40}\n{'Art Vandelay':>50}" def __lt__(self, other): return self.total_donations < other.total_donations def __eq__(self, other): return self.name == other.name and self._donations == other._donations
class Donor_list(): donor_dictionary = List() def __init__(self, *args): self.donor_dictionary = [] for arg in args: self.donor_dictionary.append(arg) def add_donor(self, *args): for arg in args: self.donor_dictionary.append(arg) def check_donor(self, name): donor_exists = False for donor in self.donor_dictionary: if name == donor.name: donor_exists = True return donor_exists def get_donor(self, name): for donor in self.donor_dictionary: if name == donor.name: return donor def sort_donors(self): return sorted(self.donor_dictionary, reverse=True) def donor_report(self): print("\n") print("Donor Name | Total Given | Num Gifts | Average Gift") for donor in self.sort_donors(): print(donor) def save(self, file_name, info): name = "{}.json".format(file_name) with open(name, 'w') as f: f.write(info) print("saved") def __iter__(self): return self def __str__(self): return "\n".join(donor.name for donor in self.donor_dictionary)
class DonorList: donor_dict = List() def __init__(self, *args): self.donor_dict = [] for addition in args: self.donor_dict.append(addition) def add_(self, *args): for donor in args: self.donor_dict.append(donor) def check_(self, chk_name): found_flag = False for donor in self.donor_dict: if chk_name == donor.name: found_flag = True return found_flag def get_(self, name): for donor in self.donor_dict: if name == donor.name: return donor def sort_list(self): return sorted(self.donor_dict, reverse=True) def report(self): print() print( "Donor Name | Total Given | Num Gifts | Average Gift") for donor in self.sort_list(): print(donor) def save_(self, fname, info): name = "{}.json".format(fname) with open(name, 'w') as f: f.write(info) def __iter__(self): return self def __str__(self): return "\n".join(donor.name for donor in self.donor_dict)
class Donor: donor_dict = Dict() donation_list = List() def __init__(self, name, donations): self.name = name self.donor_dict = {} self.donation_list = [] if type(donations) == int or type(donations) == float: self.donation_list.append(round(donations, 2)) elif type(donations) == list: for i in donations: self.donation_list.append(round(i, 2)) else: raise ValueError('You must enter a number for donation amount.') self.donor_dict = {'name': self.name, 'donations': self.donation_list} self.sum_dict = {'name': self.name, 'total': round(sum(self.donation_list, 2)), "num_donations": len(self.donation_list), "avg": round(sum(self.donation_list) / len(self.donation_list), 2)} def append(self, amount): self.donation_list.append(amount) self.donation_list self.sum_dict = {'name': self.name, 'total': round(sum(self.donation_list, 2)), "num_donations": len(self.donation_list), "avg": round(sum(self.donation_list) / len(self.donation_list), 2)} with open('donor_data.json', 'w') as f: data = json.dumps(self.sum_dict) f.write(data) d.add(self.name.lower(), self.sum_dict) @property def avg(self): return round(sum(self.donation_list, 2) / len(self.donation_list)) @property def total(self): return round(sum(self.donation_list)) @property def status(self): return (self.name, self.total, len(self.donation_list), self.avg) def send_thanks(self): letter = 'Thank you {} for your donation in the amount of ${}; it is very generous.'.format(self.name, self.donation_list[-1]) with open('Thank_You - {}.txt'.format(self.name.lower(). replace(' ', '_')), 'w') as f: f.write(letter) print("Your thank you letter has been written to disk.") def __repr__(self): return repr(self.donor_dict)
class Donors: _donors = List() """ A collection of donors """ def __init__(self, donors=None): if donors is None: self._donors = [] else: self._donors = donors def add_donor(self, donor): """ Add a new donor to the donors list :param donor: the new donor to add """ self._donors.append(donor) def list_donors(self): """ Creates a list of the donors by name """ return f"\n{'-'*10} Donors {'-'*10}\n" + '\n'.join( [donor.name for donor in self._donors]) def print_donors(self): """ Prints the list of donors """ print(self.list_donors()) def find_donor(self, name): """ Find a donor by name :param name: the name of the donor to search for :return: The donor if found else None """ for donor in self._donors: if donor.name == name: return donor return None def add_donation(self, name, amount): """ Add a donation. :param name: the name of the donor. :param amount: the amount of the donation.the :returns: the list of donations for the donor """ donor = self.find_donor(name) if donor is None: donor = Donor(name) self.add_donor(donor) amount = float(amount) donor.add_donation(amount) print("\n" + donor.create_thank_you(amount)) return donor def create_report(self): """ Handles the create report menu selection :returns: returns the report string """ header = "\n{:<20}| Total Given | Num Gifts | Average Gift\n".format( "Donor Name") result = header result += f"{'-' * (len(header) - 1)}" donors_list = sorted(self._donors, reverse=True) for donor in donors_list: result += "\n{:<20}| ${:>10.2f} | {:>9} | ${:>11.2f}".format( donor.name, donor.total_donations, donor.num_donations, donor.avg_donation) return result def print_report(self): """ Prints the report """ print(self.create_report()) def mail_everyone(self): """ Handles the mail to everyone menu selection """ for donor in self._donors: with open(donor.name.lower().replace(' ', "_") + ".txt", 'w') as f: f.write(donor.create_thank_you(donor.total_donations)) def save(self, file_name): """ Save the database of donors as a json file """ with open(file_name, 'w') as f: self.to_json(f) def load(self, file_name): """ Loads the database of donors from a json file """ json_donors = "" with open(file_name, 'r') as f: for l in f: json_donors = json_donors + l temp = from_json(json_donors) self._donors = temp._donors
class Donors_All: _donors = List() def __init__(self, donors=None): if donors: self._donors = donors else: self._donors = [] def add_donor(self, donor): self._donors.append(donor) def _get_donor_names(self): return [donor.name for donor in self._donors] def _donation_summary(self): sort_rep = [] for donor in self._donors: sort_rep.append([donor.name, donor.total_donations, donor.len_donations, donor.avg_donations]) sort_rep.sort(key=lambda elem: elem[1], reverse=True) return sort_rep def donor_list(self): """Return all donors name.""" for donor in self._donors: print(donor.name) def add_donation(self, x, d): if x not in self._get_donor_names(): self.add_donor(Donor(x, [])) donor = self._donors[self._get_donor_names().index(x)] donor.add_donations(d) donor.letter(d) def report(self): """ Generate the statistics for the donor list. """ print("\n") print('Donor Name' + ' ' * 16 + '|' + ' ' * 9 + 'Total Given' + ' |' + ' ' * 7 + 'Num Gifts' + ' |'+' '*8+'Average Gift') print('-'*26+'|'+'-'*21+'|'+'-'*17+'|'+'-'*20+'|') for donor in self._donation_summary(): print('{:<25s} | ${:>18,.2f} | {:>15d} | ${:>18,.2f}'.format( donor[0], donor[1], donor[2], donor[3])) print('\n') def write(self): txt = """\n Dear {0:s}, Thank you for your very kind donation of ${1:,.2f}. It will be put to very good use. Sincerely, -The Team """ for donor in self._donation_summary(): file_name = donor[0] + ".txt" with open(file_name, 'w') as f: try: f.write(txt.format(donor[0], donor[1])) print("Generated letter for {:s}!\n".format(donor[0])) except(OSError, FileExistsError, IsADirectoryError, PermissionError) as x: print('Error trying to write', file_name, ':', x) def save(self, file_name='donors.json'): """ Save donors in a json file """ with open(file_name, 'w') as f: self.to_json(f) print("Saved donor list to file: {:s}!\n".format(file_name)) def load(self, file_name='donors.json'): """ Load donors from a json file """ json_donors = "" try: with open(file_name, 'r') as f: for l in f: json_donors = json_donors + l temp = from_json(json_donors) self._donors = temp._donors print("Loaded donor list from file: {:s}\n".format(file_name)) except Exception as e: print("Error loading file: {e}!\n".format(e))
class Donor: _name = String() _donations = List() _total_donations = Float() def __init__(self, name, donations=None): if ' ' in name: self._first, self._last = name.split(' ') else: self._first = '' self._last = name self._name = name if donations: self._donations = donations else: self._donations = [] @property def name(self): return self._name @property def first_name(self): return self._first @property def last_name(self): return self._last @property def donations(self): return self._donations @property def full_name(self): return f"{self._first} {self._last}" def __str__(self): return f"{self._first} {self._last} {self._donations}" def __repr__(self): return f'Donor(\'{str(self._name)}\', {self._donations})' def add_donations(self, amount): return self._donations.append(amount) @property def total_donations(self): return sum(self._donations) @property def len_donations(self): return len(self._donations) @property def avg_donations(self): try: return self.total_donations / self.len_donations except ValueError: return self._donations def letter(self, amount): txt = """\n To: {0:s} Subject: Your donation of ${1:,.2f} Dear {0:s},\n Thank you for your donation of ${1:,.2f}.\n """ print(txt.format(self._name, amount))
class DonationRecords: _donors = List() """ Maintains record of all donors """ ltr_template = ("\n\nDear {donor_name}," "\n\nThank you for your generous donation of ${amt}." "\nThis brings your to-date total of donations to ${total}!" "\nYour kind help is greatly appreciated." "\n\nKindest regards, Monty Burns\n\n" ) def __init__(self, donors=None): if donors is None: self._donors = [] else: self._donors = donors @property def donors(self): """ Get list of donors """ return self._donors def add_donor(self, donor): """ Add a donor :param - donor - new donor """ self._donors.append(donor) def get_donor(self, name): """ Return a donor :param - name - donor name :return - donor with matching name, or None if not found """ for donor in self._donors: if donor.name == name: return donor return None def record_donation(self, name, donation): """ Record a new donation :param - name - donor to thank :param - donation - donation amount """ donor = self.get_donor(name) if donor is None: donor = Donor(name) self.add_donor(donor) donor.donate(donation) return donor def clear_donations(self): """ Clear all donor records """ self._donors.clear() def create_report(self): """ Return a formatted report of all donors """ # print the report header header_row = "\n\n{:25} | {:11} | {:9} | {:12}\n".format("Donor Name", "Total Given", "Num Gifts", "Average Gift") report = header_row + ("-" * len(header_row)) + "\n" # create sorted list of row data from donors sorted_donors = sorted(self._donors, reverse=True) # add a report row for each sorted donor row for donor in sorted_donors: report += ("{:28}${:>10.2f}{:>12} ${:>12.2f}\n" .format(donor.name, donor.total_donations, donor.num_donations, donor.avg_donation)) report += "\n\n" return report def send_thanx(self, donor, donation): """ Return formatted thank you :param - donor - donor to thank :param - donation - donation amount to thank them for :return - formatted thank you letter """ record = {'donor_name' : donor.name, 'amt' : "{:.2f}".format(donation), 'total' : "{:.2f}".format(donor.total_donations)} return self.ltr_template.format(**record) def thank_all(self): """ Write thank you letters for all donors to separate files """ for donor in self._donors: f = open(donor.name.replace(' ', '_') + ".txt", 'w') last_donation = donor.donations[-1:][0] f.write(self.send_thanx(donor, last_donation)) def save(self, filename): """ Saves the donors as a json file """ with open(filename, 'w') as f: self.to_json(f) def load(self, filename): """ Loads the donors from a json file """ json_donors = "" with open(filename, 'r') as f: for l in f: json_donors = json_donors + l temp = from_json(json_donors) self._donors = temp._donors
class Donor: _name = String() _donations = List() """ Defines a single donor with their individual donation information """ def __init__(self, name, donations=None): self._name = name if donations is None: self._donations = [] else: self._donations = donations @property def name(self): """ Get donor name """ return self._name def donate(self, amt): """ Record a new donation for this donor """ self._donations.append(amt) @property def donations(self): """ Return list the donations for this donor """ return self._donations @property def num_donations(self): """ Return the number of donations for this donor """ return len(self._donations) @property def total_donations(self): """ Return the total donations for this donor """ total = 0; for donation in self._donations: total += donation return total @property def avg_donation(self): """ Return the average donation for this donor """ return self.total_donations / self.num_donations def __lt__(self, other): """ Less-than comparator for this donor's total donations to anothers """ return self.total_donations < other.total_donations def __eq__(self, other): """ Equality comparator for this donor's total donations to another """ return self.total_donations == other.total_donations
class EachDonor: """ Individual donor field behaviors """ name = String() each_donation = List() def __init__(self, name, each_donation): """ Initialize instance objects :param name: name object for individual donors :param each_donation: individual donations (to be added to list) """ self.name = name self.each_donation = [] for new_donation in each_donation: self.each_donation.append(new_donation) def new_donation(self, amnt): """ Donation adder() function -- allows user to enter new donation amount(s) for a specific donor. :param amnt: donation amount (numeric) :return: N/A """ self.each_donation.append(amnt) def write_letter(self, *args): """ Pre-written text with donor info to be added on individual run :param args: :return: """ donor_container = { 'name': self.name, 'donation': self.each_donation[-1], 'num_donations': len(self.each_donation) } thankyou_file = (''' Dear {name}, Thank you for your continued support through your most recent contribution of ${donation:,.2f}. Your {num_donations} donation(s) over this year have been instrumental in moving towards our fundraising goal of $100,000.00 to benefit local charities. On behalf of all the members of the Foundation, we thank you for your generosity and look forward to working with you in the future to build a better world! Best wishes, Foundation Board of Directors\n'''.format(**donor_container)) return thankyou_file @property def sum_donations(self): """ Returns sum of donor's donations :return: """ return sum(self.each_donation) @property def num_donations(self): """ Returns number of donations for self.donor :return: """ return len(self.each_donation) @property def avg_donations(self): """ Returns average value of donations for self.donor :return: """ return sum(self.each_donation) / len(self.each_donation) def __str__(self): """ Formatting for report columns :return: """ return "{:<20}{:>15,.2f}{:^18}{:>10,.2f}".\ format(self.name, self.sum_donations, self.num_donations, self.avg_donations) def __repr__(self): """ :return: """ return "Donor(\'{}\', {})".format(self.name, self.each_donation) 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
class Donor(JsonSaveable): name = String() history = List() def __init__(self, title, gift): self.name = title self.history = [] if type(gift) == int or type(gift) == float: self.history.append(round(gift, 2)) elif type(gift) == list: for x in gift: self.history.append(round(x, 2)) def __len__(self): return len(self_history) @property def avg_gift(self): return sum(self.history) / len(self.history) @property def sum_gift(self): return sum(self.history) @property def info(self): return (self.name, len(self.history), self.avg_gift, self.sum_gift) def add_gift(self, value): self.history.append(round(value, 2)) def challenge(self, factor, min_gift=None, max_gift=None): if min_gift is None: min_gift = min(self.history) if max_gift is None: max_gift = max(self.history) filt_hist = list( filter(lambda x: x >= min_gift and x <= max_gift, self.history)) remain_hist = list( filter(lambda x: x < min_gift or x > max_gift, self.history)) filt_hist = list(map(lambda x: x * factor, filt_hist)) return Donor("*" + self.name, filt_hist + remain_hist) def thank_u_letter_str(self, new_gift=False): divider = "\n" + "*" * 50 + "\n" thank_u_letter = divider + f"Dearest {self.name},\n" if new_gift: thank_gift = self.history[len(self.history) - 1] thank_u_letter += "\tThank you for your most recent donation of" else: thank_gift = self.sum_gift thank_u_letter += "\tThank you for your lifetime total of " thank_u_letter += (f" ${thank_gift:.2f}!\n" "We will use your donation(s) to create real " "living Pokemon.\n" "You now have our eternal loyalty. Use it wisely.\n" "Sincerely,\n" f"We're a Pyramid Scheme & so is {self.name}" + divider) return thank_u_letter