Ejemplo n.º 1
0
class Donor:

    _f_name = js.String()
    _l_name = js.String()
    _donations = js.List()

    def __init__(self, f_name, l_name, donation=None):
        self._f_name = f_name
        self._l_name = l_name
        if donation is None:
            self._donations = []
        else:
            self._donations = donation

    def f_name(self):
        return self._f_name

    def l_name(self):
        return self._l_name

    @property
    def full_name(self):
        return self._f_name + " " + self._l_name

    @property
    def get_donation_count(self):
        return len(self._donations)

    @property
    def get_donation_total(self):
        return sum(self._donations)

    @property
    def get_avg_donation(self):
        if len(self._donations) == 0:
            return 0
        else:
            return round(sum(self._donations) / len(self._donations), 2)

    def add_donation(self, value):
        self._donations.append(value)

    def get_email_text(self, current_donation):
        """Prints a thank you email to a donator
        Donor name and amount is passed in as a parameter"""
        return "Dear {:s} {:s},\n\
            Thank you for the generous donation of ${:,.2f}.\n\
            Sincerely,\n\
            Your Local Charity".format(*current_donation)

    def get_letter_text(self):
        """Returns a message of the donor name and donation total"""
        message = "Dear {:s},\n\
        Thank you for donating ${:,.2f}.\n\
        Sincerely,\n\
        Your Local Charity"

        return message.format(self.full_name, self.get_donation_total)
Ejemplo n.º 2
0
class Donor:

    name = js.String()
    donations = js.List()

    def __init__(self, name, donations):
        self.name = name
        self.donations = donations

    @property
    def total_donations(self):
        return sum(self.donations)

    @property
    def num_of_gifts(self):
        return len(self.donations)

    def add_donation(self, donation):
        self.donations.append(donation)

    def save_data(self):
        data = self.to_json_compat()
        data = json.dumps(data)
        with open('{}.json'.format(self.name), 'w') as datafh:
            datafh.write(data)

    @classmethod
    def load_data(cls, donor_name):
        with open('{}'.format(donor_name), 'r') as ddatafh:
            ddata = ddatafh.read()
        ddata = json.loads(ddata)
        return cls.from_json_dict(ddata)
Ejemplo n.º 3
0
class DonorHistory:

    name = js.String()
    donations = js.List()

    def __init__(self, name, donations=None):

        self.name = name
        if donations is None:
            self.donations = []
        else:
            self.donations = donations

    def add_donation(self, amount):
        try:
            self.donations.append(int(amount))
        except ValueError:
            print("Please enter a donation amount.")

    def number_donations(self):
        return len(self.donations)

    def total_donation(self):
        try:
            return sum(self.donations)
        except TypeError:
            return self.donations

    def donation_avg(self):
        try:
            return self.total_donation() / self.number_donations()
        except TypeError:
            return self.donations
Ejemplo n.º 4
0
class Donor():
    name = js.String()
    amount = js.Float()
    lst = js.List()

    def __init__(self, name, lst = []):
        self.name = name.capitalize()
        self.donation = lst

    def add_donations(self, amount):
        self.donation.append(amount)

    @property
    def total(self):
        return sum(self.donation)


    @property
    def times(self):
        return len(self.donation)

    @property
    def ave(self):
        return self.total/self.times

    @property
    def last(self):
        if len(self.donation) > 0:
            return self.donation[-1]
        else:
            return 0

    def __str__(self):
        return f'{self.name}:{self.donation}'
