class ClassWithDict:
    x = js.Int()
    d = js.Dict()

    def __init__(self, x, d):
        self.x = x
        self.d = d
示例#2
0
class Donors:
    dic = js.Dict()

    def __init__(self, dic={}):
        self.dic = dic
    
    def add_donor(self, name, lst):
        self.dic.update({name: lst})
示例#3
0
class donor_DB():
    dict = js.Dict()

    def __init__(self, dict= {}):
        self._donors = dict

    def find_donor(self, name):
        if name.lower() in self._donors:
            return self._donors[name.lower()]
        return None

    def add_donor(self, name):
        if self.find_donor(name):
            pass
        else:
            donor = Donor(name)
            self._donors[donor.name.lower()] = donor

    def search_donor(self,name):
        return self._donors.get(name.lower())

    def donor_list(self):
        return list(self._donors)

    def _letter(self, d):
        letter = f'''Dear {d.name}
            Thank you for your generous donation of ${d.last:.2f}.
            We appreciate your contribution.
            Team R '''
        return letter

    def report(self):
        head = '{:20}|{:20}|{:10}|{:20}|'.format('Donor Name','Total Given', 'Num Gifts','Average Gifts')
        result = [head]
        result.append('-'*len(head))
        for donor in self._donors:
            result.append(f"{donor.name:20}|${donor.total:19,.2f}|{donor.times:10}|${donor.ave:19,.2f}|")
        return result

    def file_letters(self):
        for donor in self._donors:
            f_name = donor.name+'.txt'
            with open(f_name, 'wt') as f:
                print(f'''Dear {donor.name},
                    Thank you for your generous donation ${donor.total:.2f}.
                    We appreciate your contribution.
                    Team R ''', file = f)

    def quit(self):
        sys.exit()
class DonorDB(object):
    #Dictionary: keys are donors and values are lists of donations
    donor_data = {
        "Allen, Paul": [1000000.00, 50000.00, 300000.00],
        "Gates, Bill": [5000000.00, 80000.00, 700000.00],
        "Bezos, Jeff": [30000.00],
        "Musk, Elon": [1000000.00, 30000.00],
        "Zuckerberg, Mark": [10000.00, 50000.00, 2000.00, 400000.00]
    }
    donor_db = js.Dict()

    def __init__(self):
        try:
            with open('mailroom.json', 'r') as db_handle:
                file_contents = db_handle.read()
        except IOError:
            self.donor_db = self.initial_db
        if file_contents:
            self.donor_db = js.from_json(file_contents)
class DonorDB(object):

    initial_db = {
        "Aristotle": [384.0, 322.0],
        "Kant": [1724.0, 1804.0, 1785.0],
        "Locke": [1632.0],
        "Russell": [1872.0, 1970.0, 1950.0],
        "Dennett": [1942.0],
    }

    donor_db = js.Dict()

    def __init__(self):

        try:
            with open('mailroom.json', 'r') as db_handle:
                file_contents = db_handle.read()
        except IOError:
            self.donor_db = self.initial_db

        if file_contents:
            self.donor_db = js.from_json(file_contents)
