Initial views, and basic invoice export UI tools
This commit is contained in:
commit
7384bd1fea
17 changed files with 1029 additions and 0 deletions
30
tailbone_quickbooks/views/__init__.py
Normal file
30
tailbone_quickbooks/views/__init__.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2022 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Views w/ Quickbooks integration
|
||||
"""
|
||||
|
||||
def includeme(config):
|
||||
config.include('tailbone_quickbooks.views.departments')
|
||||
config.include('tailbone_quickbooks.views.stores')
|
||||
config.include('tailbone_quickbooks.views.vendors')
|
55
tailbone_quickbooks/views/departments.py
Normal file
55
tailbone_quickbooks/views/departments.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2022 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Department views, w/ Quickbooks integration
|
||||
"""
|
||||
|
||||
from tailbone.views import ViewSupplement
|
||||
|
||||
|
||||
class DepartmentViewSupplement(ViewSupplement):
|
||||
"""
|
||||
Department view supplement for Quickbooks integration
|
||||
"""
|
||||
route_prefix = 'departments'
|
||||
|
||||
def get_grid_query(self, query):
|
||||
model = self.model
|
||||
return query.outerjoin(model.QuickbooksDepartment)
|
||||
|
||||
def configure_grid(self, g):
|
||||
model = self.model
|
||||
g.set_filter('quickbooks_expense_account', model.QuickbooksDepartment.quickbooks_expense_account)
|
||||
g.set_filter('quickbooks_expense_class', model.QuickbooksDepartment.quickbooks_expense_class)
|
||||
|
||||
def configure_form(self, f):
|
||||
f.append('quickbooks_expense_account')
|
||||
f.append('quickbooks_expense_class')
|
||||
|
||||
def get_version_child_classes(self):
|
||||
model = self.model
|
||||
return [model.QuickbooksDepartment]
|
||||
|
||||
|
||||
def includeme(config):
|
||||
DepartmentViewSupplement.defaults(config)
|
0
tailbone_quickbooks/views/quickbooks/__init__.py
Normal file
0
tailbone_quickbooks/views/quickbooks/__init__.py
Normal file
506
tailbone_quickbooks/views/quickbooks/invoices.py
Normal file
506
tailbone_quickbooks/views/quickbooks/invoices.py
Normal file
|
@ -0,0 +1,506 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2022 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Views for Quickbooks invoices
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from rattail_quickbooks.db.model import (QuickbooksExportableInvoice,
|
||||
QuickbooksExportableInvoiceDistribution,
|
||||
QuickbooksInvoiceExport)
|
||||
from rattail.util import simple_error
|
||||
|
||||
import colander
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
|
||||
from tailbone import forms
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.views.exports import ExportMasterView
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ToggleInvoices(colander.MappingSchema):
|
||||
uuids = colander.SchemaNode(colander.String())
|
||||
|
||||
|
||||
class ExportableInvoiceView(MasterView):
|
||||
"""
|
||||
Master view for Quickbooks exportable invoices
|
||||
"""
|
||||
model_class = QuickbooksExportableInvoice
|
||||
route_prefix = 'quickbooks.exportable_invoices'
|
||||
url_prefix = '/quickbooks/exportable-invoices'
|
||||
has_versions = True
|
||||
|
||||
labels = {
|
||||
'store_id': "Store ID",
|
||||
'vendor_id': "Vendor ID",
|
||||
'txn_id': "Transaction ID",
|
||||
'quickbooks_vendor_terms': "Vendor Terms",
|
||||
'quickbooks_export_template': "Export Template",
|
||||
'status_code': "Status",
|
||||
}
|
||||
|
||||
grid_columns = [
|
||||
'invoice_date',
|
||||
'invoice_number',
|
||||
'invoice_total',
|
||||
'store',
|
||||
'vendor',
|
||||
'quickbooks_vendor_terms',
|
||||
'quickbooks_export_template',
|
||||
'status_code',
|
||||
]
|
||||
|
||||
form_fields = [
|
||||
'store',
|
||||
'vendor',
|
||||
'txn_id',
|
||||
'invoice_number',
|
||||
'invoice_date',
|
||||
'invoice_total',
|
||||
'quickbooks_vendor_name',
|
||||
'quickbooks_vendor_terms',
|
||||
'quickbooks_vendor_bank_account',
|
||||
'quickbooks_export_template',
|
||||
'status_code',
|
||||
'status_text',
|
||||
'deleted',
|
||||
'deleted_by',
|
||||
'exported',
|
||||
'exported_by',
|
||||
]
|
||||
|
||||
has_rows = True
|
||||
model_row_class = QuickbooksExportableInvoiceDistribution
|
||||
rows_filterable = False
|
||||
rows_pageable = False
|
||||
rows_viewable = False
|
||||
|
||||
# TODO: this does not work right yet, e.g. clicking the View
|
||||
# action link will still trigger row-click event
|
||||
# clicking_row_checks_box = True
|
||||
|
||||
row_labels = {
|
||||
'department_id': "Department ID",
|
||||
'status_code': "Status",
|
||||
}
|
||||
|
||||
row_grid_columns = [
|
||||
'department_id',
|
||||
'department',
|
||||
'quickbooks_expense_account',
|
||||
'quickbooks_expense_class',
|
||||
'source_amount',
|
||||
'calculated_percent',
|
||||
'calculated_amount',
|
||||
'status_code',
|
||||
]
|
||||
|
||||
def configure_grid(self, g):
|
||||
super(ExportableInvoiceView, self).configure_grid(g)
|
||||
model = self.model
|
||||
|
||||
# store
|
||||
g.set_joiner('store', lambda q: q.outerjoin(model.Store))
|
||||
g.set_filter('store', model.Store.name)
|
||||
g.set_sorter('store', model.Store.name)
|
||||
|
||||
# vendor
|
||||
g.set_joiner('vendor', lambda q: q.outerjoin(model.Vendor))
|
||||
g.set_filter('vendor', model.Vendor.name)
|
||||
g.set_sorter('vendor', model.Vendor.name)
|
||||
g.set_link('vendor')
|
||||
|
||||
# invoice_number
|
||||
g.filters['invoice_number'].default_active = True
|
||||
g.filters['invoice_number'].default_verb = 'contains'
|
||||
g.set_link('invoice_number')
|
||||
|
||||
# invoice_date
|
||||
g.set_sort_defaults('invoice_date', 'desc')
|
||||
g.set_link('invoice_date')
|
||||
|
||||
# invoice_total
|
||||
g.set_type('invoice_total', 'currency')
|
||||
|
||||
# status_code
|
||||
g.set_enum('status_code', model.QuickbooksExportableInvoice.STATUS)
|
||||
g.set_renderer('status_code', self.make_status_renderer(
|
||||
model.QuickbooksExportableInvoice.STATUS))
|
||||
|
||||
# exported
|
||||
g.filters['exported'].default_active = True
|
||||
g.filters['exported'].default_verb = 'is_null'
|
||||
|
||||
# deleted
|
||||
g.filters['deleted'].default_active = True
|
||||
g.filters['deleted'].default_verb = 'is_null'
|
||||
|
||||
if self.has_perm('export'):
|
||||
g.checkboxes = True
|
||||
g.check_handler = 'rowChecked'
|
||||
g.check_all_handler = 'allChecked'
|
||||
|
||||
def grid_extra_class(self, invoice, i):
|
||||
if not self.exportable(invoice):
|
||||
if invoice.status_code in (invoice.STATUS_DEPTS_IGNORED,
|
||||
invoice.STATUS_EXPORTED,
|
||||
invoice.STATUS_DELETED):
|
||||
return 'notice'
|
||||
return 'warning'
|
||||
|
||||
def checkbox(self, invoice):
|
||||
return self.exportable(invoice)
|
||||
|
||||
def checked(self, invoice):
|
||||
return invoice.uuid in self.get_selected()
|
||||
|
||||
def template_kwargs_index(self, **kwargs):
|
||||
kwargs = super(ExportableInvoiceView, self).template_kwargs_index(**kwargs)
|
||||
kwargs['selected'] = self.get_selected()
|
||||
return kwargs
|
||||
|
||||
def get_selected(self):
|
||||
route_prefix = self.get_route_prefix()
|
||||
return self.request.session.get('{}.selected'.format(route_prefix), set())
|
||||
|
||||
def set_selected(self, selected):
|
||||
route_prefix = self.get_route_prefix()
|
||||
self.request.session['{}.selected'.format(route_prefix)] = selected
|
||||
|
||||
def exportable(self, invoice):
|
||||
"""
|
||||
Return boolean indicating whether the given invoice is exportable.
|
||||
"""
|
||||
return invoice.status_code == invoice.STATUS_EXPORTABLE
|
||||
|
||||
def configure_form(self, f):
|
||||
super(ExportableInvoiceView, self).configure_form(f)
|
||||
model = self.model
|
||||
invoice = f.model_instance
|
||||
|
||||
# store
|
||||
f.set_renderer('store', self.render_store)
|
||||
|
||||
# vendor
|
||||
f.set_renderer('vendor', self.render_vendor)
|
||||
|
||||
# invoice_total
|
||||
f.set_type('invoice_total', 'currency')
|
||||
|
||||
# status
|
||||
f.set_enum('status_code', model.QuickbooksExportableInvoice.STATUS)
|
||||
|
||||
# exported
|
||||
if self.creating or not invoice.exported:
|
||||
f.remove('exported', 'exported_by')
|
||||
|
||||
# deleted
|
||||
if self.creating or not invoice.deleted:
|
||||
f.remove('deleted', 'deleted_by')
|
||||
|
||||
def get_row_data(self, invoice):
|
||||
model = self.model
|
||||
return self.Session.query(model.QuickbooksExportableInvoiceDistribution)\
|
||||
.filter(model.QuickbooksExportableInvoiceDistribution.invoice == invoice)
|
||||
|
||||
def get_parent(self, dist):
|
||||
return dist.invoice
|
||||
|
||||
def configure_row_grid(self, g):
|
||||
super(ExportableInvoiceView, self).configure_row_grid(g)
|
||||
model = self.model
|
||||
|
||||
# department_id
|
||||
g.set_sort_defaults('department_id')
|
||||
|
||||
# amounts etc.
|
||||
g.set_type('source_amount', 'currency')
|
||||
g.set_type('calculated_percent', 'percent')
|
||||
g.set_type('calculated_amount', 'currency')
|
||||
|
||||
# status
|
||||
g.set_enum('status_code', model.QuickbooksExportableInvoiceDistribution.STATUS)
|
||||
|
||||
def row_grid_extra_class(self, dist, i):
|
||||
if dist.status_code in (dist.STATUS_DEPT_IGNORED,
|
||||
dist.STATUS_EXPORTED):
|
||||
return 'notice'
|
||||
elif dist.status_code != dist.STATUS_EXPORTABLE:
|
||||
return 'warning'
|
||||
|
||||
def refresh(self):
|
||||
"""
|
||||
View to refresh data for a single invoice.
|
||||
"""
|
||||
invoice = self.get_instance()
|
||||
self.refresh_invoice(invoice)
|
||||
return self.redirect(self.get_action_url('view', invoice))
|
||||
|
||||
def refresh_invoice(self, invoice):
|
||||
"""
|
||||
Logic to actually refresh data for the given invoice.
|
||||
Implement as needed.
|
||||
"""
|
||||
|
||||
def select(self):
|
||||
"""
|
||||
Mark one or more invoices as selected, within the current user's session.
|
||||
"""
|
||||
model = self.model
|
||||
|
||||
form = forms.Form(schema=ToggleInvoices(), request=self.request)
|
||||
if not form.validate(newstyle=True):
|
||||
return {'error': "Form did not validate"}
|
||||
uuids = form.validated['uuids'].split(',')
|
||||
|
||||
invoices = []
|
||||
for uuid in uuids:
|
||||
invoice = self.Session.query(model.QuickbooksExportableInvoice).get(uuid)
|
||||
if invoice and self.exportable(invoice):
|
||||
invoices.append(invoice)
|
||||
if not invoices:
|
||||
return {'error': "Must specify one or more valid invoice UUIDs."}
|
||||
|
||||
selected = self.get_selected()
|
||||
for invoice in invoices:
|
||||
selected.add(invoice.uuid)
|
||||
self.set_selected(selected)
|
||||
return {
|
||||
'ok': True,
|
||||
'selected_count': len(selected),
|
||||
}
|
||||
|
||||
def deselect(self):
|
||||
"""
|
||||
Mark one or more invoices as *not* selected, within the current user's session.
|
||||
"""
|
||||
model = self.model
|
||||
|
||||
form = forms.Form(schema=ToggleInvoices(), request=self.request)
|
||||
if not form.validate(newstyle=True):
|
||||
return {'error': "Form did not validate"}
|
||||
uuids = form.validated['uuids'].split(',')
|
||||
|
||||
invoices = []
|
||||
for uuid in uuids:
|
||||
invoice = self.Session.query(model.QuickbooksExportableInvoice).get(uuid)
|
||||
if invoice and self.exportable(invoice):
|
||||
invoices.append(invoice)
|
||||
if not invoices:
|
||||
return {'error': "Must specify one or more valid invoice UUIDs."}
|
||||
|
||||
selected = self.get_selected()
|
||||
for invoice in invoices:
|
||||
selected.discard(invoice.uuid)
|
||||
self.set_selected(selected)
|
||||
return {
|
||||
'ok': True,
|
||||
'selected_count': len(selected),
|
||||
}
|
||||
|
||||
def export(self):
|
||||
"""
|
||||
Export all currently-selected invoices.
|
||||
"""
|
||||
model = self.model
|
||||
|
||||
selected = self.get_selected()
|
||||
if not selected:
|
||||
self.request.session.flash("You must first select one or more "
|
||||
"invoices.", 'error')
|
||||
return self.redirect(self.get_index_url())
|
||||
|
||||
invoices = []
|
||||
for uuid in selected:
|
||||
invoice = self.Session.query(model.QuickbooksExportableInvoice).get(uuid)
|
||||
if invoice and invoice.status_code == invoice.STATUS_EXPORTABLE:
|
||||
invoices.append(invoice)
|
||||
else:
|
||||
log.warning("invoice not found or wrong status: %s", uuid)
|
||||
|
||||
if not invoices:
|
||||
self.request.session.flash("Hm, was unable to determine any invoices "
|
||||
"to export.", 'error')
|
||||
return self.redirect(self.get_index_url())
|
||||
|
||||
# perform actual export and capture result
|
||||
result = self.do_export(invoices)
|
||||
|
||||
# clear out current checkbox selection
|
||||
self.set_selected(set())
|
||||
|
||||
# result may be a redirect, e.g. to new export record. if so
|
||||
# then just return as-is
|
||||
if isinstance(result, HTTPFound):
|
||||
return result
|
||||
|
||||
# otherwise go back to invoice list
|
||||
return self.redirect(self.get_index_url())
|
||||
|
||||
def do_export(self, invoices):
|
||||
export = self.make_invoice_export(invoices)
|
||||
self.update_export_status(invoices)
|
||||
url = self.request.route_url('quickbooks.invoice_exports.view',
|
||||
uuid=export.uuid)
|
||||
return self.redirect(url)
|
||||
|
||||
def make_invoice_export_filename(self, invoices):
|
||||
raise NotImplementedError
|
||||
|
||||
def make_invoice_export(self, invoices):
|
||||
model = self.model
|
||||
|
||||
export = model.QuickbooksInvoiceExport()
|
||||
export.created_by = self.request.user
|
||||
export.record_count = len(invoices)
|
||||
export.filename = self.make_invoice_export_filename(invoices)
|
||||
self.Session.add(export)
|
||||
self.Session.flush()
|
||||
|
||||
path = export.filepath(self.rattail_config, filename=export.filename,
|
||||
makedirs=True)
|
||||
|
||||
try:
|
||||
self.write_invoice_export_file(export, path, invoices)
|
||||
|
||||
except Exception as error:
|
||||
log.warning("failed to write invoice export file for %s", export.uuid,
|
||||
exc_info=True)
|
||||
self.request.session.flash("Failed to write export file: {}".format(
|
||||
simple_error(error)), 'error')
|
||||
|
||||
return export
|
||||
|
||||
def write_invoice_export_file(self, export, path, invoices, progress=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def update_export_status(self, invoices):
|
||||
app = self.get_rattail_app()
|
||||
now = app.make_utc()
|
||||
for invoice in invoices:
|
||||
invoice.exported = now
|
||||
invoice.exported_by = self.request.user
|
||||
invoice.status_code = invoice.STATUS_EXPORTED
|
||||
for dist in invoice.distributions:
|
||||
if dist.status_code == dist.STATUS_EXPORTABLE:
|
||||
dist.status_code = dist.STATUS_EXPORTED
|
||||
|
||||
@classmethod
|
||||
def defaults(cls, config):
|
||||
cls._invoice_defaults(config)
|
||||
cls._defaults(config)
|
||||
|
||||
@classmethod
|
||||
def _invoice_defaults(cls, config):
|
||||
route_prefix = cls.get_route_prefix()
|
||||
url_prefix = cls.get_url_prefix()
|
||||
instance_url_prefix = cls.get_instance_url_prefix()
|
||||
permission_prefix = cls.get_permission_prefix()
|
||||
model_title_plural = cls.get_model_title_plural()
|
||||
|
||||
# nb. must fix permission group title
|
||||
config.add_tailbone_permission_group(permission_prefix,
|
||||
model_title_plural, overwrite=False)
|
||||
|
||||
# select
|
||||
config.add_route('{}.select'.format(route_prefix),
|
||||
'{}/select'.format(url_prefix))
|
||||
config.add_view(cls, attr='select',
|
||||
route_name='{}.select'.format(route_prefix),
|
||||
request_method='POST',
|
||||
permission='{}.export'.format(permission_prefix),
|
||||
renderer='json')
|
||||
|
||||
# deselect
|
||||
config.add_route('{}.deselect'.format(route_prefix),
|
||||
'{}/deselect'.format(url_prefix))
|
||||
config.add_view(cls, attr='deselect',
|
||||
route_name='{}.deselect'.format(route_prefix),
|
||||
request_method='POST',
|
||||
permission='{}.export'.format(permission_prefix),
|
||||
renderer='json')
|
||||
|
||||
# refresh
|
||||
config.add_route('{}.refresh'.format(route_prefix),
|
||||
'{}/refresh'.format(instance_url_prefix))
|
||||
config.add_view(cls, attr='refresh',
|
||||
route_name='{}.refresh'.format(route_prefix),
|
||||
request_method='POST',
|
||||
permission='{}.export'.format(permission_prefix))
|
||||
|
||||
# export
|
||||
config.add_tailbone_permission(permission_prefix,
|
||||
'{}.export'.format(permission_prefix),
|
||||
"Export Invoices")
|
||||
config.add_route('{}.export'.format(route_prefix),
|
||||
'{}/export'.format(url_prefix))
|
||||
config.add_view(cls, attr='export',
|
||||
route_name='{}.export'.format(route_prefix),
|
||||
request_method='POST',
|
||||
permission='{}.export'.format(permission_prefix))
|
||||
|
||||
|
||||
class InvoiceExportView(ExportMasterView):
|
||||
"""
|
||||
Master view for Quickbooks invoice exports.
|
||||
"""
|
||||
model_class = QuickbooksInvoiceExport
|
||||
route_prefix = 'quickbooks.invoice_exports'
|
||||
url_prefix = '/quickbooks/exports/invoice'
|
||||
downloadable = True
|
||||
delete_export_files = True
|
||||
|
||||
grid_columns = [
|
||||
'id',
|
||||
'created',
|
||||
'created_by',
|
||||
'filename',
|
||||
'record_count',
|
||||
]
|
||||
|
||||
form_fields = [
|
||||
'id',
|
||||
'created',
|
||||
'created_by',
|
||||
'record_count',
|
||||
'filename',
|
||||
]
|
||||
|
||||
|
||||
def defaults(config, **kwargs):
|
||||
base = globals()
|
||||
|
||||
ExportableInvoiceView = kwargs.get('ExportableInvoiceView', base['ExportableInvoiceView'])
|
||||
ExportableInvoiceView.defaults(config)
|
||||
|
||||
InvoiceExportView = kwargs.get('InvoiceExportView', base['InvoiceExportView'])
|
||||
InvoiceExportView.defaults(config)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
defaults(config)
|
53
tailbone_quickbooks/views/stores.py
Normal file
53
tailbone_quickbooks/views/stores.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2022 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Store views, w/ Quickbooks integration
|
||||
"""
|
||||
|
||||
from tailbone.views import ViewSupplement
|
||||
|
||||
|
||||
class StoreViewSupplement(ViewSupplement):
|
||||
"""
|
||||
Store view supplement for Quickbooks integration
|
||||
"""
|
||||
route_prefix = 'stores'
|
||||
|
||||
def get_grid_query(self, query):
|
||||
model = self.model
|
||||
return query.outerjoin(model.QuickbooksStore)
|
||||
|
||||
def configure_grid(self, g):
|
||||
model = self.model
|
||||
g.set_filter('quickbooks_location', model.QuickbooksStore.quickbooks_location)
|
||||
|
||||
def configure_form(self, f):
|
||||
f.append('quickbooks_location')
|
||||
|
||||
def get_version_child_classes(self):
|
||||
model = self.model
|
||||
return [model.QuickbooksStore]
|
||||
|
||||
|
||||
def includeme(config):
|
||||
StoreViewSupplement.defaults(config)
|
57
tailbone_quickbooks/views/vendors.py
Normal file
57
tailbone_quickbooks/views/vendors.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2022 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Vendor views, w/ Quickbooks integration
|
||||
"""
|
||||
|
||||
from tailbone.views import ViewSupplement
|
||||
|
||||
|
||||
class VendorViewSupplement(ViewSupplement):
|
||||
"""
|
||||
Vendor view supplement for Quickbooks integration
|
||||
"""
|
||||
route_prefix = 'vendors'
|
||||
|
||||
def get_grid_query(self, query):
|
||||
model = self.model
|
||||
return query.outerjoin(model.QuickbooksVendor)
|
||||
|
||||
def configure_grid(self, g):
|
||||
model = self.model
|
||||
g.set_filter('quickbooks_name', model.QuickbooksVendor.quickbooks_name)
|
||||
g.set_filter('quickbooks_bank_account', model.QuickbooksVendor.quickbooks_bank_account)
|
||||
g.set_filter('quickbooks_terms', model.QuickbooksVendor.quickbooks_terms)
|
||||
|
||||
def configure_form(self, f):
|
||||
f.append('quickbooks_name')
|
||||
f.append('quickbooks_bank_account')
|
||||
f.append('quickbooks_terms')
|
||||
|
||||
def get_version_child_classes(self):
|
||||
model = self.model
|
||||
return [model.QuickbooksVendor]
|
||||
|
||||
|
||||
def includeme(config):
|
||||
VendorViewSupplement.defaults(config)
|
Loading…
Add table
Add a link
Reference in a new issue