class Donor():

    _first = js.String()
    _last = js.String()
    _donations = js.List()

    def __init__(self, first_name, last_name, donations=None):
        self._first = first_name
        self._last = last_name
        if donations is None:
            self._donations = []
        else:
            self._donations = donations

    @property
    def full_name(self):
        return '{} {}'.format(self._first, self._last)

    def thank_you_letter_template(self, donor):
        if self.num_of_donations > 1:
            return "Dear {},\nThank you for your {} generous donations of ${:.2f}. Your continued support helps our charity stay in business.\n\nSincerely,\n-The Team\n".format(
                donor.full_name, donor.num_of_donations, donor.total_donation)
        else:
            return "Dear {},\nThank you for your generous donation of ${:.2f}. Your support helps our charity stay in business.\n\nSincerely,\n-The Team\n".format(
                donor.full_name, donor.total_donation)

    def add_donation(self, amount):
        return self._donations.append(amount)

    @property
    def num_of_donations(self):
        return len(self._donations)

    @property
    def total_donation(self):
        return sum(self._donations)

    @property
    def avg_donation(self):
        return sum(self._donations / len(self._donations))

    @property
    def donation_lis(self):
        return self._donations

    def __str__(self):
        return f"{self.full_name:20} ${self.total_donation:>17.2f}    {self.num_of_donations:>6}     ${self.avg_donation:>16.2f}"
Ejemplo n.º 6
0
class OtherSaveable:

    foo = js.String()
    bar = js.Int()

    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
Ejemplo n.º 7
0
class Donor:
    """
    Instance of donor class for each donor.  Takes a tuple of
    (name, [donations]) and has methods for finding total donations and
    average donation.  Sorts on donor name or total donations.
    Implementing save as JSON feature
    """

    name = js.String()
    _donations = js.List()

    def __init__(self, *args, **kwargs):
        """
        Expected input format is a tuple containting a donor name
        and a list of donation values.
        """
        self.name = str(args[0])
        # Using protected _donations value because I don't want people
        # overwriting These values.  I don't mind if they change the name.
        try:
            self._donations = [float(x) for x in args[1]]
        except IndexError:
            self._donations = []

    def add_donation(self, val):
        """ Appends a positive numerical value to donations"""
        if val < 0:
            raise ValueError('Donation must be greater than 0')
        self._donations.append(float(val))

    def sort_key(self):
        return self.name

    def sort_by_total(self):
        return self.total

    @property
    def donations(self):
        return self._donations

    @property
    def total(self):
        return sum(self._donations)

    @property
    def count(self):
        return len(self._donations)

    @property
    def average(self):
        try:
            return self.total / self.count
        except ZeroDivisionError:
            return 0
Ejemplo n.º 8
0
class Donor:
    """ Class to keep track of a donor with a donor name and list of donation amounts """
    name = js.String()
    donationList = js.List()

    def __init__(self, name=''):
        self.name = name.strip()
        self.donationList = js.List()

    def addDonation(self, amount):
        """ Add a donation amount to the list """
        self.donationList.append(amount)

    # CHANGE INTO A PROPERTY
    def getNumDonations(self):
        """ Get the number of donations the donor has made """
        return len(self.donationList)

    def getAvgDonation(self):
        """ Get the average value of the donations the donor has made"""
        try:
            return self.getTotDonation() / self.getNumDonations()
        except ZeroDivisionError:
            return 0.0

    def getTotDonation(self):
        """ Get the total value of the donations the donor has made """
        return sum(self.donationList)

    def createThankYouEmail(self):
        """ Return donation thank you e-mail text based on the donor name and the donated amount """
        result = (
            "\nDear {:s},\n\n"
            "\tThank you so much for your generous donation of ${:,.2f}!\n\n"
            "\tIt will be put to very good use.\n\n"
            "\t\tSincerely,\n\t\t\t- The Team".format(self.name,
                                                      self.getTotDonation()))
        return result

    def getDictRep(self):
        return {self.name: self.donationList}
class NoInit:
    """
    A class with saveable attribute, but no __init__
    """
    x = js.Int()
    y = js.String()