class DonorCollection:

    donor_dict = js.Dict()

    def __init__(self, donors):
        self.donor_dict = donors

    def generate_name_list(self):
        """Creates a list of all the distinct donors, returns a list
        helper method for print_names"""
        return list(self.donor_dict)

    def print_names(self):
        """Prints out all the names in the name list,
        references generate_name_list"""
        for name in self.generate_name_list():
            print(name)

    def send_thanks(self):
        """Prompts the user to type a name of a donor, enter a donation amount,
        prints an email thanking the donor
        If the user types exit, it would return to the main prompt"""
        temp_list = []
        donor_name = get_new_donor_name()
        if (donor_name != 'exit'):
            temp_list = donor_name.split()
            donation_amt = get_new_donor_amount()
            if (donation_amt != 'exit'):
                temp_list.append(float(donation_amt))
                if donor_name in self.donor_dict:
                    self.donor_dict[donor_name].add_donation(temp_list[2])
                else:
                    self.donor_dict[donor_name] = Donor(
                        temp_list[0], temp_list[1], [temp_list[2]])
                print(self.donor_dict[donor_name].get_email_text(temp_list))

    def send_letters(self):
        """Goes through all the previous donators, gets their total donated,
        sends a thank you letter that is output on a .txt file"""
        for name, vals in self.donor_dict.items():
            message = vals.get_letter_text()
            with open(name + ".txt", 'w') as output:
                output.write(message)
        print("Letters have been generated.")

    def generate_report(self):
        """Generates a report of all the previous donators
        Report includes name, total donated, count of donations, average gift
        Report is also formatted with a certain spacing
        returns the report as a string"""
        donation_total = [[
            k, v.get_donation_total, v.get_donation_count, v.get_avg_donation
        ] for k, v in self.donor_dict.items()]
        donation_total.sort(key=lambda l: l[1], reverse=True)
        s1 = "Donor Name          |   Total Given  |  Num Gifts |  Average Gift\n"
        s2 = "-----------------------------------------------------------------\n"
        final_string = s1 + s2
        for z in range(0, len(donation_total)):
            s3 = '{:20} ${:13,.2f}{:14}  ${:13,.2f}\n'.format(
                *donation_total[z])
            final_string += s3
        return final_string

    def print_report(self):
        """Prints a report of all the previous donators references generate_report"""
        print(self.generate_report())

    def challenge(self):
        """Prompts the user whether they want to get an estimate or match,
        enter a number to multiply all the donations by an amount,
        enter a min and max threshold on the donation amount to filter"""
        projection = get_projection()
        factor = get_multip_factor()
        lower = get_min_donation()
        upper = get_max_donation()
        temp_sum = 0
        for donor, val in self.donor_dict.items():
            filtered_list = list(
                filter(lambda x: lower <= x <= upper, val._donations))
            challenge_list = list(map(lambda x: x * factor, filtered_list))
            if projection == '1':  # Get estimate
                if challenge_list:
                    temp_sum += reduce(lambda x, y: x + y, challenge_list)
            else:  # Get match
                self.donor_dict[donor]._donations = challenge_list
        if projection == '1':
            print("Estimated match contribution is ${:.2f}.".format(temp_sum))
        else:  # projection == '2'
            print("Donations have been multiplied by a factor of {}.".format(
                factor))
        return self.donor_dict

    def save_json(self):
        """Saves the donor dictionary into a json file"""
        json_string = json.dumps(self.to_json_compat())
        with open('Data.json', 'w') as file:
            file.write(json_string)
        print("Your file has been generated.")

    def load_json(self):
        #global donor_dict
        """Loads donor information from a json file"""
        with open('Data1.json', 'r') as data_load:
            json_data = json.load(data_load)
        self.donor_dict = self.from_json_dict(json_data).donor_dict
        print("Donors have been loaded.")
class DonorList():

    donors = js.Dict()

    def __init__(self, donors):
        self.donors = donors

    @property
    def donor_list(self):
        return (list(self.donors.keys()))

    # define a function to prompt the user for their desired action
    def prompt_user(self):
        print("Choose an action. ")
        print()
        print("1 - Send a thank you ")
        print("2 - Create a report ")
        print("3 - Send letters to everyone ")
        print("4 - Quit")

        while True:
            try:
                response = int(input(" > "))
            except ValueError:
                print("You must enter an *integer* value. ")
                continue
            else:
                return response

    def add_donor(self, new_donor):
        self.donors[new_donor.name] = new_donor

    def receive_thank_you_card_recepient_input(self):
        recipient = str(
            input("To whom would you like to send a thank you? > "))
        while recipient == "list":
            print(self.donor_list)
            print("\n")
            recipient = str(
                input("To whom would you like to send a thank you? > "))
        return (recipient)

    def receive_donation_amount(self):
        while True:
            donation_amount = input("How much would you like to donate? > ")
            try:
                donation_amount = float(donation_amount)
                if donation_amount < 0.00:
                    print("You must enter a positive number to donate. ")
                    continue
                break
            except ValueError:
                print("You must enter a numeric value. > ")
        return (donation_amount)

    def send_a_thank_you(self, out=sys.stdout):
        recipient = self.receive_thank_you_card_recepient_input()
        donation_amount = self.receive_donation_amount()
        self.donors.setdefault(recipient,
                               Donor(recipient)).add_donation(donation_amount)
        out.write("Dear {:s}, \n".format(recipient))
        out.write("Thank you for your generous donations totaling ${:.2f}. \n".
                  format(*[
                      x.total_donations
                      for i, x in enumerate(self.donors.values())
                      if x.name == recipient
                  ]))
        out.write("Best, The Donation Foundation")

    def create_a_report(self, out=sys.stdout):
        header_tuple = ("Donor Name", "Total Given", "Num Gifts",
                        "Average Gift Size")
        out.write("{:20s} | {:10s} | {:10s} | {:15s}\n".format(*header_tuple))
        out.write("-" * 70)
        out.write("\n")
        for donor in self.donors.values():
            out.write("{:20s} ${:10.2f}   {:10d}   ${:15.2f}\n".format(
                donor.name, donor.total_donations, donor.number_of_donations,
                donor.average_donation_size))

    def send_letters_to_everyone(self):
        for donor in self.donors.values():
            file = open(
                "thank_you_{name:{width}}.txt".format(name=donor.name,
                                                      width=len(donor.name)),
                "w")
            file.write("Dear {:s}, \n".format(donor.name))
            file.write(
                "Thank you for your generous donations totaling ${:.2f}. \n".
                format(donor.total_donations))
            file.write("Best, The Donation Foundation")
            file.close()
