Ejemplo n.º 1
0
    def setUp(self):
        super(AddEstimates, self).setUp()
        self.login_as_member('new')

        # use post training project to require estimates
        membership = models.Membership.objects.get(
            member_id=self.member_id, giving_project_id=self.post_id)
        member = models.Member.objects.get(pk=self.member_id)
        member.current = membership.pk
        member.save()

        # create donors without estimates
        donor = models.Donor(firstname='Al',
                             lastname='Bautista',
                             membership=membership)
        donor.save()
        self.donor_id1 = donor.pk
        donor = models.Donor(firstname='Velcro',
                             lastname='Cat',
                             membership=membership)
        donor.save()
        self.donor_id2 = donor.pk

        # set up base form POST data given 2 donors we just created
        self.base_form_data = {
            'form-MAX_NUM_FORMS': 2,
            'form-INITIAL_FORMS': 2,
            'form-TOTAL_FORMS': 2,
            'form-0-donor': unicode(self.donor_id1),
            'form-0-amount': u'',
            'form-0-likelihood': u'',
            'form-1-donor': unicode(self.donor_id2),
            'form-1-amount': u'',
            'form-1-likelihood': u'',
        }
Ejemplo n.º 2
0
    def test_estimates_done(self):
        """ Verify add estimates form is not shown if contacts have estimates """

        # use post-training membership
        membership = models.Membership.objects.get(pk=self.post_id)
        member = membership.member
        member.current = self.post_id
        member.save()

        # create contacts with amount & likelihood
        contact = models.Donor(firstname='Anna',
                               membership=membership,
                               amount=0,
                               likelihood=0)
        contact.save()
        contact = models.Donor(firstname='Banana',
                               membership=membership,
                               amount=567,
                               likelihood=34)
        contact.save()

        response = self.client.get(self.url)

        # verify estimates form is not shown
        self.assertTemplateNotUsed('fund/forms/add_estimates.html')
        self.assertEqual(response.context['request'].membership, membership)
Ejemplo n.º 3
0
    def setUp(self):
        super(OverdueEmails, self).setUp()
        self.login_as_member('new')

        # create 2 donors on new member's pre membership
        donor = models.Donor(firstname='En', membership_id=self.pre_id)
        donor.save()
        self.donor1 = donor.pk
        donor = models.Donor(firstname='Tva', membership_id=self.pre_id)
        donor.save()
        self.donor2 = donor.pk

        # create another member, membership, donor
        member = models.Member.objects.create_with_user(email='*****@*****.**',
                                                        first_name='Two',
                                                        last_name='Dos')
        member.save()
        gp = models.GivingProject.objects.get(title='Post training')
        membership = models.Membership(giving_project=gp,
                                       member=member,
                                       approved=True)
        membership.save()
        donor = models.Donor(firstname='Tre', membership=membership)
        donor.save()
        self.donor3 = donor.pk
Ejemplo n.º 4
0
    def test_merge_duplicates(self):
        """ Verify that duplicate contacts are merged before form is displayed

      Add duplicates in all 3 ways (last, phone, email).
    """
        unique_donors = models.Donor.objects.filter(
            membership__member_id=self.member_id).count()
        self.assertEqual(unique_donors, 8)

        expect_to_contain = []

        # create copies of existing donors from fixtures
        # match by first + last name, add notes
        donor = models.Donor.objects.get(pk=1)
        self.assertTrue(donor.lastname)
        self.assertEqual(donor.notes, '')
        copy = models.Donor(membership_id=self.ship_id,
                            firstname=donor.firstname,
                            lastname=donor.lastname,
                            notes='Beep.')
        copy.save()
        expect_to_contain += [donor.firstname, donor.lastname, copy.notes]

        # match by first + email
        donor = models.Donor.objects.get(pk=2)
        self.assertTrue(donor.email)

        copy = models.Donor(membership_id=self.ship_id,
                            firstname=donor.firstname,
                            email=donor.email)
        copy.save()
        expect_to_contain += [donor.firstname, donor.email]

        # match by first + phone, add last name
        donor = models.Donor.objects.get(pk=3)
        self.assertEqual(donor.lastname, '')
        self.assertTrue(donor.phone)
        copy = models.Donor(membership_id=self.ship_id,
                            firstname=donor.firstname,
                            lastname='Surname',
                            phone=donor.phone)
        copy.save()
        expect_to_contain += [donor.firstname, copy.lastname, donor.phone]

        res = self.client.get(self.get_url, follow=True)

        self.assertEqual(res.status_code, 200)
        self.assertTemplateUsed(res, self.template)

        formset = res.context['formset']

        self.assertEqual(formset.initial_form_count(), unique_donors)
        for expected_string in expect_to_contain:
            self.assertContains(res, expected_string, 1)
