Beispiel #1
0
 def test_handle_add(self):
     from seantisinvoice.models import Invoice
     from seantisinvoice.models import DBSession
     from seantisinvoice.views.invoice import InvoiceController
     # Register route for redirect in invoice form actions
     testing.registerRoute('/', 'invoices', factory=None)
     # Each invoice belongs to a customer, thus add one.
     customer = self._add_customer()
     request = testing.DummyRequest()
     view = InvoiceController(None, request)
     data = view.form_defaults()
     data['customer_contact_id'] = customer.contacts[0].id
     data['project_description'] = u'Project name'
     data['recurring_term'] = 30
     data['date'] = datetime.date(2010, 1, 18)
     data['item_list'] = [
         dict(item_id='',
              service_title=u'Testing',
              service_description=u'Work',
              amount=2000.0)
     ]
     view.handle_add(data)
     session = DBSession()
     invoice = session.query(Invoice).one()
     self.assertEquals(u'Project name', invoice.project_description)
     self.assertEquals(customer.contacts[0], invoice.contact)
     self.assertEquals(1, len(invoice.items))
     self.assertEquals(u'Testing', invoice.items[0].service_title)
Beispiel #2
0
 def test_next_invoice_number(self):
     from seantisinvoice.models import DBSession
     from seantisinvoice.models import Company
     from seantisinvoice.models import next_invoice_number
     session = DBSession()
     company = session.query(Company).one()
     company.invoice_start_number = 20
     result = next_invoice_number()
     self.assertEqual(20, result)
     self.assertEqual(21, company.invoice_start_number)
    def _apply_data(self, invoice, converted):
        changed = False
        # Apply schema fields to the customer object
        field_names = [p.key for p in class_mapper(Invoice).iterate_properties]
        for field_name in field_names:
            if field_name in converted.keys():
                if getattr(invoice, field_name) != converted[field_name]:
                    setattr(invoice, field_name, converted[field_name])
                    changed = True
        if invoice.due_date != invoice.date + datetime.timedelta(
                days=converted['payment_term']):
            invoice.due_date = invoice.date + datetime.timedelta(
                days=converted['payment_term'])
            changed = True
        if converted[
                'recurring_term'] and invoice.recurring_date != invoice.date + datetime.timedelta(
                    days=converted['recurring_term']):
            invoice.recurring_date = invoice.date + datetime.timedelta(
                days=converted['recurring_term'])
            changed = True

        # Apply data of the items subforms
        session = DBSession()
        item_map = {}
        for item in invoice.items:
            item_map[item.id] = item
        for index, item_data in enumerate(converted['item_list']):
            if item_data['item_id']:
                item_id = item_data['item_id']
                item = item_map[item_id]
                del item_map[item_id]
            else:
                item = InvoiceItem()
                item.invoice = invoice
                session.add(item)
                changed = True
            # Apply schema fields to the invoice item object
            field_names = [
                p.key for p in class_mapper(InvoiceItem).iterate_properties
            ]
            for field_name in field_names:
                if field_name in item_data.keys():
                    if getattr(item, field_name) != item_data[field_name]:
                        setattr(item, field_name, item_data[field_name])
                        changed = True
            if item.item_number != index:
                item.item_number = index
                changed = True
        # Remove invoice items that have been removed in the form
        for item in item_map.values():
            invoice.items.remove(item)
            changed = True

        return changed
    def form_defaults(self):
        defaults = {}
        session = DBSession()
        company = session.query(Company).first()
        field_names = [p.key for p in class_mapper(Company).iterate_properties]
        form_fields = [field[0] for field in company_schema.attrs]
        for field_name in field_names:
            if field_name in form_fields:
                defaults[field_name] = getattr(company, field_name)

        return defaults
    def handle_submit(self, converted):
        session = DBSession()
        company = session.query(Company).first()
        changed = self._apply_data(company, converted)

        if changed:
            statusmessage.show(self.request, u"Changes saved.", "success")
        else:
            statusmessage.show(self.request, u"No changes saved.", "notice")

        return HTTPFound(location=route_url('company', self.request))
    def handle_submit(self, converted):
        invoice_id = self.request.matchdict['invoice']
        session = DBSession()
        invoice = session.query(Invoice).filter_by(id=invoice_id).one()
        changed = self._apply_data(invoice, converted)

        if changed:
            statusmessage.show(self.request, u"Changes saved.", "success")
        else:
            statusmessage.show(self.request, u"No changes saved.", "notice")

        return HTTPFound(location=route_url('invoices', self.request))
    def __call__(self):
        if "invoice" in self.request.matchdict:
            session = DBSession()
            invoice_id = self.request.matchdict['invoice']
            invoice = session.query(Invoice).filter_by(id=invoice_id).first()
            if not invoice:
                return Response(status=404)

        main = get_template('templates/master.pt')
        return dict(request=self.request,
                    main=main,
                    msgs=statusmessage.messages(self.request))
    def form_defaults(self):

        session = DBSession()
        company = session.query(Company).first()

        defaults = {
            'currency': u'CHF',
            'payment_term': 30,
            'tax': company.tax,
        }

        if "invoice" in self.request.matchdict:
            invoice_id = self.request.matchdict['invoice']
            invoice = session.query(Invoice).filter_by(id=invoice_id).first()
            if invoice:
                field_names = [
                    p.key for p in class_mapper(Invoice).iterate_properties
                ]
                form_fields = [field[0] for field in invoice_schema.attrs]
                for field_name in field_names:
                    if field_name in form_fields:
                        defaults[field_name] = getattr(invoice, field_name)
                defaults['payment_term'] = (invoice.due_date -
                                            invoice.date).days
                if invoice.recurring_date:
                    defaults['recurring_term'] = (invoice.recurring_date -
                                                  invoice.date).days
                else:
                    defaults['recurring_term'] = None

                # Default values for the item subforms
                defaults['item_list'] = []
                # Make test happy
                invoice.items.sort(key=lambda obj: obj.item_number)
                for item in invoice.items:
                    item_defaults = {}
                    field_names = [
                        p.key
                        for p in class_mapper(InvoiceItem).iterate_properties
                    ]
                    form_fields = [
                        field[0] for field in invoice_item_schema.attrs
                    ]
                    for field_name in field_names:
                        if field_name in form_fields:
                            item_defaults[field_name] = getattr(
                                item, field_name)
                    item_defaults['item_id'] = item.id
                    defaults['item_list'].append(item_defaults)

        return defaults
    def handle_add(self, converted):
        session = DBSession()
        invoice = Invoice()
        invoice.company = session.query(Company).first()
        self._apply_data(invoice, converted)
        session.add(invoice)

        # Get and add unique invoice number
        if invoice.invoice_number is None:
            invoice.invoice_number = next_invoice_number()

        statusmessage.show(self.request, u"Invoice added.", "success")

        return HTTPFound(location=route_url('invoices', self.request))