示例#8
0
class DonorDB:
    """
    Encapsulation of the entire database of donors and data associated with them.
    """
    # specify a json_save dict as the data structure for the data.
    donor_data = js.Dict()

    _frozen = False

    def __init__(self, donors=None, db_file=None):
        """
        Initialize a new donor database

        :param donors=None: iterable of Donor objects

        :param db_file=None: path to file to store the datbase in.
                             if None, the data will be stored in the
                             package data_dir
        """
        if db_file is None:
            self.db_file = data_dir / "mailroom_data.json"
        else:
            self.db_file = Path(db_file)

        self.donor_data = {}

        if donors is not None:
            # you can set _frozen so that it won't save on every change.
            self._frozen = True
            for d in donors:
                self.add_donor(d)
            self.save  # save resets _frozen

    def mutating(method):
        """
        Decorator that saves the DB when a change is made

        It should be applied to all mutating methods, so the
        data will be saved whenever it's been changed.

        NOTE: This is not very efficient -- it will re-write
              the entire file each time.
        """

        # note that this is expecting to decorate a method
        # so self will be the first argument
        def wrapped(self, *args, **kwargs):
            res = method(self, *args, **kwargs)
            if not self._frozen:
                self.save()
            return res

        return wrapped

    @classmethod
    def load_from_file(cls, filename):
        """
        loads a donor database from a raw json file
        NOTE: This is not a json_save format file!
              -- it is a simpler, less flexible format.
        """
        with open(filename) as infile:
            donors = json.load(infile)
        db = cls([Donor(*d) for d in donors])
        return db

    @classmethod
    def load(cls, filepath):
        """
        loads a donor database from a json_save format file.
        """
        with open(filepath) as jsfile:
            db = js.from_json(jsfile)
        db.db_file = filepath

    def save(self):
        """
        Save the data to a json_save file
        """
        # if explicitly called, you want to do it!
        self._frozen = False
        with open(self.db_file, 'w') as db_file:
            self.to_json(db_file)

    @property
    def donors(self):
        """
        an iterable of all the donors
        """
        return self.donor_data.values()

    def list_donors(self):
        """
        creates a list of the donors as a string, so they can be printed

        Not calling print from here makes it more flexible and easier to
        test
        """
        listing = ["Donor list:"]
        for donor in self.donors:
            listing.append(donor.name)
        return "\n".join(listing)

    def find_donor(self, name):
        """
        find a donor in the donor db

        :param: the name of the donor

        :returns: The donor data structure -- None if not in the self.donor_data
        """
        return self.donor_data.get(Donor.normalize_name(name))

    @mutating
    def add_donor(self, donor):
        """
        Add a new donor to the donor db

        :param donor: A Donor instance, or the name of the donor

        :returns: The new or existing Donor object
        """

        if not isinstance(donor, Donor):
            donor = Donor(donor)
        self.donor_data[donor.norm_name] = donor
        donor._donor_db = self
        return donor

    @staticmethod
    def sort_key(item):
        # used to sort on name in self.donor_data
        return item[1]

    def generate_donor_report(self):
        """
        Generate the report of the donors and amounts donated.

        :returns: the donor report as a string.
        """
        # First, reduce the raw data into a summary list view
        report_rows = []
        for donor in self.donor_data.values():
            name = donor.name
            gifts = donor.donations
            total_gifts = donor.total_donations
            num_gifts = len(gifts)
            avg_gift = donor.average_donation
            report_rows.append((name, total_gifts, num_gifts, avg_gift))

        # sort the report data
        report_rows.sort(key=self.sort_key)
        report = []
        report.append("{:25s} | {:11s} | {:9s} | {:12s}".format(
            "Donor Name", "Total Given", "Num Gifts", "Average Gift"))
        report.append("-" * 66)
        for row in report_rows:
            report.append(
                "{:25s}   ${:10.2f}   {:9d}   ${:11.2f}".format(*row))
        return "\n".join(report)

    def save_letters_to_disk(self):
        """
        make a letter for each donor, and save it to disk.
        """
        print("Saving letters:")
        for donor in self.donor_data.values():
            print("donor:", donor.name)
            letter = donor.gen_letter()
            # I don't like spaces in filenames...
            filename = donor.name.replace(" ", "_") + ".txt"
            open(filename, 'w').write(letter)