Ejemplo n.º 10
0
class Donor:
    """
    class to hold the information about a single donor
    """
    name = js.String()
    donations = js.List()

    # reference to the DB its in -- this will be set in the instance
    # when added to the DonorDB
    _donor_db = None

    def __init__(self, name, donations=None):
        """
        create a new Donor object

        :param name: the full name of the donor

        :param donations=None: iterable of past donations
        """

        self.norm_name = self.normalize_name(name)
        self.name = name.strip()
        if donations is None:
            self.donations = []
        else:
            self.donations = list(donations)

    def __str__(self):
        msg = (f"Donor: {self.name}, with {self.num_donations:d} "
               f"donations, totaling: ${self.total_donations:.2f}")
        return msg

    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 requires that the donor object is in a DonorDB.
        """

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

        return wrapped

    @staticmethod
    def normalize_name(name):
        """
        return a normalized version of a name to use as a comparison key

        simple enough to not be in a method now, but maybe you'd want to make it fancier later.
        """
        return name.lower().strip()

    @property
    def last_donation(self):
        """
        The most recent donation made
        """
        try:
            return self.donations[-1]
        except IndexError:
            return None

    @property
    def total_donations(self):
        return sum(self.donations)

    @property
    def num_donations(self):
        return len(self.donations)

    @property
    def average_donation(self):
        return self.total_donations / self.num_donations

    @mutating
    def add_donation(self, amount):
        """
        add a new donation
        """
        print("add_donation called")
        amount = float(amount)
        if amount <= 0.0:
            raise ValueError("Donation must be greater than zero")
        self.donations.append(amount)

    def gen_letter(self):
        """
        Generate a thank you letter for the donor

        :param: donor tuple

        :returns: string with letter

        note: This doesn't actually write to a file -- that's a separate
              function. This makes it more flexible and easier to test.
        """
        return dedent('''Dear {0:s},

              Thank you for your very kind donation of ${1:.2f}.
              It will be put to very good use.

                             Sincerely,
                                -The Team
              '''.format(self.name, self.last_donation))
Ejemplo n.º 11
0
class NoInit:
    x = js.Int()
    y = js.String()
Ejemplo n.º 12
0
class Donor(object):
    name = js.String()
    donations = js.List()

    def __init__(self, name, donations=None):
        if not name:
            raise ValueError("Donor name can not be empty")
        self.name = name
        if donations:
            self.donations = donations
        else:
            self.donations = []

    @property
    def first_name(self):
        name_split = self.name.split()
        if len(name_split) >= 1:
            return name_split[0]

    @property
    def last_name(self):
        name_split = self.name.split()
        if len(name_split) == 1:
            return ''
        else:
            return ''.join(name_split[1:])

    @property
    def donor_donations(self):
        """
        Returns list of donor donations
        :return: list of donor donations
        """
        return self.donations

    @property
    def donor_donations_sum(self):
        """
        Returns sum of all donor donations
        :return: donor latest donation
        """
        return sum(self.donations)

    @property
    def latest_donation(self):
        """
        Returns donor latest donation
        :return: donor latest donation
        """
        if self.donations:
            return self.donations[-1]

    def add_donation(self, amount):
        """
        Adds donation to donor donations
        :return:
        """
        if float(amount) <= 0:
            raise ValueError("donation amount can not be negative")
        self.donations.append(float(amount))

    def generate_letter(self):
        """ Generate letter for donor """
        return "Dear {},\n \nThank you for your generous donation {}.\n \n\n\t\tSincerely, \n\t\tLocal Charity". \
            format(self.name, self.latest_donation)
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)
Ejemplo n.º 14
0
class DonorDonations(object):
    """
    Class to hold the records of a donor and their donations.
    """

    # Class attributes
    # It becomes apparent when looking at the constructor and the format we will be working with.
    # Need to work with the data in JSON format - here we will use:
    # string --> Donor name
    donor_name = js.String()
    # list --> Donations made by donor
    donations = js.List()
    # May not be needed but adding in case need it
    initial_state = False

    # Constructor - take in the name of the donor and donations
    def __init__(self, donor_name, donations=None):
        """Constructor for instantiating a donor."""
        # Follow the example in example_dec.py
        # self.donor_name = donor_name
        # self.donations = []
        self.donor_name = donor_name
        if donations is None:
            self.donations = []
        else:
            self.donations = list(donations)

    @property
    def first_name(self):
        forename = self.donor_name.split()
        return forename[0]

    @property
    def last_name(self):
        surname = self.donor_name.split()
        return surname[1]

    @property
    def last_donation(self):
        """Grab the most recent donation from the list of donations."""
        try:
            # We want the last donation so we want to use the negative index
            return self.donations[-1]
        except IndexError:
            return None

    @property
    def total_donations(self):
        """Total up all the donations that were made by a donor."""
        return sum(self.donations)

    @property
    def average_donation(self):
        """Take the total_donations that were calculated and divide by the amount of
        donations made using len() on the donations list."""
        return self.total_donations / len(self.donations)

    def letter_template(self):
        """Template for writing a letter to a donor, thanking them for their donation."""
        return """Dear {}{},\n
        Thank you for your very kind donation of ${:.2f}.\n\n
        It will be put to very good use.\n\n \t\tSincerely,\n\t\t\t
        -The Team""".format(self.first_name, self.last_name,
                            self.last_donation)
Ejemplo n.º 15
0
class Donor(object):

    name = js.String()
    donations = js.List()

    def __init__(self, name, donations=None):
        if not name:
            raise ValueError("Donor name cannot be empty.")
        self.name = name
        if not donations:
            self.donations = []
        else:
            self.donations = donations

    @property
    def first(self):
        name_sp = self.name.split()
        if len(name_sp) == 1:
            return ''
        else:
            return name_sp[0]

    @property
    def last(self):
        name_sp = self.name.split()
        if len(name_sp) == 1:
            return self.name
        else:
            return ' '.join(name_sp[1:])

    def add_donation(self, amount):
        if float(amount) <= 0:
            raise ValueError('Donation amount must be a positive number.')
        else:
            self.donations.append(amount)

    @property
    def last_donation(self):
        if not self.donations:
            return None
        else:
            return self.donations[-1]

    def generate_letter(self):
        """
        Generates a Thank You letter to send to a donor. Uses the last value in their donations list to
        mention their last donation amount.
        :param donor: a donor dictionary entry
        :return: string containing the text of the Thank You letter.
        """
        format_string = """
