예제 #1
0
    def post(self):
        target_year = int(self.request.get("year"))
        s = tools.getKey(self.request.get("skey"))
        mode = self.request.get("mode")

        td1 = datetime(target_year, 1, 1, 0, 0)
        td2 = datetime(target_year, 12, 31, 0, 0)

        annual_donations = models.Donation.query(models.Donation.settings == s,
                                                 models.Donation.donation_date >= td1,
                                                 models.Donation.donation_date <= td2)

        all_contacts = set([d.contact for d in annual_donations])

        with_email = []
        without_email = []
        missing_contacts = []

        for c_key in all_contacts:
            c = c_key.get()
            if not c:
                missing_contacts.append(c_key)

            else:

                if c.email != ['']:
                    with_email.append(c)

                else:
                    donation_total = c.data.donation_total
                    if donation_total >= tools.toDecimal("250"):
                        without_email.append(c)

                    elif c.data.number_donations == 1 and donation_total >= tools.toDecimal("100"):
                        without_email.append(c)

        body = ""

        body += "\n" + "#### " + str(len(with_email)) + " Donors with Email Addresses ####"
        for c in with_email:
            body += "\n" + c.websafe

        body += "\n" + "\n\n\n#### " + str(len(without_email)) + " Donors WITHOUT Email Addresses ####"
        for c in without_email:
            body += "\n" + "https://ghidonations.appspot.com/reports/donor?c=" + c.websafe + "&y=2013"

        body += "\n" + "\n\n\n#### " + str(len(missing_contacts)) + " Missing Contacts ####"
        for c in missing_contacts:
            body += "\n" + str(c)

        # Writing text file
        gcs_file_key, gcs_file = tools.newFile("text/plain", "GHI_Donations_" + str(target_year) + ".txt")
        gcs_file.write(body)
        gcs_file.close()
예제 #2
0
    def task(self, isAdmin, s):
        try:

            contact_key = self.request.get("c")
            year = int(self.request.get("y"))

            if contact_key == "" or year == "" or len(str(year)) != 4:
                # Throw an error if you don't have those two pieces of info or if the year isn't a number
                raise Exception("Don't know contact key or year.")

            c = tools.getKey(contact_key).get()
            s = c.settings.get()

            donations = c.data.annual_donations(year)
            donation_total = tools.toDecimal(0)

            for d in donations:
                donation_total += d.confirmation_amount

            donation_total = "${:,.2f}".format(donation_total)

            template_variables = {"s": s, "c": c, "donations": donations, "year": str(year),
                                  "donation_total": str(donation_total), "street": c.address[0], "city": c.address[1],
                                  "state": c.address[2], "zip": c.address[3]}

            self.response.write(
                template.render("pages/letters/donor_report_print.html", template_variables))


        except:
            # If there's a malformed URL, give a 500 error
            self.error(500)
            self.response.write(
                template.render('pages/letters/thankyou_error.html', {}))
예제 #3
0
    def new_offline_donation(self, req):
        message = "Offline donation created"
        success = True

        isAdmin, s = tools.checkAuthentication(self, True, from_endpoints=True)

        # Make req variables local
        name, email, amount_donated, notes, address, team_key, individual_key, \
        add_deposit = req.name, req.email, tools.toDecimal(req.amount_donated), req.notes, \
                      req.address, req.team_key, req.individual_key, req.add_deposit

        # Check for null value in individual field
        if individual_key == "none":
            individual_key = None

        if address:
            address = [address.street, address.city, address.state, address.zipcode]

        if team_key:
            team_key = tools.getKey(team_key)

        if individual_key:
            individual_key = tools.getKey(individual_key)

        s.create.donation(name, email, amount_donated, "offline", address=address, team_key=team_key,
                          individual_key=individual_key, add_deposit=add_deposit, special_notes=notes)

        return SuccessMessage_Out(success=success, message=message)