示例#9
0
class Donor_Save(js.JsonSaveable):

    donors = js.Dict()

    def __init__(self, donors):
        self.donors = donors
class Mailroom(object):

    # Initial donor table with the donation values.
    donor_table_dict = js.Dict()

    def __init__(self, donor_table_dict):
        self.donor_table_dict = donor_table_dict

    def thank_you(self, thank_you_dict, full_name, donation_value_str):
        output_string = ""
        while True:
            if full_name.lower() == "quit": return thank_you_dict, ""
            if full_name.lower() == "list":
                output_string = "Donor list:\n"
                for i in (list(thank_you_dict.keys())):
                    output_string = output_string + i + "\n"
                return thank_you_dict, output_string
            else:
                if donation_value_str.lower() == "quit":
                    return thank_you_dict, ""
                try:
                    donation_value_flt = float(donation_value_str)
                    if donation_value_flt <= 0:
                        raise ValueError
                    if full_name in thank_you_dict:
                        thank_you_dict[full_name].append(donation_value_flt)
                    else:
                        thank_you_dict[full_name] = [donation_value_flt]
                    print()
                    output_string = ("""
Dear {}:
    Thank you for your generous donation of ${:.2f} to Save the Kids.

-------------
Save the Kids
[email protected]
                    """.format(full_name, donation_value_flt))
                    return (thank_you_dict, output_string)
                except ValueError:
                    output_string = "Not entered. Please enter a positive number value for the donation amount."
                    return thank_you_dict, output_string

    def create_report(self, create_report_dict):
        output_string = "{:<20} | {:<10} | {:<10} | {:<10}\n".format(
            "Donor Name", "Total Given", "Num Gifts", "Average Gift")
        output_string += "----------------------------------------------------------------------------\n"
        order_dict = OrderedDict(sorted(create_report_dict.items()))
        for key in order_dict:
            output_string += (
                "{:<20}   ${:>10.2f}   {:>10d}   ${:>10.2f}\n".format(
                    key, sum(order_dict[key]), len(order_dict[key]),
                    sum(order_dict[key]) / len(order_dict[key])))
        return create_report_dict, output_string

    def send_letters(self, send_letters_dict):
        for key in send_letters_dict:
            with open(key + ".txt", "w") as writefile:
                letter = """
Dear {}:
    Thank you for your recent donation of ${:.2f} to Save the Kids. We are grateful for your total donations of ${:.2f} 
    to our organization.

-------------
Save the Kids
[email protected]
""".format(key, send_letters_dict[key][-1], sum(send_letters_dict[key]))
                writefile.write(letter)
        print("Letters have been created.\n")