Ejemplo n.º 5
0
    def test_gift_notifications(self):
        # enter gift received from donor
        test_donor = models.Donor.objects.get(pk=self.donor_id)
        test_donor.received_this = 100
        test_donor.save()

        member = models.Member.objects.create_with_user(email='*****@*****.**',
                                                        password='******',
                                                        first_name='A',
                                                        last_name='B')
        membership = models.Membership(member=member, giving_project_id=1)
        membership.save()
        donor = models.Donor(membership=membership,
                             firstname='Greta',
                             lastname='Polkis',
                             received_next=55)
        donor.save()

        # run cron task
        response = self.client.get(self.cron_url, follow=True)
        self.assertEqual(response.status_code, 200)

        # verify notification shows
        response = self.client.get(self.url, follow=True)

        self.assertTemplateUsed(response, 'fund/home.html')
        self.assertContains(response, 'gift or pledge received')
        self.assertContains(response, unicode(test_donor))

        # verify notification doesn't show on reload
        response = self.client.get(self.url, follow=True)

        self.assertTemplateUsed(response, 'fund/home.html')
        self.assertNotContains(response, 'gift or pledge received')

        # verify emails sent
        self.assertEqual(len(mail.outbox), 2)
        testacct_emailed = False
        abcd_emailed = False
        for email in mail.outbox:
            self.assertIn('gift or pledge received', email.body)
            if email.to == [member.user.username]:
                self.assertFalse(abcd_emailed)
                self.assertIn(unicode(donor), email.body)
                self.assertNotIn(unicode(test_donor), email.body)
                abcd_emailed = True
            elif email.to == [self.email]:
                self.assertFalse(testacct_emailed)
                self.assertIn(unicode(test_donor), email.body)
                self.assertNotIn(unicode(donor), email.body)
                testacct_emailed = True
            else:
                self.fail(
                    'Unexpected gift notification email recipient: {}'.format(
                        email.to))

        self.assertTrue(abcd_emailed)
        self.assertTrue(testacct_emailed)
Ejemplo n.º 6
0
    def test_contacts_without_est(self):
        """ Going to home page with contacts that do not have estimates """

        # using pre-training membership
        membership = models.Membership.objects.get(pk=self.pre_id)

        # create contacts without amount or likelihood
        contact1 = models.Donor(firstname='Anna', membership=membership)
        contact1.save()
        contact2 = models.Donor(firstname='Banana', membership=membership)
        contact2.save()

        response = self.client.get(self.url)

        # verify estimates form is not shown
        self.assertEqual(response.context['request'].membership, membership)
        self.assertTemplateNotUsed('fund/forms/add_estimates.html')

        # using post-training membership
        member = membership.member
        member.current = self.post_id
        member.save()

        membership = models.Membership.objects.get(pk=self.post_id)

        # move created contacts to current membership
        contact1.membership = membership
        contact1.save()
        contact2.membership = membership
        contact2.save()

        response = self.client.get(self.url, follow=True)

        # verify estimates form is shown
        self.assertTemplateUsed('fund/forms/add_estimates.html')
        self.assertEqual(response.context['request'].membership, membership)
Ejemplo n.º 7
0
    def test_same_member(self):
        """ overdue step in two memberships for same member """
        donor = models.Donor(membership_id=self.post_id, firstname='Other')
        donor.save()

        step = models.Step(donor_id=self.donor1,
                           date=timezone.now() - timedelta(days=3))
        step.save()
        step = models.Step(donor=donor,
                           date=timezone.now() - timedelta(days=9))
        step.save()

        self.assertEqual(len(mail.outbox), 0)
        response = self.client.get(self.url, follow=True)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(mail.outbox), 2)