예제 #4
0
    def _run(self):

        # Scheduled cron job to update analytics for all settings accounts every hour
        all_settings = models.Settings.query()
        for s in all_settings:

            ## Update one_week_history
            last_week = datetime.today() - timedelta(days=7)

            # Get donations made in the last week
            donations = models.Donation.gql(
                "WHERE settings = :s AND donation_date > :last_week ORDER BY donation_date DESC",
                s=s.key, last_week=last_week)

            donation_count = 0
            total_money = tools.toDecimal(0)

            for d in donations:
                # Counting total money
                total_money += d.amount_donated

                # Counting number of donations
                donation_count += 1

            one_week_history = [donation_count, str(total_money)]
            s.one_week_history = json.dumps(one_week_history)

            #####################################################################################################

            ## Update one_month_history
            last_week = datetime.today() - timedelta(days=30)

            # Get donations made in the last week
            donations = models.Donation.gql(
                "WHERE settings = :s AND donation_date > :last_week ORDER BY donation_date DESC",
                s=s.key, last_week=last_week)

            one_month_history = [["Date", "Amount Donated ($)"]]
            donations_dict = {}

            for d in donations:
                d_date = tools.convertTime(d.donation_date)
                day = str(d_date.month).zfill(2) + "/" + str(d_date.day).zfill(2)

                if day in donations_dict:
                    donations_dict[day] += d.amount_donated
                else:
                    donations_dict[day] = d.amount_donated

            for date in sorted(donations_dict.iterkeys()):
                one_month_history.append([date, float(donations_dict[date])])

            s.one_month_history = json.dumps(one_month_history)

            s.put()
예제 #5
0
    def post(self):
        contact_key = self.request.get("contact_key")
        year = self.request.get("year")
        c = tools.getKey(contact_key).get()

        logging.info("AnnualReport handler hit with contact key " + contact_key + " and year " + year)

        if c.email:

            message = mail.EmailMessage()

            try:
                email = c.email[0]
            except:
                email = c.email

            message.to = email
            message.sender = "Global Hope India <*****@*****.**>"
            message.subject = str(year) + " Global Hope India Donations"

            donations = c.data.annual_donations(year)
            donation_total = tools.toDecimal(0)

            for d in donations:
                donation_total += d.confirmation_amount

            donation_total = "${:,.2f}".format(donation_total)

            template_variables = {"s": c.settings.get(), "c": c, "donations": donations, "year": year,
                                  "donation_total": str(donation_total)}

            message.html = template.render("pages/letters/donor_report.html", template_variables)
            message.send()

            logging.info("Annual report sent to:" + c.name)

        else:
            logging.info("Annual report not sent sent because " + c.name + "doesn't have an email.")
예제 #6
0
    def update(self, name, email, team_list, description, change_image, password, show_donation_page,
               show_progress_bar):
        name_changed = False
        show_donation_changed = False

        if name != self.name:
            self.name = name
            name_changed = True

        if email:
            if email != self.email:
                self.email = email

            if password != None and password != "" and self.password != password:
                self.password = password

        else:
            self.email = None
            self.password = None

        if show_donation_page != self.show_donation_page:
            self.show_donation_page = show_donation_page
            show_donation_changed = True

        if show_progress_bar != self.show_progress_bar:
            self.show_progress_bar = show_progress_bar
            show_donation_changed = True

        # Initializes DictDiffer object to tell differences from current dictionary to server-side one
        team = json.loads(team_list)
        dd = tools.DictDiffer(team, self.data.team_list)

        for key in dd.added():
            new_tl = TeamList()
            new_tl.individual = self.key
            new_tl.team = tools.getKey(key)
            new_tl.fundraise_amt = tools.toDecimal(team[key][1])

            new_tl.put()

        for key in dd.removed():
            query = TeamList.gql("WHERE team = :t AND individual = :i", t=tools.getKey(key), i=self.key)
            tl = query.fetch(1)[0]

            for d in tl.data.donations:
                d.team = None
                d.put()

            tl.key.delete()

        for key in dd.changed():
            query = TeamList.gql("WHERE team = :t AND individual = :i", t=tools.getKey(key), i=self.key)

            tl = query.fetch(1)[0]
            tl.fundraise_amt = tools.toDecimal(team[key][1])
            tl.put()

        if description != self.description:
            self.description = description

        if change_image != None:
            # If change_image = None, there isn't any change. If it isn't, it
            # contains a
            if self.photo != None:
                # Delete old blob to keep it from orphaning
                old_blobkey = self.photo
                old_blob = blobstore.BlobInfo.get(old_blobkey)
                old_blob.delete()

            self.photo = change_image

        try:
            if name_changed or show_donation_changed:
                for tl in self.teamlist_entities:

                    if name_changed == True:
                        tl.sort_name = name

                    if show_donation_changed:
                        tl.show_donation_page = show_donation_page
                        tl.show_progress_bar = show_progress_bar

                    tl.put()
        except:
            pass

        self.put()

        if name_changed:
            # Reindexing donations on name change
            taskqueue.add(url="/tasks/reindex", params={'mode': 'team', 'key': self.websafe}, countdown=1,
                          queue_name="backend")