class DonorCollection:
    #convert list to json
    donorsdict = js.Dict()

    def __init__(self, donors):
        self.donorsdict = donors

    def add_donor(self, donor):
        return self.donorsdict.update({donor.full_name: donor.donation_lis})

    #Returns sorted list of all donors
    def get_all_donors(self):
        donor_lis = list(self.donorsdict.keys())
        return sorted(donor_lis)

    def search_for_donor(self):
        reply = input("Enter first and last name of donor>> ")
        donor = reply.title()
        if donor not in self.donorsdict:
            print("{} is not a previous donor.".format(donor))
        else:
            for key, val in self.donorsdict.items():
                if donor == key:
                    print("Name: {}\nDonations: {}\n".format(donor, val))

    def sort_donors_by_total_amount(self):
        donor_total_amount = {
            key: sum(value)
            for key, value in self.donorsdict.items()
        }
        return OrderedDict(
            sorted(donor_total_amount.items(), key=itemgetter(1),
                   reverse=True))

    def thank_you(self):
        try:
            self.name = donor_name_prompt()
            if self.name.lower() == 'list':
                print(self.get_all_donors())
            elif self.name.upper() == 'Q':
                main_menu(self)
            first, last = self.name.split(' ')
        except ValueError:
            print("Invalid input.")
            self.thank_you()
        else:
            success = False
            while not success:
                try:
                    self.donation = donation_prompt()
                    success = True

                except ValueError:
                    print('Please enter a valid number.')
                    success = False

            self.donor = Donor(first.title(), last.title(), [self.donation])

            if self.donor.full_name not in self.donorsdict:
                print(f"{self.name.title()} is a new donor.")
                print(self.thank_you_message(self.name, self.donation, 0))
                self.add_donor(self.donor)
            else:
                print(f"{self.name.title()} is a previous donor.\n>> ")
                print(self.thank_you_message(self.name, self.donation, 1))
                self.donorsdict[f"{first.title()} {last.title()}"].append(
                    self.donation)

    def thank_you_message(self, name, donation, type):
        #New donor message
        if type == 0:
            return f"Thank you {name.title()} for becoming a new donor to our charity! Your genereous donation of ${float(donation):.2f} is much appreciated."
        # previous donor message
        elif type == 1:
            return f"Thank you {name.title()} for your loyal support to our charity! Your genereous donation of ${float(donation):.2f} is much appreciated."

    def match_contributions(self, projection=-1):
        while projection not in [0, 1]:
            try:
                projection = projection_prompt()
            except ValueError:
                print('invalid input')

        success = False
        while not success or min_amount > max_amount:
            try:
                factor = factor_prompt()
                min_amount = min_amount_prompt()
                max_amount = max_amount_prompt()
                if min_amount > max_amount:
                    print(
                        'The minimum donation amount must be less than the maximum donation amount'
                    )
                else:
                    success = True

            except ValueError:
                print('Please enter a valid number.')
                success = False

        self.challenge(projection, min_amount, max_amount, factor)

    def challenge(self, projection=0, min=0, max=99999999, factor=1):
        #Multiplies  total donation amount of each donor by factor.
        total = 0
        for donor in self.donorsdict:
            filtered_list1 = list(
                filter(lambda x: x >= min and x <= max,
                       self.donorsdict[donor]))
            filtered_list2 = list(
                filter(lambda x: x < min and x > max, self.donorsdict[donor]))
            challenge_list = list(map(lambda x: x * factor, filtered_list1))
            if projection == 1:
                self.donorsdict[donor] = challenge_list + filtered_list2
            else:
                if challenge_list:
                    total = total + functools.reduce(lambda x, y: x + y,
                                                     challenge_list)

        if projection == 1:
            print(
                f"All donations have been multiplied by a factor of {factor}")
            return self.donorsdict
        else:
            if total == 0:
                print(
                    'There were no donation amounts that fit into the range of minimum and maximum donations. Please re-adjust minimum and maximum donations.'
                )
            else:
                print(f'Total estimated donation: ${total:.2f}')

    def create_report(self):

        print(
            "Donor Name           |   Total Given   |   Num Gifts  |    Average Gift"
        )
        print(
            "-----------------------------------------------------------------------"
        )

        for donor in self.sort_donors_by_total_amount():
            print(
                f"{donor:20} ${sum(self.donorsdict.get(donor)):>17.2f}    {len(self.donorsdict.get(donor)):>6}     ${sum(self.donorsdict.get(donor))/ len(self.donorsdict.get(donor)):>16.2f}"
            )

    def create_thank_you_letters(self):
        # Creates a letter for each donor that gets a file in the working dir based on donor's name.
        for donor in self.donorsdict:
            letter = self.letter_template(donor)
            with open(donor + ".txt", 'w') as output:
                output.write(letter)
        print("Letters have been generated.")

    def letter_template(self, donor):
        letter = "Dear {},\n   Thank you for donating ${:,.2f}. Your donation makes a positive impact on your community.\n\nSincerely,\nThe Team".format(
            donor, sum(self.donorsdict.get(donor)))
        return letter

    def thank_you_email_template(self, dk):
        if len(self.donorsdict.get(dk)) > 1:
            return "Dear {},\nThank you for your {} generous donations of ${:.2f}. Your support helps our charity stay in business.\n\nSincerely,\n-The Team".format(
                dk, len(self.donorsdict.get(dk)), sum(self.donorsdict.get(dk)))
        else:
            return "Dear {},\nThank you for your generous donation of ${:.2f}. Your support helps our charity stay in business.\n\nSincerely,\n-The Team".format(
                dk, sum(self.donorsdict.get(dk)))

    def save_json(self):
        """Saves the donor dictionary into a json file"""
        json_string = json.dumps(self.to_json_compat())
        with open('Donor_DB.json', 'w') as file:
            file.write(json_string)
        print("Your file has been generated.")

    def load_json(self):
        """Loads donor information from a json file"""
        with open('Donor_DB.json', 'r') as data_load:
            json_data = json.load(data_load)
        self.donorsdict = self.from_json_dict(json_data).donorsdict
        print("Donors have been loaded.")