Ejemplo n.º 8
0
    def setup_member(self, member):
        self.member_id = member.pk

        post_gp = models.GivingProject.objects.get(title="Post training")
        post_ship = models.Membership(giving_project=post_gp,
                                      member=member,
                                      approved=True)
        post_ship.save()

        if member.first_name == 'current':
            self.ship_id = post_ship.pk
            member.current = post_ship.pk
            member.save()

            # create donor & step
            donor = models.Donor(membership=post_ship,
                                 firstname='Anna',
                                 amount=500,
                                 talked=True,
                                 likelihood=50)
            donor.save()
            step = models.Step(donor=donor,
                               description='Talk to about project',
                               created=timezone.now(),
                               date='2013-04-06')
            step.save()
            self.donor_id = donor.pk
            self.step_id = step.pk

        elif member.first_name == 'new':
            self.post_id = post_ship.pk

            pre_gp = models.GivingProject.objects.get(title='Pre training')
            pre_ship = models.Membership(giving_project=pre_gp,
                                         member=member,
                                         approved=True)
            pre_ship.save()
            self.pre_id = self.ship_id = pre_ship.pk

            member.current = pre_ship.pk
            member.save()

        else:
            raise Exception('setup_member got unexpected name: {}'.format(
                member.first_name))
Ejemplo n.º 9
0
    def test_basic(self):
        # membership with a few donors, some progress
        self.login_as_member('new')
        ship_id = self.post_id

        # first donor
        donor = models.Donor(membership_id=ship_id,
                             firstname='Alice',
                             amount=240,
                             likelihood=75,
                             talked=True)
        donor.save()
        step = models.Step(donor=donor,
                           date='2015-04-01',
                           description='Talk',
                           completed='2015-04-01')
        step.save()
        step = models.Step(donor=donor, date='2015-5-25', description='Ask')
        step.save()

        # second donor
        donor = models.Donor(membership_id=ship_id,
                             firstname='Bab',
                             talked=True,
                             amount=300,
                             likelihood=50,
                             asked=True,
                             promised=300,
                             received_this=100,
                             received_next=100)
        donor.save()
        step = models.Step(donor=donor,
                           date='2015-04-01',
                           description='Ask',
                           completed='2015-04-01',
                           asked=True)
        step.save()
        step = models.Step(donor=donor,
                           date='2015-04-08',
                           description='Follow upt',
                           completed='2015-04-08',
                           promised=300)
        step.save()
        step = models.Step(donor=donor, date='2015-5-25', description='Thank')
        step.save()

        donors = models.Donor.objects.filter(
            membership_id=ship_id).prefetch_related('step_set')

        progress, incomplete_steps = _compile_membership_progress(donors)

        self.assertIsInstance(progress, dict)
        self.assertEqual(progress['estimated'], 330)
        self.assertEqual(progress['contacts'], 2)
        self.assertEqual(progress['asked'], 1)
        self.assertEqual(progress['talked'], 1)
        self.assertEqual(progress['promised'], 100)
        self.assertEqual(progress['received'], 200)

        self.assertEqual(progress['contacts_remaining'], 0)
        self.assertEqual(progress['togo'], 30)

        self.assertEqual(len(incomplete_steps), 2)
        for donor in donors:
            self.assertIsInstance(donor.next_step, models.Step)
            self.assertIs(type(donor.completed_steps), list)
            self.assertTrue(len(donor.completed_steps) > 0)