Beispiel #10
0
 def test_next_invoice_number_used(self):
     from seantisinvoice.models import DBSession
     from seantisinvoice.models import Company
     from seantisinvoice.models import Invoice
     from seantisinvoice.models import next_invoice_number
     session = DBSession()
     company = session.query(Company).one()
     company.invoice_start_number = 20
     invoice = Invoice(invoice_number=20)
     session.add(invoice)
     session.flush()
     result = next_invoice_number()
     self.assertEqual(21, result)
     self.assertEqual(22, company.invoice_start_number)
Beispiel #11
0
 def test_recurring(self):
     from seantisinvoice.models import DBSession
     from seantisinvoice.models import Invoice, InvoiceItem
     from seantisinvoice.recurring import copy_recurring
     session = DBSession()
     copy_recurring()
     self.assertEquals(0, session.query(Invoice).count())
     # Add a new invoice
     invoice = Invoice()
     invoice_date = datetime.date.today() - datetime.timedelta(days=100)
     invoice.date = invoice_date
     invoice.due_date = datetime.date.today() - datetime.timedelta(days=70)
     invoice.project_description = u'Invoice project description'
     session.add(invoice)
     # Add an item to the invoice
     item = InvoiceItem()
     item.item_number = 0
     item.amount = 1000
     item.service_description = u'Item description'
     item.service_title = u'Invoice item'
     item.invoice = invoice
     session.merge(item)
     copy_recurring()
     # Invoice not cloned as it has no recurring_date
     self.assertEquals(1, session.query(Invoice).count())
     invoice = session.query(Invoice).one()
     # Set the recurring date on the invoice
     recurring_date = datetime.date.today() - datetime.timedelta(days=70)
     invoice.recurring_date = recurring_date
     copy_recurring()
     # There are now two invoices
     self.assertEquals(2, session.query(Invoice).count())
     invoice = session.query(Invoice).filter_by(date=invoice_date).one()
     # Recurring date of the original invoice has been reset
     self.failIf(invoice.recurring_date)
     cloned_invoice = session.query(Invoice).filter_by(
         date=recurring_date).one()
     # New invoice has the recurring date of the original one as date
     self.assertEquals(recurring_date, cloned_invoice.date)
     self.assertEquals(recurring_date + datetime.timedelta(days=30),
                       cloned_invoice.recurring_date)
     # Check whether attributes on invoice and invoice item have been cloned
     self.assertEquals(invoice.project_description,
                       cloned_invoice.project_description)
     cloned_item = cloned_invoice.items[0]
     self.assertEquals(item.amount, cloned_item.amount)
     self.assertEquals(item.service_description,
                       cloned_item.service_description)
     self.assertEquals(item.service_title, cloned_item.service_title)