class DonorsCollection():
    _donors = js.Dict()
    rep = js.String()

    def __init__(self, val=None):
        self._donors = {}
        self.donors = val
        self.rep = ""

    @property
    def donors(self):
        return self._donors

    @donors.setter
    def donors(self, val):
        if val is not None:
            if isinstance(val, Donor):
                self._donors[val.name] = val
            else:
                raise ValueError("Must be instance od Donor class")
                return

    def add_donor(self):
        name = input("Type donor first and last name: ")
        donor_name = tuple(name.split())
        if donor_name in self.donors:
            self.donors[donor_name].donations = float(
                input(" Donation in USD: "))
        else:
            d = Donor(name)
            try:
                d.donations = float(input("Donation in USD: "))
            except ValueError:
                print("""
                      Donation must be in USD...
                      Donor not added
                      """)
                del (d)
                return
            self.donors = d
        self.donors[donor_name].print_greetings

    def display_key(self, a):
        return a[-1]

    def display(self):
        for donor in sorted(self.donors, key=self.display_key):
            print("".join(["{} "] * len(donor)).format(*donor))

    def custom_key(self, a):
        return (a[1].total)  # 2nd arg => dict value => Donor instance

    def challenge(self, factor, min_donation=None, max_donation=None):
        for donor in self.donors:
            self.donors[donor] = \
                self.donors[donor].multiply_donations(factor,
                                                      min_donation,
                                                      max_donation)

    @property
    def report(self):
        self.rep = ""
        self.rep += "{:<40}| {:<18}| {:<8}| {:<18}\n".format(
            'Donor Name', 'Total Given', 'Num Gifts', 'Average Gift')
        self.rep += "{:-<90}\n".format('')
        for k, v in sorted(self.donors.items(),
                           key=self.custom_key,
                           reverse=True):

            name = " ".join(["{} "] * len(k)).format(*k)
            self.rep += "{:<40}{}{:>18.2f}{:>11}{}{:>17.2f}\n" \
                        .format(name, ' $', v.total, v.number, ' $', v.average)
        return (self.rep)

    def print_report(self):
        print(self.report)

    def write_letters(self):
        print("Sending letters to all donors...")
        for k, d in self.donors.items():
            d.write_letter()

    def projections(self, factor, min_donation=None, max_donation=None):
        for donor in self.donors.values():
            temp = cp.deepcopy(donor)  # projection done on donor copy
            print("Donor: {} Current total of dination: {} \
                   Total after factor applied: {}".format(
                donor.name, donor.total,
                temp.multiply_donations(factor=factor,
                                        min_donation=min_donation,
                                        max_donation=max_donation).total))
            del (temp)
        answer = None
        while answer not in ['Yes', 'No']:
            answer = input("Whould you like to multiply " +
                           "(above min, below max) donations: [Yes, No]:")
        if answer == "Yes":
            self.challenge(factor,
                           min_donation=min_donation,
                           max_donation=max_donation)
            print("Changes applied...")
        else:
            print("No changes applied...")

    def save(self, backup_file=None):
        if not backup_file:
            backup_file = input(
                "Name of json backup file(without extension): ")
        bkp = self.to_json()
        name = "{}.json".format(backup_file)
        with open(name, 'w') as f:
            f.write(bkp)
        print("Database save in {}".format(name))

    @classmethod
    def load(self, backup_file=None):
        if not backup_file:
            backup_file = input("Name of json backup file to load:\n")
        bkp_f = backup_file + ".json"
        with open(bkp_f, 'r') as f:
            bkp = json.load(f)
        return self.from_json_dict(bkp)