예제 #7
0
 def _from_base_type(self, value):
     return tools.toDecimal(value)
예제 #8
0
    def post(self):
        # Below URL used for the live version.
        PP_URL = "https://www.paypal.com/cgi-bin/webscr"

        # Below URL used for testing with the sandbox - if this is uncommented, all real
        # donations will not be authenticated. ONLY use with dev versions.
        # PP_URL = "https://www.sandbox.paypal.com/cgi-bin/webscr"

        # Gets all account emails from Settings data models
        # to authenticate PayPal (don't accept payment from unknown)
        all_account_emails = tools.getAccountEmails()

        parameters = None
        if self.request.POST:
            parameters = self.request.POST.copy()
        if self.request.GET:
            parameters = self.request.GET.copy()

        payment_status = self.request.get("payment_status")
        logging.info("Payment status: " + payment_status)

        # Check payment is completed, not Pending or Failed.
        if payment_status == "Failed" or payment_status == "Pending":
            logging.error("Payment status is " + payment_status + ", so not continuing.")

        else:
            logging.info("All parameters: " + str(parameters))

            # Check the IPN POST request came from real PayPal, not from a fraudster.
            if parameters:
                parameters['cmd'] = '_notify-validate'

                # Encode the parameters in UTF-8 out of Unicode
                str_parameters = {}
                for k, v in parameters.iteritems():
                    str_parameters[k] = unicode(v).encode('utf-8')

                params = urllib.urlencode(str_parameters)
                status = urlfetch.fetch(
                    url=PP_URL,
                    method=urlfetch.POST,
                    payload=params,
                ).content
                if not status == "VERIFIED":
                    logging.debug("PayPal returned status:" + str(status))
                    logging.debug('Error. The request could not be verified, check for fraud.')
                    parameters['homemadeParameterValidity'] = False

            # Comparing receiver email to list of allowed email addresses
            try:
                receiver_email = parameters['receiver_email']
                authenticated = False
                settings = None

                # If the receiver_email isn't in the database, this will fail
                settings = all_account_emails[receiver_email]
                authenticated = True
                logging.info("Getting payment to account: " + receiver_email + ", #: " + settings)

            except:
                authenticated = False
                logging.info("No match for incoming payment email address. Not continuing.")

            # Make sure money is going to the correct account - otherwise fraudulent
            if authenticated == True:
                # Currency of the donation
                # currency = parameters['mc_currency']

                s = tools.getKey(settings).get()
                ipn_data = str(parameters)

                # Email and payer ID  numbers
                try:
                    email = parameters['payer_email']
                except:
                    email = None

                try:
                    name = parameters['first_name'] + " " + parameters['last_name']
                except:
                    name = "Anonymous Donor"

                # Check if an address was given by the donor
                try:
                    # Stich all the address stuff together
                    address = [parameters['address_street'], parameters['address_city'], parameters['address_state'],
                               parameters['address_zip']]

                except:
                    address = None

                # Reading designation and notes values encoded in JSON from
                # donate form
                decoded_custom = None

                try:
                    decoded_custom = json.loads(parameters["custom"])

                    team_key = tools.getKeyIfExists(decoded_custom[0])
                    individual_key = tools.getKeyIfExists(decoded_custom[1])
                    special_notes = decoded_custom[2]

                    if s.exists.entity(team_key) == False:
                        team_key = None
                    if s.exists.entity(individual_key) == False:
                        individual_key = None

                except:
                    logging.error("Excepted on designation.")
                    team_key = None
                    individual_key = None
                    special_notes = None

                try:
                    cover_trans = decoded_custom[3]
                    email_subscr = decoded_custom[4]
                except:
                    cover_trans = False
                    email_subscr = False

                try:
                    phone = parameters['contact_phone']

                    if len(phone) > 10:
                        special_notes += "\nContact phone: " + phone
                        phone = None
                except:
                    logging.info("Excepted on phone number.")
                    phone = None

                confirmation_amount = tools.toDecimal(0)
                amount_donated = tools.toDecimal(0)
                try:
                    confirmation_amount = parameters['mc_gross']
                    amount_donated = float(parameters['mc_gross']) - float(parameters['mc_fee'])

                except:
                    pass

                # Find out what kind of payment this was - recurring, one-time, etc.
                try:
                    payment_type = parameters['txn_type']
                except:
                    logging.info("Txn_type not available, so continuing with payment status")
                    payment_type = payment_status

                if payment_type == "recurring_payment_profile_created" or payment_type == "subscr_signup":
                    logging.info("This is the start of a recurring payment. Create info object.")

                    payment_id = parameters['subscr_id']

                    # Duration between payments
                    duration = "recurring"

                    # s.create.recurring_donation(payment_id, duration, ipn_data)

                elif payment_type == "recurring_payment" or payment_type == "subscr_payment":
                    logging.info("This is a recurring donation payment.")

                    payment_id = parameters['subscr_id']
                    payment_type = "recurring"

                    # Create a new donation
                    s.create.donation(name, email, amount_donated, payment_type,
                                      confirmation_amount=confirmation_amount,
                                      phone=phone, address=address, team_key=team_key, individual_key=individual_key,
                                      payment_id=payment_id, special_notes=special_notes, email_subscr=email_subscr,
                                      ipn_data=ipn_data)

                elif payment_type == "web_accept":
                    logging.info("This is a one-time donation.")

                    if payment_status == "Completed":
                        payment_id = parameters['txn_id']

                        # Create a new donation
                        s.create.donation(name, email, amount_donated, "one-time",
                                          confirmation_amount=confirmation_amount, address=address,
                                          team_key=team_key, individual_key=individual_key, payment_id=payment_id,
                                          special_notes=special_notes,
                                          email_subscr=email_subscr, ipn_data=ipn_data)

                    else:
                        logging.info("Payment status not complete.  Not logging the donation.")

                elif payment_type == "subscr_cancel":
                    logging.info("A subscriber has cancelled.")
                    amount_donated = "N/A"

                elif payment_type == "subscr_failed":
                    logging.info("A subscriber payment has failed.")
                    amount_donated = "N/A"

                elif payment_type == "Refunded":
                    try:
                        donation = models.Donation.gql("WHERE payment_id = :t", t=parameters["txn_id"])
                        donation_key = donation[0].key()

                        donation_key.delete()
                        logging.info("Refund detected and donation deleted. (" + donation_key.urlsafe() + ")")
                    except:
                        logging.info("Donation tried to be deleted, but failed. Most likely already deleted.")

                try:
                    logging.info("Recording IPN")
                    logging.info("Payment type: " + payment_type)
                    logging.info("Name: " + name)
                    logging.info("Email: " + email)
                    logging.info("Amount donated: " + str(amount_donated))
                except:
                    logging.error("Failed somewhere in the logs.")