Beispiel #12
0
 def _set_company_profile(self):
     from seantisinvoice.models import Company
     from seantisinvoice.models import DBSession
     session = DBSession()
     company = session.query(Company).one()
     company.name = u'Example Inc.'
     company.address1 = u'Main street 1'
     company.postal_code = u'1000'
     company.city = u'Somewhere'
     company.email = u'*****@*****.**'
     company.phone = u'1233456789'
     company.hourly_rate = 100.0
     company.daily_rate = 1000.0
     company.invoice_template = u'invoice_pdf.pt'
     return company
def view_invoices(request):
    session = DBSession()
    query = session.query(Invoice)
    today = datetime.date.today()

    if 'recurring' in request.params:
        if request.params['recurring'] == '1':
            query = query.filter(Invoice.recurring_date != None)
            # We don't show the recurring invoices that have stop date in the past
            query = query.filter(Invoice.recurring_stop >= today
                                 or Invoice.recurring_stop == None)
            title = u'Recurring Invoices'
        elif request.params['recurring'] == '0':
            query = query.filter(Invoice.recurring_date == None)
            title = u'Non-recurring Invoices'
    elif 'due' in request.params and request.params['due'] == '1':
        query = query.filter(Invoice.due_date <= today)
        query = query.filter(Invoice.payment_date == None)
        title = u'Invoices due'
    else:
        title = u'All Invoices'

    # Sorting
    if 'sort' in request.params:
        sort_key = request.params['sort']
        if hasattr(Invoice, sort_key):
            sort_attr = getattr(Invoice, sort_key)
            if 'reverse' in request.params:
                sort_attr = desc(sort_attr)
            query = query.order_by(sort_attr)
    else:
        query = query.order_by(desc(Invoice.date))

    invoices = query.all()
    company = session.query(Company).first()
    main = get_template('templates/master.pt')
    return dict(request=request,
                main=main,
                invoices=invoices,
                company=company,
                title=title,
                msgs=statusmessage.messages(request),
                formatThousands=formatThousands)
Beispiel #14
0
 def _add_customer(self):
     from seantisinvoice.models import Customer
     from seantisinvoice.models import CustomerContact
     from seantisinvoice.models import DBSession
     session = DBSession()
     customer = Customer()
     customer.name = u'Customers Inc.'
     customer.address1 = u'Street'
     customer.postal_code = u'12234'
     customer.city = u'Dublin'
     session.add(customer)
     # Each customer needs at least one contact
     contact = CustomerContact()
     contact.first_name = u'Buck'
     contact.last_name = u'Mulligan'
     contact.title = u'Mr.'
     contact.customer = customer
     session.add(contact)
     session.flush()
     return customer