示例#13
0
class Donor(object):
    """
    Encapsulation of the entire database of donors and data associated with them.
    """
    # Class attributes
    # Will be using a dictionary here to work with it
    db = None
    donor_records = js.Dict()
    initial_state = False

    def __init__(self, donors=None, donor_data=None):
        """Initialize a new donor database."""
        # Database
        # Does it exist?
        if donor_data is None:
            self.donor_data = os.path.abspath("data/donor_records.json")
        else:
            self.donor_data = Path(donor_data)

        self.donor_records = {}

        # Donors
        if donors is not None:
            self.initial_state = True
            for i in donors:
                self.add_donor(i)

    @property
    def donors(self):
        """Method to get the donor values."""
        return self.donor_records.values()

    def add_donor(self, donor):
        """Add a donor."""
        if not isinstance(donor, DonorDonations):
            donor = DonorDonations(donor)
        self.donor_records[donor] = donor
        donor.db = self
        return donor

    def list_donors(self):
        """Method to create a list of the donors as a string, so they can be printed."""
        donor_list = ["Donor list:"]
        for donor in self.donors:
            donor_list.append(donor.donor_name)
        return "\n".join(donor_list)

    def donor_lookup(self, name):
        """Method for looking up a donor."""
        return self.donor_records.get(DonorDonations(name))

    def donor_save_records(self):
        """Save donor and information related to donor."""
        # Open donor_records.json in write mode an save to the file.
        with open(self.donor_data, 'w') as donor_data:
            self.to_json(donor_data)

    @classmethod
    def load_donor_records_js(cls, file):
        """Class method for working with the json_save library."""
        # Open donor_records.json using context manager
        with open(file) as f_obj:
            temp_donors = js.from_json(f_obj)
        temp_donors.donor_data = file

    def create_donor_report(self):
        """Create a report of the donors and donation amounts."""
        # Set an empty list for donations to append donations to as they are iterated over.
        donations = []

        print("{:26s} | {:13s} | {:9s} | {:13s}".format(
            "Donor name", "Total Donation", "Number of Gifts",
            "Average Gifts"))
        print("-" * 80)
        # print(self.donor_records.values())

        for donor in self.donor_records.values():
            full_name = donor.name
            gifts = donor.donor_donation
            total_given = donor.total_donations
            number_gifts = len(gifts)
            average_gift = donor.average_donation
            donations.append(
                (full_name, total_given, number_gifts, average_gift))

        for amount in donations:
            print("{:26s} | {:14.2f} | {:15d} | {:13.2f}".format(*amount))
        print()

        return donations

    def gen_letter(self, donor):
        """Generate a thank you letter for the donor."""
        """Template for writing a letter to a donor, thanking them for their donation."""
        return """Dear {0:s},\nThank you for your very kind donation of ${1:.2f}.\n\nIt will be put to very good use.\n\n \t\tSincerely,\n\t\t\t-The Team""".format(
            donor, donor.last_donation)

    def send_letter_file(self):
        """Write a thank you letter and save to file."""
        for k, v in donor_data.values():
            letter = gen_letter(donor)
            file_name = donor.name.replace(" ", "_") + ".txt"
            with open(file_name, 'w') as f:
                f.write(letter)

        print('Completed creating letters to send out to donors.')
示例#14
0
class DonorList:

    donors = js.Dict()

    def __init__(self, donors):
        self.donors = Donor(donors)