Dear {first_name} {last_name},

   Thank you for your donation of ${last_donation:.2f}.

            Warmest Regards,
                Local Charity
"""
        return format_string.format(last_donation=float(self.last_donation),
                                    first_name=self.first,
                                    last_name=self.last)
Ejemplo n.º 16
0
class Donor():

    first_name = js.String()
    last_name = js.String()
    donations = js.List()

    def __init__(self, first, last, amount):
        self.first_name = first
        self.last_name = last
        if type(amount) is list:
            self.donations = amount
        else:
            self.donations = [amount]

    def add_donation(self, amount):
        if type(amount) is list:
            self.donations.extend(amount)
        else:
            self.donations.append(amount)

    def challenge(self, factor, min_donation=None, max_donation=None):
        if min_donation is not None:
            self.donations = list(
                filter(lambda x: x > min_donation, self.donations))
        if max_donation is not None:
            self.donations = list(
                filter(lambda x: x < max_donation, self.donations))
        self.donations = list(map(lambda x: x * factor, self.donations))

    @property
    def total(self):
        return sum(self.donations)

    @property
    def count(self):
        return len(self.donations)

    @property
    def average(self):
        if self.count == 0:
            return 0
        else:
            return self.total / self.count

    def __lt__(self, other):
        return self.total < other.total

    def __le__(self, other):
        return self.total <= other.total

    def __eq__(self, other):
        return self.total == other.total

    def __ge__(self, other):
        return self.total >= other.total

    def __gt__(self, other):
        return self.total > other.total

    def __ne__(self, other):
        return self.total != other.total