def copy_recurring():
    today = datetime.date.today()
    session = DBSession()
    query = session.query(Invoice)
    query = query.filter(Invoice.recurring_date <= today)
    query = query.filter(
        or_(Invoice.recurring_stop == None, Invoice.recurring_stop > today))
    for invoice in query.all():
        # Clone invoice and invoice items
        invoice_clone = Invoice()
        invoice_clone.company = invoice.company
        invoice_clone.contact = invoice.contact
        invoice_clone.project_description = invoice.project_description
        invoice_clone.currency = invoice.currency
        invoice_clone.tax = invoice.tax
        session.add(invoice_clone)
        for item in invoice.items:
            item_clone = InvoiceItem()
            item_clone.item_number = item.item_number
            item_clone.amount = item.amount
            item_clone.hours = item.hours
            item_clone.days = item.days
            item_clone.service_description = item.service_description
            item_clone.service_title = item.service_title
            item_clone.invoice = invoice_clone
            session.add(item_clone)

        # Get new invoice number
        invoice_clone.invoice_number = next_invoice_number()

        # Adjust dates on cloned invoice
        invoice_clone.date = invoice.recurring_date
        invoice_clone.due_date = invoice_clone.date + (invoice.due_date -
                                                       invoice.date)
        invoice_clone.recurring_date = invoice_clone.date + (
            invoice.recurring_date - invoice.date)
        invoice_clone.recurring_stop = invoice.recurring_stop
        # Old invoice is not recurring anymore
        invoice.recurring_date = None

    transaction.commit()
def view_invoice_pdf(request):
    session = DBSession()
    company = session.query(Company).first()

    invoice_id = request.matchdict['invoice']
    invoice = session.query(Invoice).filter_by(id=invoice_id).first()
    if not invoice:
        return Response(status=404)

    rml_template = 'templates/rml/' + company.invoice_template

    # Only jpeg without PIL
    logo_path = os.path.join(os.path.dirname(__file__), 'templates', 'static',
                             'uploads', 'logo.jpg')

    result = render_template(rml_template,
                             invoice=invoice,
                             logo_path=logo_path,
                             formatThousands=formatThousands)
    response = Response(parseString(result.encode('utf-8')).read())
    response.content_type = "application/pdf"
    return response
    def form_widgets(self, fields):
        widgets = {}
        widgets['date'] = formish.DateParts(day_first=True)
        widgets['recurring_stop'] = formish.DateParts(day_first=True)
        widgets['payment_date'] = formish.DateParts(day_first=True)
        session = DBSession()
        options = []
        query = session.query(CustomerContact.id, Customer.name,
                              CustomerContact.first_name,
                              CustomerContact.last_name)
        query = query.join(CustomerContact.customer)
        query = query.order_by(Customer.name, CustomerContact.last_name,
                               CustomerContact.first_name)
        for (contact_id, company, first_name, last_name) in query.all():
            options.append(
                (contact_id, '%s: %s %s' % (company, first_name, last_name)))
        widgets['customer_contact_id'] = formish.SelectChoice(options=options)
        widgets['item_list'] = formish.SequenceDefault(min_start_fields=1)
        widgets['item_list.*.item_id'] = formish.Hidden()
        widgets['item_list.*.service_description'] = formish.TextArea()

        return widgets
Beispiel #18
0
 def _add_invoice(self):
     from seantisinvoice.models import Invoice
     from seantisinvoice.models import InvoiceItem
     from seantisinvoice.models import DBSession
     session = DBSession()
     customer = self._add_customer()
     invoice = Invoice()
     invoice.project_description = u'Project'
     invoice.date = datetime.date.today()
     invoice.due_date = invoice.date + datetime.timedelta(days=30)
     invoice.currency = u'CHF'
     invoice.contact = customer.contacts[0]
     session.add(invoice)
     # Add invoice item to the invoice
     item = InvoiceItem()
     item.item_number = 0
     item.service_title = u'Testing'
     item.service_description = u'A lot of work!'
     item.amount = 1000.0
     item.invoice = invoice
     session.add(item)
     session.flush()
     return invoice
Beispiel #19
0
 def test_handle_add(self):
     from seantisinvoice.models import Customer
     from seantisinvoice.models import DBSession
     from seantisinvoice.views.customer import CustomerController
     # Register route for redirect in customer form actions
     testing.registerRoute('/customers', 'customers', factory=None)
     request = testing.DummyRequest()
     view = CustomerController(None, request)
     # Add a new customer
     data = dict(name=u'Customers Inc.',
                 address1=u'Street',
                 postal_code=u'12234',
                 city=u'Dublin')
     data['contact_list'] = [
         dict(first_name=u'Buck',
              last_name=u'Mulligan',
              title=u'Mr.',
              contact_id='')
     ]
     view.handle_add(data)
     session = DBSession()
     customer = session.query(Customer).one()
     self.assertEquals(u'Customers Inc.', customer.name)
     self.assertEquals(u'Buck', customer.contacts[0].first_name)