示例#15
0
class Donors:

    donors = js.Dict()

    def __init__(self, donors_dict):
        self.donors = donors_dict

    def __iter__(self):
        return iter(self.donors)

    def __contains__(self, donor_str):
        return donor_str in self.donors.keys()

    def report_gen(self):
        header = ('Donor Name', 'Total Given', 'Num Gifts', 'Average Gift')
        row_format, row_format0 = '{:<14}', '{:<14}'
        for item in header[1:]:
            row_format += f' | {{:>{len(item)}}}'
            row_format0 += f'  {{}}{{:>{len(item)}}}'
        print(row_format.format(*header))
        print('-' * len(row_format.format(*header)))
        for item in self.donors.keys():
            print(
                row_format0.format(
                    item, '$', sum(self.donors[item]), ' ',
                    len(self.donors[item]), '$',
                    round(sum(self.donors[item]) / len(self.donors[item]), 1)))

    def letters(self):
        for names in self.donors.keys():
            with open(f'{names}.txt', 'w') as text_file:
                print(
                    f'Dear {names},\nThank you for your very kind donation of ${sum(self.donors[names])}.\nIt will be put to very good use.\nSincerely,\n-The Team',
                    file=text_file)

    def see_list(self):
        for item in self.donors.keys():
            print(item)

    def add_donor(self, name_str, amount):
        try:
            if name_str in self.donors:
                self.donors[name_str].append(int(amount))
            else:
                self.donors[name_str] = [int(amount)]
        except ValueError:
            print("Please Enter a number.")

    def challenge(self, name_str, factor, min_donation=0, max_donation=None):
        temp = list(
            set(self.filter_min(min_donation)).intersection(
                self.filter_max(max_donation)))
        amount0 = sum(map(lambda x: sum(self.donors[x]) * factor, temp))
        self.add_donor(name_str, amount0)

    def filter_min(self, min_donation):
        return list(
            filter(lambda x: sum(donors[x]) > min_donation,
                   self.donors.keys()))

    def filter_max(self, max_donation):
        if max_donation == None:
            return self.donors.keys()
        else:
            return list(
                filter(lambda x: sum(donors[x]) < max_donation,
                       self.donors.keys()))

    def load_json(self):
        with open("save_file.json") as file_in:
            temp = js.from_json(file_in)
        self.donors = temp.donors

    def save_json(self):
        json_dlist = self.to_json()
        with open("save_file.json", 'w') as file_out:
            file_out.write(json_dlist)
示例#16
0
class Donorlist:
    """
    Instance of a list of donors, implemented as a dictionary.  Implements
    methods used in mailroom5.
    """

    _donor_objects = js.Dict()

    def __init__(self, init_list=None):
        """Takes dictionary value using format {'donor1', ['donations1']} """
        self._donor_objects = {}
        self._short_template = "Dear {}, thank you for your generous donation of ${:.2f}\n"
        self._long_template = (
            'Dear {},\n'
            '\n'
            '        Thank you for your kind donations totaling ${:.2f}\n'
            '\n'
            '        Your gifts will be put to very good use.\n\n'
            '                            Sincerely\n'
            '                                -The Team\n')

        if init_list:
            for d in init_list:
                self._donor_objects[d[0]] = Donor(*d)

    def __contains__(self, val):
        """ Returns if a name is in the list of donors"""
        return val in self._donor_objects.keys()
        pass

    def get_donor(self, val):
        """Returns a single donor object.  Not using in mailroom"""
        if val in self._donor_objects.keys():
            return self._donor_objects[val]

    def list_donors(self):
        """Returns a list of donors sorted by name"""
        return sorted(self._donor_objects.keys())

    def list_by_total(self):
        """Returns a list of donors sorted by total donations"""

        return tuple(
            sorted(self._donor_objects.values(),
                   key=Donor.sort_by_total,
                   reverse=True))

    def list_donations(self, name):
        """Returns list of donations for a donor"""
        if name in self._donor_objects.keys():
            return self._donor_objects[name].donations
        else:
            raise ValueError('Donor not in list')

    def add_donor(self, name):
        """Adds a new donor to the list with a blank donation history"""
        if name not in self._donor_objects.keys():
            self._donor_objects[name] = Donor(name, [])
        else:
            raise ValueError(f"Duplicate name in {type(self)}")

    def add_donation(self, name, amt):
        self._donor_objects[name].add_donation(amt)

    def send_thankyou(self, name, amt, template='short'):
        """
        Sends thank you note after donation.  Can pass an alternate template
        if desired.
        """
        if template == 'short':
            template = self._short_template
        elif template == 'long':
            template = self._long_template
        return template.format(name, amt)

    def create_report(self, file_out):
        """Prints report of all donors"""
        categories = ['Donor Name', 'Total Given', 'Num Gifts', 'Average Gift']
        spacing = "{:<20} $ {:>10.2f} {:>10}     $ {:>10.2f}\n"
        sorted_tuple = self.list_by_total()
        header = "{:<20}| {:>10} | {:>10} | {:>10}\n"
        file_out.write(header.format(*categories))
        for dn in sorted_tuple:
            ft = spacing.format(dn.name, dn.total, dn.count, dn.average)
            file_out.write(ft)

    def get_total(self, name):
        """Returns total donations for donor"""
        return self._donor_objects[name].total

    def save_list(self, file_out):
        """Writes Donor List object to open file handle in JSON format"""
        file_out.write(self.to_json())

    @classmethod
    def load_file(cls, file_in):
        """"Creates Donorlist object from JSON file"""
        input_dict = json.loads(file_in.getvalue())
        return Donorlist.from_json_dict(input_dict)