예제 #9
0
    def task(self, isAdmin, s):

        # WARNING - this is a complicated and kind of a hacked-together
        # solution. I didn't understand it the day after I wrote it.
        # ... But it works. 

        deposit_key = self.request.get("d")
        deposit = tools.getKey(deposit_key).get()

        entity_keys = deposit.entity_keys
        gross_amount = tools.toDecimal(0)
        net_amount = tools.toDecimal(0)
        general_fund = tools.toDecimal(0)

        donations = []
        team_breakout = {}

        for k in entity_keys:
            d = k.get()
            if d != None:
                donations.append(d)

                gross_amount += d.confirmation_amount
                net_amount += d.amount_donated

                if d.team:
                    t = d.team.get()
                    try:
                        team_breakout[t.name]
                    except:
                        team_breakout[t.name] = [tools.toDecimal(0), []]

                    team_breakout[t.name][0] += d.amount_donated

                    if d.individual:
                        i = d.individual.get()
                        array = [i.name, d.amount_donated]

                        team_breakout[t.name][1].append(array)
                else:
                    # Add count to general fund
                    general_fund += d.amount_donated

        team_breakout["General Fund"] = [tools.toDecimal(general_fund), []]

        new_team_breakout = {}
        for k, v in team_breakout.items():
            name = k
            amount_donated = v[0]
            array = v[1]
            new_array = []

            for a in array:
                string = a[0] + " ($" + str(a[1]) + ")"
                new_array.append(string)

            new_team_breakout[unicode(name) + " ($" + str(amount_donated) + ")"] = new_array

        template_variables = {"d": deposit, "donations": donations, "team_breakout": new_team_breakout,
                              "gross_amount": gross_amount, "net_amount": net_amount}
        self.response.write(
            template.render('pages/deposit.html', template_variables))