Exemplo n.º 1
0
def dues16_listing(request):
    """
    a listing of all invoices for the 2016 dues run.
    shall show both active/valid and cancelled/invalid invoices.
    """
    # get them all from the DB
    dues16_invoices = Dues16Invoice.get_all()

    return {
        'count': len(dues16_invoices),
        '_today': date.today(),
        'invoices': dues16_invoices,
    }
Exemplo n.º 2
0
def dues16_listing(request):
    """
    a listing of all invoices for the 2016 dues run.
    shall show both active/valid and cancelled/invalid invoices.
    """
    # get them all from the DB
    dues16_invoices = Dues16Invoice.get_all()

    return {
        'count': len(dues16_invoices),
        '_today': date.today(),
        'invoices': dues16_invoices,
    }
    def test_dues16_reduction(self):
        """
        test the dues16_reduction functionality
        """
        # have to accept their membersip first
        m1 = C3sMember.get_by_id(1)  # german normal member
        m1.membership_accepted = True
        m2 = C3sMember.get_by_id(2)  # english normal member
        m2.membership_accepted = True

        self.config.add_route('make_dues16_invoice_no_pdf', '/')
        self.config.add_route('make_dues16_reversal_invoice_pdf', '/')
        self.config.add_route('detail', '/detail/')
        self.config.add_route('error_page', '/error_page')
        self.config.add_route('toolbox', '/toolbox')
        req = testing.DummyRequest()
        req.referrer = 'toolbox'
        from c3smembership.views.membership_dues_2016 import (
            send_dues16_invoice_batch, )
        # send out invoices. this is a prerequisite for reductions
        res = send_dues16_invoice_batch(req)
        res
        """
        test reduction of dues
        """
        # pre-check
        self.assertFalse(m1.dues16_reduced)  # not reduced yet!
        _m1_amount_reduced = m1.dues16_amount_reduced  # is Decimal('0')
        _number_of_invoices_before_reduction = len(Dues16Invoice.get_all())
        # print("_number_of_invoices_before_reduction: {}".format(
        #    _number_of_invoices_before_reduction))
        # we have 2 invoices as of now
        self.assertEqual(len(Dues16Invoice.get_all()), 2)
        # import the function under test
        from c3smembership.views.membership_dues_2016 import dues16_reduction

        #############################################################
        # try to reduce to the given calculated amount (edge case coverage)
        # this will not work, produce no new invoices
        req_reduce = testing.DummyRequest(  # prepare request
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 50,
            }, )
        req_reduce.matchdict['member_id'] = 1  # do it for member with id 1

        res_reduce = dues16_reduction(req_reduce)  # call reduce on her

        self.assertEqual(len(Dues16Invoice.get_all()), 2)  # no new invoice

        #############################################################
        # try to reduce above the given calculated amount
        # this will not work, produce no new invoices
        req_reduce = testing.DummyRequest(  # prepare request
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 500,
            }, )
        req_reduce.matchdict['member_id'] = 1  # do it for member with id 1

        res_reduce = dues16_reduction(req_reduce)  # call reduce on her

        self.assertEqual(len(Dues16Invoice.get_all()), 2)  # no new invoice

        #############################################################
        # valid reduction but without confirmation
        req_reduce = testing.DummyRequest(post={
            'confirmed': 'no',
            'submit': True,
            'amount': 42,
        }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)
        self.assertEqual(len(Dues16Invoice.get_all()), 2)  # no new invoice

        #############################################################
        # valid reduction
        req_reduce = testing.DummyRequest(post={
            'confirmed': 'yes',
            'submit': True,
            'amount': 42,
        }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)

        _number_of_invoices_after_reduction = len(Dues16Invoice.get_all())

        assert (  # two new invoices must have been issued
            (_number_of_invoices_before_reduction +
             2) == _number_of_invoices_after_reduction)
        assert (_number_of_invoices_after_reduction == 4)
        assert ('detail' in res_reduce.headers['Location'])  # 302 to detail p.
        assert (_m1_amount_reduced != m1.dues16_amount_reduced)  # changed!
        assert (m1.dues16_amount_reduced == 42)  # changed to 42!

        # check the invoice created
        _rev_inv = Dues16Invoice.get_by_invoice_no(
            _number_of_invoices_before_reduction + 1)
        _new_inv = Dues16Invoice.get_by_invoice_no(
            _number_of_invoices_before_reduction + 2)
        # print(_rev_inv.invoice_amount)
        # print(type(_rev_inv.invoice_amount))
        assert (_rev_inv.invoice_amount == D('-50'))
        assert (_new_inv.invoice_amount == D('42'))

        # we have 4 invoices as of now
        self.assertEqual(len(Dues16Invoice.get_all()), 4)

        #############################################################
        # now try to raise above the previous reduction
        req_reduce = testing.DummyRequest(post={
            'confirmed': 'yes',
            'submit': True,
            'amount': 50,
        }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)

        _number_of_invoices_after_reduction = len(Dues16Invoice.get_all())

        # no new invoices were created, we still have 4 invoices
        self.assertEqual(len(Dues16Invoice.get_all()), 4)

        #############################################################
        # try to reduce to the same amount again (edge case coverage)
        req_reduce = testing.DummyRequest(
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 42,
                # lots of values missing
            }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)
        #############################################################
        # try to reduce to zero (edge case coverage)
        # print("------------- reduction to zero ahead!!!")
        req_reduce = testing.DummyRequest(
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 0,
                # lots of values missing
            }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)

        req_reduce = testing.DummyRequest(
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 0,
                # lots of values missing
            }, )
        req_reduce.matchdict['member_id'] = 2
        res_reduce = dues16_reduction(req_reduce)
        #############################################################
        # try to reduce to zero with english member (edge case coverage)
        # how to do this if you already reduced to zero? reduce to more first!
        req_reduce = testing.DummyRequest(
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 1,
                # lots of values missing
            }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)
        m1.locale = u'en'
        req_reduce = testing.DummyRequest(
            post={
                'confirmed': 'yes',
                'submit': True,
                'amount': 0,
                # lots of values missing
            }, )
        req_reduce.matchdict['member_id'] = 1
        res_reduce = dues16_reduction(req_reduce)
        #############################################################
        """
        test reversal invoice PDF generation
        """

        from c3smembership.views.membership_dues_2016 import (
            make_dues16_reversal_invoice_pdf)
        req2 = testing.DummyRequest()

        # wrong token: must fail!
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token + 'false!!!',  # must fail
            'no': u'0006',
        }
        res = make_dues16_reversal_invoice_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error

        # wrong invoice number: must fail!
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token,
            'no': u'1234',  # must fail
        }
        res = make_dues16_reversal_invoice_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error

        # wrong invoice token: must fail!
        i2 = Dues16Invoice.get_by_invoice_no('2')
        i2.token = u'not_matching'
        req2.matchdict = {
            'email': m2.email,
            'code': m2.dues16_token,
            'no': u'2',  # must fail
        }
        res = make_dues16_reversal_invoice_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error

        ######################################################################
        # wrong invoice type (not a reversal): must fail! (edge case coverage)
        assert (not i2.is_reversal)  # i2 is not a reversal
        i2.token = m2.dues16_token  # we give it a valid token
        req2.matchdict = {
            'email': m2.email,
            'code': m2.dues16_token,
            'no': u'0002',
        }
        res = make_dues16_reversal_invoice_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error
        ######################################################################

        # retry with valid token:
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token,
            'no': u'0003',
        }
        res = make_dues16_reversal_invoice_pdf(req2)
        # print("length of the result: {}".format(len(res.body)))
        # print("headers of the result: {}".format((res.headers)))
        assert (60000 < len(res.body) < 80000)
        assert ('application/pdf' in res.headers['Content-Type'])
    def test_send_dues16_invoice_email_via_BATCH(self):
        """
        test the send_dues16_invoice_batch function
        for batch processing
        """
        # from pyramid_mailer import get_mailer
        from c3smembership.views.membership_dues_2016 import (
            send_dues16_invoice_batch, )
        self.config.add_route('make_dues16_invoice_no_pdf', '/')
        self.config.add_route('make_dues16_reversal_invoice_pdf', '/')
        self.config.add_route('detail', '/detail/')
        self.config.add_route('error_page', '/error_page')
        self.config.add_route('toolbox', '/toolbox')

        # have to accept their membersip first
        m1 = C3sMember.get_by_id(1)  # german normal member
        m1.membership_accepted = True
        m2 = C3sMember.get_by_id(2)  # english normal member
        m2.membership_accepted = True
        m3 = C3sMember.get_by_id(3)  # german investing member
        m3.membership_accepted = True
        m4 = C3sMember.get_by_id(4)  # english investing member
        m4.membership_accepted = True
        m5 = C3sMember.get_by_id(5)  # german investing member
        m5.membership_accepted = True
        m5 = C3sMember.get_by_id(6)  # english investing member
        m5.membership_accepted = True

        # check number of invoices: should be 0
        _number_of_invoices_before_batch = len(Dues16Invoice.get_all())
        # print("_number_of_invoices_before_batch: {}".format(
        #    _number_of_invoices_before_batch))
        assert (_number_of_invoices_before_batch == 0)

        req = testing.DummyRequest()
        req.referrer = 'toolbox'
        res = send_dues16_invoice_batch(req)
        # print res

        # check number of invoices: should be 2
        _number_of_invoices_batch = len(Dues16Invoice.get_all())
        # print("number of invoices after batch: {}".format(
        #    _number_of_invoices_batch))
        assert (_number_of_invoices_batch == 2)

        # try to post a number for batch processing
        req_post = testing.DummyRequest(
            post={
                'submit': True,
                'number': 24
                # lots of values missing
            }, )
        req.referrer = 'toolbox'
        res = send_dues16_invoice_batch(req_post)

        assert ('sent out 5 mails (to members with ids [1, 2, 3, 4, 5])'
                in req.session.pop_flash('message_to_staff'))

        # try to batch-send once more:
        # this will respond with a redirect and tell
        # that there are no invitees left
        res2 = send_dues16_invoice_batch(req)
        # print res2
        self.assertEquals(res2.status, '302 Found')
        self.assertEquals(res2.status_code, 302)
        assert ('no invoicees left. all done!'
                in req.session.pop_flash('message_to_staff'))
        """
        and now some tests for make_dues16_invoice_no_pdf
        """
        from c3smembership.views.membership_dues_2016 import (
            make_dues16_invoice_no_pdf)
        req2 = testing.DummyRequest()

        # wrong token: must fail!
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token + 'false!!!',  # must fail
            'i': u'0001',
        }

        res = make_dues16_invoice_no_pdf(req2)

        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error

        # wrong invoice number: must fail!
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token,
            'i': u'1234',  # must fail
        }
        res = make_dues16_invoice_no_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error

        # wrong invoice token: must fail!
        i2 = Dues16Invoice.get_by_invoice_no(2)
        i2.token = u'not_matching'
        req2.matchdict = {
            'email': m2.email,
            'code': m2.dues16_token,
            'i': u'3',  # must fail
        }
        res = make_dues16_invoice_no_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error

        #######################################################################
        # one more edge case:
        # check _inv.token must match code, or else!!!
        # first, set inv_code to something wrong:
        i1 = Dues16Invoice.get_by_invoice_no(1)
        _old_i1_token = i1.token
        i1.token = u'not_right'
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token,
            'i': u'0001',
        }
        res = make_dues16_invoice_no_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error
        # reset it to what was there before
        i1.token = _old_i1_token
        #######################################################################
        # one more edge case:
        # check this invoice is not a reversal, or else no PDF!!!
        # first, set is_reversal to something wrong:
        i1 = Dues16Invoice.get_by_invoice_no(1)
        _old_i1_reversal_status = i1.is_reversal  # False
        i1.is_reversal = True
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token,
            'i': u'0001',
        }
        res = make_dues16_invoice_no_pdf(req2)
        assert ('application/pdf' not in res.headers['Content-Type'])  # no PDF
        assert ('error_page' in res.headers['Location'])  # but error
        # reset it to what was there before
        i1.is_reversal = _old_i1_reversal_status
        #######################################################################

        # retry with valid token:
        req2.matchdict = {
            'email': m1.email,
            'code': m1.dues16_token,
            'i': u'0001',
        }
        res = make_dues16_invoice_no_pdf(req2)
        # m1.
        # print("length of the result: {}".format(len(res.body)))
        # print("headers of the result: {}".format((res.headers)))
        assert (60000 < len(res.body) < 80000)
        assert ('application/pdf' in res.headers['Content-Type'])
        """
        test dues listing
        """
        from c3smembership.views.membership_dues_2016 import dues16_listing
        req_list = testing.DummyRequest()
        resp_list = dues16_listing(req_list)
        # print resp_list
        # {'count': 5,
        #   'invoices': [
        #       <c3smembership.models.Dues16Invoice object at 0x7f95df761a50>,
        #       <c3smembership.models.Dues16Invoice object at 0x7f95df761690>,
        #       <c3smembership.models.Dues16Invoice object at 0x7f95df816a50>,
        #       <c3smembership.models.Dues16Invoice object at 0x7f95df761c90>,
        #       <c3smembership.models.Dues16Invoice object at 0x7f95df761c10>],
        #   '_today': datetime.date(2016, 9, 1)}
        assert (resp_list['count'] == 2)
    def test_send_dues16_invoice_email_single(self):
        """
        test the send_dues16_invoice_email view

        * calculate invoice amount and send invoice email
        ** to not accepted member
        ** to accepted member
        ** to non-existing member (wrong id)
        ** to same member (just send email, don't create new invoice)

        ... and also check email texts for
        * german normal member
        * english normal member
        * german investing member
        * english investing member
        * german investing legal entity
        * english investing legal entity

        """
        from pyramid_mailer import get_mailer
        from c3smembership.views.membership_dues_2016 import (
            send_dues16_invoice_email, )
        from c3smembership.models import Dues16Invoice

        _number_of_invoices = len(Dues16Invoice.get_all())

        self.config.add_route('toolbox', '/')
        self.config.add_route('detail', '/')
        self.config.add_route('make_dues16_invoice_no_pdf', '/')

        req = testing.DummyRequest()
        req.matchdict = {
            'member_id': '1',
        }
        req.referrer = 'detail'
        res = send_dues16_invoice_email(req)
        self.assertTrue(res.status_code == 302)
        self.assertTrue('http://example.com/' in res.headers['Location'])
        # member 1 not accepted by the board. problem!

        _number_of_invoices_2 = len(Dues16Invoice.get_all())
        assert (_number_of_invoices == _number_of_invoices_2 == 0)
        # print("_number_of_invoices: {}".format(_number_of_invoices))

        m1 = C3sMember.get_by_id(1)
        m1.membership_accepted = True

        res = send_dues16_invoice_email(req)
        # print('#'*60)
        # print res
        # print('#'*60)

        _number_of_invoices_3 = len(Dues16Invoice.get_all())
        # print("_number_of_invoices 3: {}".format(_number_of_invoices_3))
        assert (_number_of_invoices_3 == 1)

        # check for outgoing email
        mailer = get_mailer(req)
        # print mailer
        # print mailer.outbox
        self.assertEqual(len(mailer.outbox), 1)
        # print mailer.outbox[0].body
        self.assertTrue(
            'Verwendungszweck: C3S-dues2016-0001' in mailer.outbox[0].body)
        """
        now we try to get an id that does not exist
        """
        req2 = testing.DummyRequest()
        req2.matchdict = {
            'member_id': '1234',
        }
        req2.referrer = 'detail'
        res2 = send_dues16_invoice_email(req2)
        self.assertTrue(res2.status_code == 302)
        self.assertTrue('http://example.com/' in res2.headers['Location'])
        """
        what if we call that function (and send email) twice?
        test that no second invoice is created in DB.
        """
        req3 = testing.DummyRequest()
        req3.matchdict = {
            'member_id': '1',
        }
        req3.referrer = 'detail'
        res3 = send_dues16_invoice_email(req3)
        self.assertTrue(res3.status_code == 302)
        self.assertTrue('http://example.com/' in res3.headers['Location'])
        _number_of_invoices_4 = len(Dues16Invoice.get_all())
        self.assertEqual(_number_of_invoices_3, _number_of_invoices_4)
        """
        check for email texts
        """
        self.assertEqual(len(mailer.outbox), 2)
        self.assertTrue(
            (u'Dein Mitgliedsbeitrag ab Quartal 1 beträgt also 50 Euro.'
             ) in mailer.outbox[0].body)
        # print(mailer.outbox[0].body)
        self.assertTrue(
            (u'Dein Mitgliedsbeitrag ab Quartal 1 beträgt also 50 Euro.'
             ) in mailer.outbox[1].body)
        # print(mailer.outbox[1].body)
        """
        send email to
        * english member,
        * investing members (de/en),
        * legal entities (de/en)
        """
        # english normal #####################################################
        m2 = C3sMember.get_by_id(2)
        m2.membership_accepted = True
        req_en_normal = testing.DummyRequest()
        req_en_normal.matchdict = {
            'member_id': '2',
        }
        req_en_normal.referrer = 'detail'
        res_en_normal = send_dues16_invoice_email(req_en_normal)
        self.assertTrue(res_en_normal.status_code == 302)
        self.assertEqual(len(mailer.outbox), 3)
        # print(mailer.outbox[2].body)
        self.assertTrue((u'Please transfer 50 Euro') in mailer.outbox[2].body)

        # german investing ###################################################
        m3 = C3sMember.get_by_id(3)
        m3.membership_accepted = True
        req_de_investing = testing.DummyRequest()
        req_de_investing.matchdict = {
            'member_id': '3',
        }
        req_de_investing.referrer = 'detail'
        res_de_investing = send_dues16_invoice_email(req_de_investing)
        self.assertTrue(res_de_investing.status_code == 302)
        self.assertEqual(len(mailer.outbox), 4)
        # print(mailer.outbox[3].body)
        self.assertTrue(
            (u'Da Du investierendes Mitglied bist') in mailer.outbox[3].body)

        # english investing ##################################################
        m4 = C3sMember.get_by_id(4)
        m4.membership_accepted = True
        req_en_investing = testing.DummyRequest()
        req_en_investing.matchdict = {
            'member_id': '4',
        }
        req_en_investing.referrer = 'detail'
        res_en_investing = send_dues16_invoice_email(req_en_investing)
        self.assertTrue(res_en_investing.status_code == 302)
        self.assertEqual(len(mailer.outbox), 5)
        # print(mailer.outbox[4].body)
        self.assertTrue(
            (u'Since you are an investing member') in mailer.outbox[4].body)

        # german legal entity ################################################
        m5 = C3sMember.get_by_id(5)
        m5.membership_accepted = True
        req_de_legalentity = testing.DummyRequest()
        req_de_legalentity.matchdict = {
            'member_id': '5',
        }
        req_de_legalentity.referrer = 'detail'
        res_de_legalentity = send_dues16_invoice_email(req_de_legalentity)
        self.assertTrue(res_de_legalentity.status_code == 302)
        self.assertEqual(len(mailer.outbox), 6)
        # print(mailer.outbox[5].body)
        self.assertTrue((u'') in mailer.outbox[5].body)

        # english legal entity ###############################################
        m6 = C3sMember.get_by_id(6)
        m6.membership_accepted = True
        req_en_legalentity = testing.DummyRequest()
        req_en_legalentity.matchdict = {
            'member_id': '6',
        }
        req_en_legalentity.referrer = 'detail'
        res_en_legalentity = send_dues16_invoice_email(req_en_legalentity)
        self.assertTrue(res_en_legalentity.status_code == 302)
        self.assertEqual(len(mailer.outbox), 7)
        # print(mailer.outbox[6].body)
        self.assertTrue((u'Da Musikverlag investierendes Mitglied ist'
                         ) in mailer.outbox[6].body)
        self.assertTrue((u'Für juristische Personen wird empfohlen'
                         ) in mailer.outbox[6].body)