Ejemplo n.º 10
0
def add_mult(request):
    """ Add multiple contacts, with or without estimates

    If a user enters duplicates (same first & last name), they'll get a
      confirmation form before donors are saved

    GET is via redirect from home, and should render top blocks as well as form
    POST will be via AJAX and does not need block info
  """
    membership = request.membership

    est = membership.giving_project.require_estimates()
    if est:
        contact_formset = formset_factory(forms.MassDonor, extra=5)
    else:
        contact_formset = formset_factory(forms.MassDonorPre, extra=5)

    empty_error = u''

    if request.method == 'POST':
        membership.last_activity = timezone.now()
        membership.save()

        formset = contact_formset(request.POST)

        if formset.is_valid():

            if formset.has_changed():
                logger.info('AddMult valid formset')

                # get list of existing donors to check for duplicates
                donors = models.Donor.objects.filter(membership=membership)
                donors = [unicode(donor) for donor in donors]
                duplicates = []

                for form in formset.cleaned_data:
                    if form:  # ignore blank rows
                        confirm = form['confirm'] and form['confirm'] == '1'

                        if not confirm and (form['firstname'] + ' ' +
                                            form['lastname'] in donors):
                            # this entry is a duplicate that has not yet been confirmed
                            initial = {
                                'firstname': form['firstname'],
                                'lastname': form['lastname'],
                                'confirm': u'1'
                            }
                            if est:
                                initial['amount'] = form['amount']
                                initial['likelihood'] = form['likelihood']
                            duplicates.append(initial)

                        else:  # not a duplicate
                            if est:
                                contact = models.Donor(
                                    membership=membership,
                                    firstname=form['firstname'],
                                    lastname=form['lastname'],
                                    amount=form['amount'],
                                    likelihood=form['likelihood'])
                            else:
                                contact = models.Donor(
                                    membership=membership,
                                    firstname=form['firstname'],
                                    lastname=form['lastname'])
                            contact.save()
                            logger.info('contact created')

                if duplicates:
                    logger.info('Showing confirmation page for duplicates: ' +
                                str(duplicates))
                    empty_error = (
                        u'<ul class="errorlist"><li>The contacts below have the '
                        'same name as contacts you have already entered. Press submit again '
                        'to confirm that you want to add them.</li></ul>')
                    if est:
                        contact_formset = formset_factory(forms.MassDonor)
                    else:
                        contact_formset = formset_factory(forms.MassDonorPre)
                    formset = contact_formset(initial=duplicates)

                else:  # saved successfully (no duplicates check needed)
                    return HttpResponse("success")

            else:  # empty formset
                empty_error = u'<ul class="errorlist"><li>Please enter at least one contact.</li></ul>'

        else:  # invalid formset
            logger.info(formset.errors)

        return render(request, 'fund/forms/add_contacts.html', {
            'formset': formset,
            'empty_error': empty_error
        })

    else:  # GET
        formset = contact_formset()
        steps, news, grants = _get_block_content(membership)
        header = membership.giving_project.title

        return render(
            request, 'fund/forms/add_contacts.html', {
                '1active': 'true',
                'header': header,
                'news': news,
                'grants': grants,
                'steps': steps,
                'formset': formset
            })
Ejemplo n.º 11
0
def copy_contacts(request):

    # base formset
    copy_formset = formset_factory(forms.CopyContacts, extra=0)

    if request.method == 'POST':
        logger.info(request.POST)

        if 'skip' in request.POST:
            logger.info('User skipping copy contacts')
            request.membership.copied_contacts = True
            request.membership.save()
            return HttpResponse('success')

        else:
            formset = copy_formset(request.POST)
            logger.info('Copy contracts submitted')
            if formset.is_valid():
                for form in formset.cleaned_data:
                    if form['select']:
                        contact = models.Donor(membership=request.membership,
                                               firstname=form['firstname'],
                                               lastname=form['lastname'],
                                               phone=form['phone'],
                                               email=form['email'],
                                               notes=form['notes'])
                        contact.save()
                        logger.debug('Contact created')
                request.membership.copied_contacts = True
                request.membership.save()
                return HttpResponse('success')
            else:  # invalid
                logger.warning('Copy formset somehow invalid?! ' +
                               str(request.POST))
                logger.warning(formset.errors)

    else:  # GET
        all_donors = (models.Donor.objects.filter(
            membership__member=request.membership.member).order_by(
                'firstname', 'lastname', '-added'))

        # extract name, contact info, notes. handle duplicates
        initial_data = []
        for donor in all_donors:
            if (initial_data
                    and donor.firstname == initial_data[-1]['firstname'] and
                (donor.lastname
                 and donor.lastname == initial_data[-1]['lastname']
                 or donor.phone and donor.phone == initial_data[-1]['phone']
                 or donor.email and donor.email == initial_data[-1]['email'])):
                logger.info('Duplicate found! ' + str(donor))
                initial_data[-1]['lastname'] = initial_data[-1][
                    'lastname'] or donor.lastname
                initial_data[-1][
                    'phone'] = initial_data[-1]['phone'] or donor.phone
                initial_data[-1][
                    'email'] = initial_data[-1]['email'] or donor.email
                initial_data[-1]['notes'] += donor.notes
                initial_data[-1]['notes'] = initial_data[-1][
                    'notes'][:253]  # cap below field char limit

            else:  # not duplicate; add a row
                initial_data.append({
                    'firstname': donor.firstname,
                    'lastname': donor.lastname,
                    'phone': donor.phone,
                    'email': donor.email,
                    'notes': donor.notes
                })

        logger.debug('Loading copy contacts formset')
        logger.info('Initial data list of ' + str(len(initial_data)))
        formset = copy_formset(initial=initial_data)

    return render(request, 'fund/forms/copy_contacts.html',
                  {'formset': formset})